diff options
100 files changed, 21686 insertions, 0 deletions
diff --git a/3rdparty/mpg123/0050_all_libxmms-charset.patch b/3rdparty/mpg123/0050_all_libxmms-charset.patch new file mode 100644 index 0000000..94416dd --- /dev/null +++ b/3rdparty/mpg123/0050_all_libxmms-charset.patch @@ -0,0 +1,191 @@ +diff -Naur xmms-1.2.10-20041012/libxmms/charset.c xmms-1.2.10-20041012.convert/libxmms/charset.c +--- xmms-1.2.10-20041012/libxmms/charset.c 2004-10-13 01:03:03.258234924 -0700 ++++ xmms-1.2.10-20041012.convert/libxmms/charset.c 2004-10-24 23:49:42.083591275 -0700 +@@ -22,7 +22,6 @@ + + #include "charset.h" + +- + char* xmms_charset_get_current(void) + { + char *charset = getenv("CHARSET"); +@@ -38,6 +37,18 @@ + return charset; + } + ++static size_t utf16_strlen(const char *string) ++{ ++ size_t len = 0; ++ ++ if (!string) ++ return 0; ++ ++ while (*(string + len) != 0 || *(string + len + 1) != 0) ++ len += 2; ++ ++ return len; ++} + + #ifdef HAVE_ICONV + char* xmms_charset_convert(const char *string, size_t insize, char *from, char *to) +@@ -108,15 +119,55 @@ + { + if (!string) + return NULL; ++ + return xmms_charset_convert(string, strlen(string), "UTF-8", NULL); + } + ++char *xmms_charset_from_utf16(const unsigned char *string) ++{ ++ if (!string) ++ return NULL; ++ ++ return xmms_charset_convert(string, utf16_strlen(string), "UTF-16", NULL); ++} ++ ++char *xmms_charset_from_utf16be(const unsigned char *string) ++{ ++ if (!string) ++ return NULL; ++ ++ return xmms_charset_convert(string, utf16_strlen(string), "UTF-16BE", NULL); ++} ++ ++char* xmms_charset_from_latin1(const char *string) ++{ ++ char *to = xmms_charset_get_current(); ++ ++ if (!string) ++ return NULL; ++ ++ if (!strcmp(to, "UTF-8")) ++ return xmms_charset_convert(string, strlen(string), "ISO-8859-1", to); ++ else ++ return g_strdup(string); ++} ++ + #else + + char* xmms_charset_convert(const char *string, size_t insize, char *from, char *to) + { ++ if (!string) ++ return NULL; ++ + if (!strcmp(from, "UTF-8") && !to) + return xmms_charset_from_utf8(string); ++ ++ if (!strcmp(from, "UTF-16") && !to) ++ return xmms_charset_from_utf16(string); ++ ++ if (!strcmp(from, "UTF-16BE") && !to) ++ return xmms_charset_from_utf16be(string); ++ + return g_strdup(string); + } + +@@ -155,11 +206,83 @@ + return ascii; + } + ++static char* utf16_to_ascii(const unsigned char *utf16, int le) ++{ ++ char *ascii; ++ unsigned int i, len, c; ++ ++ if (!utf16) ++ return NULL; ++ ++ len = utf16_strlen(utf16) / 2 + 1; ++ ++ ascii = g_malloc(len + 1); ++ ++ for (i = 0, c = 0; i < len; i++) ++ { ++ guint16 uc; ++ int o = i << 1; ++ ++ if (le) ++ uc = *(utf16 + o) | *(utf16 + o + 1) << 8; ++ else ++ uc = *(utf16 + o) << 8 | *(utf16 + o + 1); ++ ++ /* Skip BOM and surrogate pairs */ ++ if (uc == 0xfeff || (uc >= 0xd800 && uc <= 0xdfff)) ++ continue; ++ ++ if (uc < 0x80) ++ ascii[c] = uc; ++ else ++ ascii[c] = '?'; ++ c++; ++ } ++ ++ ascii[c] = 0; ++ return ascii; ++} ++ ++char *xmms_charset_from_utf16(const unsigned char *string) ++{ ++ int le = FALSE; ++ guint16 bom; ++ ++ if (!string) ++ return NULL; ++ ++ bom = *string << 8 | *(string + 1); ++ ++ if (bom == 0xfffe) ++ le = TRUE; ++ else if (bom != 0xfeff) ++ return g_strdup(""); ++ ++ return utf16_to_ascii(string, le); ++} ++ ++char *xmms_charset_from_utf16be(const unsigned char *string) ++{ ++ if (!string) ++ return NULL; ++ ++ return utf16_to_ascii(string, FALSE); ++} ++ ++char* xmms_charset_from_latin1(const char *string) ++{ ++ if (!string) ++ return NULL; ++ ++ return g_strdup(string); ++} ++ + #endif + + char* xmms_charset_to_utf8(const char *string) + { + if (!string) + return NULL; ++ + return xmms_charset_convert(string, strlen(string), NULL, "UTF-8"); + } +diff -Naur xmms-1.2.10-20041012/libxmms/charset.h xmms-1.2.10-20041012.convert/libxmms/charset.h +--- xmms-1.2.10-20041012/libxmms/charset.h 2004-10-13 01:03:03.260234595 -0700 ++++ xmms-1.2.10-20041012.convert/libxmms/charset.h 2004-10-23 08:54:11.421220833 -0700 +@@ -5,11 +5,16 @@ + * + */ + ++#ifndef XMMS_CHARSET_H ++#define XMMS_CHARSET_H + + char* xmms_charset_get_current(void); + char* xmms_charset_convert(const char *string, size_t insize, char *from, char *to); + char* xmms_charset_to_utf8(const char *string); + char* xmms_charset_from_utf8(const char *string); ++char* xmms_charset_from_utf16(const unsigned char *string); ++char* xmms_charset_from_utf16be(const unsigned char *string); ++char* xmms_charset_from_latin1(const char *string); + +- ++#endif /* XMMS_CHARSET_H */ + diff --git a/3rdparty/mpg123/2011_all_mpg123-http-seek.patch b/3rdparty/mpg123/2011_all_mpg123-http-seek.patch new file mode 100644 index 0000000..67ab4f5 --- /dev/null +++ b/3rdparty/mpg123/2011_all_mpg123-http-seek.patch @@ -0,0 +1,201 @@ +diff -dPNur xmms-1.2.11/Input/mpg123/common.c xmms-1.2.11-new/Input/mpg123/common.c +--- xmms-1.2.11/Input/mpg123/common.c 2005-05-15 02:01:19.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/common.c 2007-11-24 23:52:01.000000000 +0100 +@@ -148,19 +148,34 @@ + int mpg123_stream_jump_to_frame(struct frame *fr, int frame) + { + if (!filept) +- return -1; +- mpg123_read_frame_init(); +- fseek(filept, frame * (fr->framesize + 4), SEEK_SET); +- mpg123_read_frame(fr); ++ { ++ unsigned long r; ++ ++ r = frame * (fr->framesize + 4); ++ mpg123_stream_close(); ++ mpg123_open_stream(mpg123_filename, -1, r); ++ } ++ else ++ { ++ mpg123_read_frame_init(); ++ fseek(filept, frame * (fr->framesize + 4), SEEK_SET); ++ mpg123_read_frame(fr); ++ } + return 0; + } + + int mpg123_stream_jump_to_byte(struct frame *fr, int byte) + { + if (!filept) +- return -1; +- fseek(filept, byte, SEEK_SET); +- mpg123_read_frame(fr); ++ { ++ mpg123_stream_close(); ++ mpg123_open_stream(mpg123_filename, -1, (unsigned long)byte); ++ } ++ else ++ { ++ fseek(filept, byte, SEEK_SET); ++ mpg123_read_frame(fr); ++ } + return 0; + } + +@@ -446,14 +461,14 @@ + return 1; + } + +-void mpg123_open_stream(char *bs_filenam, int fd) ++void mpg123_open_stream(char *bs_filenam, int fd, unsigned long range) + { + filept_opened = 1; + if (!strncasecmp(bs_filenam, "http://", 7)) + { + filept = NULL; +- mpg123_http_open(bs_filenam); + mpg123_info->filesize = 0; ++ mpg123_http_open(bs_filenam, range); + mpg123_info->network_stream = TRUE; + } + else +diff -dPNur xmms-1.2.11/Input/mpg123/http.c xmms-1.2.11-new/Input/mpg123/http.c +--- xmms-1.2.11/Input/mpg123/http.c 2007-11-16 22:51:24.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/http.c 2007-11-24 23:52:01.000000000 +0100 +@@ -50,6 +50,7 @@ + extern gboolean mpg123_stereo; + + static gboolean prebuffering, going, eof = FALSE; ++static unsigned long range; + static gint sock, rd_index, wr_index, buffer_length, prebuffer_length; + static guint64 buffer_read = 0; + static gchar *buffer; +@@ -326,7 +327,7 @@ + static void *http_buffer_loop(void *arg) + { + gchar line[1024], *user, *pass, *host, *filename, +- *status, *url, *temp, *file; ++ *status, *url, *temp, *temp2, *file; + gchar *chost; + gint cnt, written, error, port, cport; + socklen_t err_len; +@@ -495,15 +496,22 @@ + } + else + file = g_strconcat("/", filename, NULL); +- temp = g_strdup_printf("GET %s HTTP/1.0\r\n" ++ if (range) ++ { ++ temp2 = g_strdup_printf("Range: bytes=%lu-\r\n", range); ++ } else ++ temp2 = NULL; ++ temp = g_strdup_printf("GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: %s/%s\r\n" +- "%s%s%s%s\r\n", ++ "%s%s%s%s%s\r\n", + file, host, PACKAGE, VERSION, + proxy_auth ? proxy_auth : "", auth ? auth : "", + mpg123_cfg.cast_title_streaming ? "Icy-MetaData:1\r\n" : "", +- mpg123_cfg.use_udp_channel ? udpspace : ""); +- ++ mpg123_cfg.use_udp_channel ? udpspace : "", ++ range ? temp2 : ""); ++ ++ g_free(temp2); + g_free(file); + if(proxy_auth) + g_free(proxy_auth); +@@ -587,7 +595,9 @@ + #endif + /* udp_serverport = atoi (line + 20); */ + } +- ++ if (!strncasecmp(line, "content-length:", 15)) { ++ mpg123_info->filesize = atoi(line + 15); ++ } + } + else + { +@@ -719,7 +729,7 @@ + pthread_exit(NULL); + } + +-int mpg123_http_open(gchar * _url) ++int mpg123_http_open(gchar * _url, unsigned long rng) + { + gchar *url; + +@@ -735,6 +745,7 @@ + going = TRUE; + eof = FALSE; + buffer = g_malloc(buffer_length); ++ range = rng; + + pthread_create(&thread, NULL, http_buffer_loop, url); + +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.c xmms-1.2.11-new/Input/mpg123/mpg123.c +--- xmms-1.2.11/Input/mpg123/mpg123.c 2006-07-25 05:18:51.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.c 2007-11-24 23:52:01.000000000 +0100 +@@ -857,7 +857,7 @@ + + mpg123_read_frame_init(); + +- mpg123_open_stream(filename, -1); ++ mpg123_open_stream(filename, -1, 0); + if (mpg123_info->eof || !mpg123_read_frame(&fr)) + mpg123_info->eof = TRUE; + if (!mpg123_info->eof && mpg123_info->going) +@@ -906,7 +906,7 @@ + break; + } + +- if (!have_xing_header && strncasecmp(filename, "http://", 7)) ++ if(!have_xing_header && mpg123_info->filesize != 0) + mpg123_info->num_frames = mpg123_calc_numframes(&fr); + + memcpy(&fr, &temp_fr, sizeof(struct frame)); +@@ -918,11 +918,10 @@ + mpg123_lsf = fr.lsf; + mpg123_mpeg25 = fr.mpeg25; + mpg123_mode = fr.mode; +- ++ mpg123_length = mpg123_info->num_frames * mpg123_info->tpf * 1000; ++ + if (strncasecmp(filename, "http://", 7)) + { +- mpg123_length = +- mpg123_info->num_frames * mpg123_info->tpf * 1000; + if (!mpg123_title) + mpg123_title = get_song_title(NULL,filename); + } +@@ -930,7 +929,6 @@ + { + if (!mpg123_title) + mpg123_title = mpg123_http_get_title(filename); +- mpg123_length = -1; + } + mpg123_ip.set_info(mpg123_title, mpg123_length, + mpg123_bitrate * 1000, +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.h xmms-1.2.11-new/Input/mpg123/mpg123.h +--- xmms-1.2.11/Input/mpg123/mpg123.h 2006-07-24 00:32:44.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.h 2007-11-24 23:52:01.000000000 +0100 +@@ -176,7 +176,7 @@ + + /* ------ Declarations from "http.c" ------ */ + +-extern int mpg123_http_open(char *url); ++extern int mpg123_http_open(char *url, unsigned long rng); + int mpg123_http_read(gpointer data, gint length); + void mpg123_http_close(void); + char *mpg123_http_get_title(char * url); +@@ -188,7 +188,7 @@ + extern unsigned int mpg123_getbits(int); + extern unsigned int mpg123_getbits_fast(int); + +-extern void mpg123_open_stream(char *bs_filenam, int fd); ++extern void mpg123_open_stream(char *bs_filenam, int fd, unsigned long range); + extern int mpg123_head_check(unsigned long); + extern void mpg123_stream_close(void); + diff --git a/3rdparty/mpg123/2012_all_mpg123-id3convert.patch b/3rdparty/mpg123/2012_all_mpg123-id3convert.patch new file mode 100644 index 0000000..8c1b76b --- /dev/null +++ b/3rdparty/mpg123/2012_all_mpg123-id3convert.patch @@ -0,0 +1,41 @@ +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.c xmms-1.2.11-new/Input/mpg123/mpg123.c +--- xmms-1.2.11/Input/mpg123/mpg123.c 2007-11-24 23:53:33.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.c 2007-11-24 23:55:43.000000000 +0100 +@@ -2,6 +2,7 @@ + #include "id3_header.h" + #include "libxmms/configfile.h" + #include "libxmms/titlestring.h" ++#include "libxmms/charset.h" + #include <string.h> + #include <stdlib.h> + #include <pthread.h> +@@ -400,6 +401,14 @@ + return ext; + } + ++static char *convert_id3v1_field(const char *v1field, unsigned len) ++{ ++ char *tmp = g_strndup(v1field, len); ++ char *v2field = xmms_charset_from_latin1(g_strstrip(tmp)); ++ g_free(tmp); ++ return v2field; ++} ++ + /* + * Function id3v1_to_id3v2 (v1, v2) + * +@@ -411,10 +420,10 @@ + char *year; + struct id3v2tag_t *v2 = g_malloc0(sizeof (struct id3v2tag_t)); + +- v2->title = g_strstrip(g_strndup(v1->title, 30)); +- v2->artist = g_strstrip(g_strndup(v1->artist, 30)); +- v2->album = g_strstrip(g_strndup(v1->album, 30)); +- v2->comment = g_strstrip(g_strndup(v1->u.v1_0.comment, 30)); ++ v2->title = convert_id3v1_field(v1->title, 30); ++ v2->artist = convert_id3v1_field(v1->artist, 30); ++ v2->album = convert_id3v1_field(v1->album, 30); ++ v2->comment = convert_id3v1_field(v1->u.v1_0.comment, 30); + v2->genre = g_strstrip(g_strdup(mpg123_get_id3_genre(v1->genre))); + + year = g_strndup(v1->year, 4); diff --git a/3rdparty/mpg123/2013_all_mpg123-latin-id3.patch b/3rdparty/mpg123/2013_all_mpg123-latin-id3.patch new file mode 100644 index 0000000..b1d33cd --- /dev/null +++ b/3rdparty/mpg123/2013_all_mpg123-latin-id3.patch @@ -0,0 +1,128 @@ +diff -Naur xmms-1.2.10-20041012/Input/mpg123/Makefile.am xmms-1.2.10-20041012.id3latin/Input/mpg123/Makefile.am +--- xmms-1.2.10-20041012/Input/mpg123/Makefile.am 2004-10-13 01:03:03.186246768 -0700 ++++ xmms-1.2.10-20041012.id3latin/Input/mpg123/Makefile.am 2004-10-23 08:52:23.370409147 -0700 +@@ -15,7 +15,7 @@ + dxhead.c dxhead.h \ + id3.c id3.h \ + id3_frame.c id3_frame_content.c id3_frame_text.c id3_frame_url.c \ +-id3_header.h id3_tag.c unicode.c ++id3_header.h id3_tag.c + + if ARCH_X86 + +diff -Naur xmms-1.2.10-20041012/Input/mpg123/id3_frame_text.c xmms-1.2.10-20041012.id3latin/Input/mpg123/id3_frame_text.c +--- xmms-1.2.10-20041012/Input/mpg123/id3_frame_text.c 2004-10-13 01:03:03.201244300 -0700 ++++ xmms-1.2.10-20041012.id3latin/Input/mpg123/id3_frame_text.c 2004-10-23 09:15:29.117825260 -0700 +@@ -60,13 +60,13 @@ + switch (encoding) + { + case ID3_ENCODING_ISO_8859_1: +- return g_strdup(text); ++ return xmms_charset_from_latin1(text); + case ID3_ENCODING_UTF8: + return xmms_charset_from_utf8(text); + case ID3_ENCODING_UTF16: +- return convert_from_utf16(text); ++ return xmms_charset_from_utf16(text); + case ID3_ENCODING_UTF16BE: +- return convert_from_utf16be(text); ++ return xmms_charset_from_utf16be(text); + default: + return NULL; + } +diff -Naur xmms-1.2.10-20041012/Input/mpg123/unicode.c xmms-1.2.10-20041012.id3latin/Input/mpg123/unicode.c +--- xmms-1.2.10-20041012/Input/mpg123/unicode.c 2004-10-13 01:03:03.215241997 -0700 ++++ xmms-1.2.10-20041012.id3latin/Input/mpg123/unicode.c 1969-12-31 16:00:00.000000000 -0800 +@@ -1,92 +0,0 @@ +-/* +- * Copyright (C) 2004 Haavard Kvaalen <havardk@xmms.org> +- * +- * Licensed under GNU GPL version 2. +- * +- */ +-#include "config.h" +- +-#include <stdlib.h> +-#include <glib.h> +- +-#include "libxmms/charset.h" +- +-size_t utf16_strlen(const char *string) +-{ +- size_t len = 0; +- +- while (*(string + len) != 0 || *(string + len + 1) != 0) +- len += 2; +- +- return len; +-} +- +-#ifdef HAVE_ICONV +- +-char *convert_from_utf16(const unsigned char *utf16) +-{ +- return xmms_charset_convert(utf16, utf16_strlen(utf16), "UTF-16", NULL); +-} +- +-char *convert_from_utf16be(const unsigned char *utf16) +-{ +- return xmms_charset_convert(utf16, utf16_strlen(utf16), "UTF-16BE", NULL); +-} +- +- +-#else +- +- +-static char* to_ascii(const unsigned char *utf16, int le) +-{ +- char *ascii; +- unsigned int i, len, c; +- +- len = utf16_strlen(utf16) / 2 + 1; +- +- ascii = g_malloc(len + 1); +- +- for (i = 0, c = 0; i < len; i++) +- { +- guint16 uc; +- int o = i << 1; +- +- if (le) +- uc = *(utf16 + o) | *(utf16 + o + 1) << 8; +- else +- uc = *(utf16 + o) << 8 | *(utf16 + o + 1); +- +- /* Skip BOM and surrogate pairs */ +- if (uc == 0xfeff || (uc >= 0xd800 && uc <= 0xdfff)) +- continue; +- +- if (uc < 0x80) +- ascii[c] = uc; +- else +- ascii[c] = '?'; +- c++; +- } +- +- ascii[c] = 0; +- return ascii; +-} +- +-char *convert_from_utf16(const unsigned char *utf16) +-{ +- int le = FALSE; +- guint16 bom = *utf16 << 8 | *(utf16 + 1); +- +- if (bom == 0xfffe) +- le = TRUE; +- else if (bom != 0xfeff) +- return g_strdup(""); +- +- return to_ascii(utf16, le); +-} +- +-char *convert_from_utf16be(const unsigned char *utf16) +-{ +- return to_ascii(utf16, FALSE); +-} +- +-#endif diff --git a/3rdparty/mpg123/2014_all_mpg123-encode-override.patch b/3rdparty/mpg123/2014_all_mpg123-encode-override.patch new file mode 100644 index 0000000..5c27f66 --- /dev/null +++ b/3rdparty/mpg123/2014_all_mpg123-encode-override.patch @@ -0,0 +1,130 @@ +diff -dPNur xmms-1.2.11/Input/mpg123/configure.c xmms-1.2.11-new/Input/mpg123/configure.c +--- xmms-1.2.11/Input/mpg123/configure.c 2005-05-15 02:01:19.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/configure.c 2007-11-24 23:57:29.000000000 +0100 +@@ -27,6 +27,7 @@ + static GtkWidget *streaming_proxy_hbox, *streaming_proxy_auth_hbox, *streaming_save_dirbrowser; + static GtkWidget *streaming_save_hbox, *title_id3_box, *title_tag_desc; + static GtkWidget *title_override, *title_id3_entry, *title_id3v2_disable; ++static GtkWidget *id3v2_encoding_override, *id3v2_encoding_box, *encoding_entry; + + MPG123Config mpg123_cfg; + +@@ -105,6 +106,8 @@ + mpg123_cfg.disable_id3v2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(title_id3v2_disable)); + g_free(mpg123_cfg.id3_format); + mpg123_cfg.id3_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(title_id3_entry))); ++ mpg123_cfg.id3v2_encoding_override = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(id3v2_encoding_override)); ++ mpg123_cfg.id3v2_default_encoding = g_strdup(gtk_entry_get_text(GTK_ENTRY(encoding_entry))); + + filename = g_strconcat(g_get_home_dir(), "/.xmms/config", NULL); + cfg = xmms_cfg_open_file(filename); +@@ -134,6 +137,8 @@ + xmms_cfg_write_boolean(cfg, "MPG123", "title_override", mpg123_cfg.title_override); + xmms_cfg_write_boolean(cfg, "MPG123", "disable_id3v2", mpg123_cfg.disable_id3v2); + xmms_cfg_write_string(cfg, "MPG123", "id3_format", mpg123_cfg.id3_format); ++ xmms_cfg_write_boolean(cfg, "MPG123", "id3v2_encoding_override", mpg123_cfg.id3v2_encoding_override); ++ xmms_cfg_write_string(cfg, "MPG123", "id3v2_default_encoding", mpg123_cfg.id3v2_default_encoding); + xmms_cfg_write_int(cfg, "MPG123", "detect_by", mpg123_cfg.detect_by); + #ifdef USE_SIMD + xmms_cfg_write_int(cfg, "MPG123", "default_synth", mpg123_cfg.default_synth); +@@ -212,6 +217,13 @@ + gtk_widget_set_sensitive(title_tag_desc, override); + } + ++static void id3v2_encoding_override_cb(GtkWidget * w, gpointer data) ++{ ++ gboolean override; ++ override = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(id3v2_encoding_override)); ++ gtk_widget_set_sensitive(id3v2_encoding_box, override); ++} ++ + static void configure_destroy(GtkWidget * w, gpointer data) + { + if (streaming_save_dirbrowser) +@@ -230,6 +242,7 @@ + GtkWidget *streaming_save_label, *streaming_save_browse; + GtkWidget *streaming_cast_frame, *streaming_cast_vbox; + GtkWidget *title_frame, *title_id3_vbox, *title_id3_label; ++ GtkWidget *title_id3_label2; + GtkWidget *bbox, *ok, *cancel; + + char *temp; +@@ -576,6 +589,23 @@ + title_tag_desc = xmms_titlestring_descriptions("pafFetnygc", 2); + gtk_widget_set_sensitive(title_tag_desc, mpg123_cfg.title_override); + gtk_box_pack_start(GTK_BOX(title_id3_vbox), title_tag_desc, FALSE, FALSE, 0); ++ ++ id3v2_encoding_override = gtk_check_button_new_with_label(_("Override default ID3V2 encoding")); ++ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(id3v2_encoding_override), mpg123_cfg.id3v2_encoding_override); ++ gtk_signal_connect(GTK_OBJECT(id3v2_encoding_override), "clicked", id3v2_encoding_override_cb, NULL); ++ gtk_box_pack_start(GTK_BOX(title_id3_vbox), id3v2_encoding_override, FALSE, FALSE, 0); ++ ++ id3v2_encoding_box = gtk_hbox_new(FALSE, 5); ++ gtk_widget_set_sensitive(id3v2_encoding_box, mpg123_cfg.id3v2_encoding_override); ++ gtk_box_pack_start(GTK_BOX(title_id3_vbox), id3v2_encoding_box, FALSE, FALSE, 0); ++ ++ title_id3_label2 = gtk_label_new(_("Encoding name:")); ++ gtk_box_pack_start(GTK_BOX(id3v2_encoding_box), title_id3_label2, FALSE, FALSE, 0); ++ ++ encoding_entry = gtk_entry_new(); ++ gtk_entry_set_text(GTK_ENTRY(encoding_entry), mpg123_cfg.id3v2_default_encoding); ++ gtk_box_pack_start(GTK_BOX(id3v2_encoding_box), encoding_entry, TRUE, TRUE, 0); ++ + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), title_frame, gtk_label_new(_("Title"))); + + bbox = gtk_hbutton_box_new(); +diff -dPNur xmms-1.2.11/Input/mpg123/id3_frame_text.c xmms-1.2.11-new/Input/mpg123/id3_frame_text.c +--- xmms-1.2.11/Input/mpg123/id3_frame_text.c 2007-11-24 23:57:15.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/id3_frame_text.c 2007-11-24 23:57:29.000000000 +0100 +@@ -29,6 +29,8 @@ + + #include "libxmms/charset.h" + ++/* For extern mpg123_cfg */ ++#include "mpg123.h" + + /* Get size of string in bytes including null. */ + guint id3_string_size(guint8 encoding, const char* text) +@@ -60,6 +62,9 @@ + switch (encoding) + { + case ID3_ENCODING_ISO_8859_1: ++ if (mpg123_cfg.id3v2_encoding_override) { ++ return xmms_charset_convert(text, strlen(text), mpg123_cfg.id3v2_default_encoding, NULL); ++ } + return xmms_charset_from_latin1(text); + case ID3_ENCODING_UTF8: + return xmms_charset_from_utf8(text); +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.c xmms-1.2.11-new/Input/mpg123/mpg123.c +--- xmms-1.2.11/Input/mpg123/mpg123.c 2007-11-24 23:56:41.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.c 2007-11-24 23:57:29.000000000 +0100 +@@ -171,6 +171,7 @@ + mpg123_cfg.use_udp_channel = FALSE; + mpg123_cfg.title_override = FALSE; + mpg123_cfg.disable_id3v2 = FALSE; ++ mpg123_cfg.id3v2_encoding_override = FALSE; + mpg123_cfg.detect_by = DETECT_EXTENSION; + mpg123_cfg.default_synth = SYNTH_AUTO; + +@@ -199,6 +200,9 @@ + xmms_cfg_read_boolean(cfg, "MPG123", "disable_id3v2", &mpg123_cfg.disable_id3v2); + if (!xmms_cfg_read_string(cfg, "MPG123", "id3_format", &mpg123_cfg.id3_format)) + mpg123_cfg.id3_format = g_strdup("%p - %t"); ++ xmms_cfg_read_boolean(cfg, "MPG123", "id3v2_encoding_override", &mpg123_cfg.id3v2_encoding_override); ++ if (!xmms_cfg_read_string(cfg, "MPG123", "id3v2_default_encoding", &mpg123_cfg.id3v2_default_encoding)) ++ mpg123_cfg.id3_format = g_strdup("ISO-8859-1"); + xmms_cfg_read_int(cfg, "MPG123", "detect_by", &mpg123_cfg.detect_by); + xmms_cfg_read_int(cfg, "MPG123", "default_synth", &mpg123_cfg.default_synth); + +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.h xmms-1.2.11-new/Input/mpg123/mpg123.h +--- xmms-1.2.11/Input/mpg123/mpg123.h 2007-11-24 23:53:33.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.h 2007-11-24 23:57:29.000000000 +0100 +@@ -159,6 +159,8 @@ + gboolean use_udp_channel; + gchar *id3_format; + gboolean title_override, disable_id3v2; ++ gboolean id3v2_encoding_override; ++ gchar *id3v2_default_encoding; + int detect_by; + int default_synth; + } diff --git a/3rdparty/mpg123/2015_all_mpg123-id3v2edit.patch b/3rdparty/mpg123/2015_all_mpg123-id3v2edit.patch new file mode 100644 index 0000000..b1d47a2 --- /dev/null +++ b/3rdparty/mpg123/2015_all_mpg123-id3v2edit.patch @@ -0,0 +1,2247 @@ +diff -dPNur xmms-1.2.11/Input/mpg123/common.c xmms-1.2.11-new/Input/mpg123/common.c +--- xmms-1.2.11/Input/mpg123/common.c 2007-11-24 23:53:33.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/common.c 2007-11-24 23:58:41.000000000 +0100 +@@ -303,8 +303,8 @@ + mpg123_id3v2_destroy(tag); + id3_close(id3d); + } +- g_free(id3buf); + ++ g_free(id3buf); + return TRUE; + } + +diff -dPNur xmms-1.2.11/Input/mpg123/fileinfo.c xmms-1.2.11-new/Input/mpg123/fileinfo.c +--- xmms-1.2.11/Input/mpg123/fileinfo.c 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/fileinfo.c 2007-11-24 23:58:41.000000000 +0100 +@@ -27,42 +27,96 @@ + #include <gdk/gdkkeysyms.h> + #include "mpg123.h" + ++#define MAX_STR_LEN 100 ++#define MAX_ENTRY_LEN2 1023 ++ + static GtkWidget *window = NULL; +-static GtkWidget *filename_entry, *id3_frame; +-static GtkWidget *title_entry, *artist_entry, *album_entry, *year_entry; +-static GtkWidget *tracknum_entry, *comment_entry, *genre_combo; ++static GtkWidget *notebook = NULL; ++static GtkWidget *filename_entry, *id3v1_frame, *id3v2_frame; ++static GtkWidget *v1_checkbox, *v2_checkbox; ++static GtkWidget *v1_title_entry, *v1_artist_entry, *v1_album_entry, *v1_year_entry, *v1_tracknum_entry, *v1_comment_entry; ++static GtkWidget *v2_title_entry, *v2_artist_entry, *v2_album_entry, *v2_year_entry, *v2_tracknum_entry, *v2_comment_entry, ++ *v2_composer_entry, *v2_orig_artist_entry, *v2_url_entry, *v2_encoded_by_entry; ++static GtkWidget *v1_genre_combo, *v2_genre_combo; + static GtkWidget *mpeg_level, *mpeg_bitrate, *mpeg_samplerate, *mpeg_flags; + static GtkWidget *mpeg_fileinfo; + ++static GPtrArray *v1_labels_list = NULL, *v2_labels_list = NULL; // TODO: Where will these be freed? + static GList *genre_list; + struct genre_item { + const char *name; + int id; + }; +-static int current_genre; ++static int v1_current_genre; ++static int v2_current_genre; + static char *current_filename; + + extern char *mpg123_filename; + extern int mpg123_bitrate, mpg123_frequency, mpg123_layer, mpg123_lsf, mpg123_mode; + extern gboolean mpg123_stereo, mpg123_mpeg25; + +-#define MAX_STR_LEN 100 +- +-static void label_set_text(GtkWidget * label, char *str, ...) ++static void label_set_text(GtkWidget * label, const char *str, ...) + G_GNUC_PRINTF(2, 3); + +-static void set_entry_tag(GtkEntry * entry, char * tag, int length) ++static void set_entry_tag_v1(GtkEntry * entry, const char * tag, int length) + { + char *text = g_strchomp(g_strndup(tag, length)); + gtk_entry_set_text(entry, text); + g_free(text); + } + +-static void get_entry_tag(GtkEntry * entry, char * tag, int length) ++static void get_entry_tag_v1(GtkEntry * entry, char * tag, int length) + { + strncpy(tag, gtk_entry_get_text(entry), length); + } + ++void copy_entry_tag_v1(GtkEntry * src, GtkEntry * dest, int length) ++{ ++ set_entry_tag_v1(dest, gtk_entry_get_text(src), length); ++ return; ++} ++ ++static void set_entry_tag_v2(GtkEntry * entry, struct id3_tag* id3, guint32 frame_type) ++{ ++ struct id3_frame* frame; ++ ++ frame = id3_get_frame(id3, frame_type, 1); ++ if (frame != NULL) ++ { ++ char *text, *url, *comment; ++ ++ text = id3_get_text(frame); ++ if (text != NULL) ++ { ++ gtk_entry_set_text(entry, text); ++ g_free(text); ++ return; ++ } ++ ++ url = id3_get_url(frame); ++ if (url != NULL) ++ { ++ gtk_entry_set_text(entry, url); ++ g_free(url); ++ return; ++ } ++ ++ comment = id3_get_comment(frame); ++ if (comment != NULL) ++ { ++ gtk_entry_set_text(entry, comment); ++ g_free(url); ++ return; ++ } ++ } ++} ++ ++void copy_entry_tag_v2(GtkEntry * src, GtkEntry * dest) ++{ ++ gtk_entry_set_text(dest, gtk_entry_get_text(src)); ++ return; ++} ++ + static int genre_find_index(GList *genre_list, int id) + { + int idx = 0; +@@ -74,6 +128,24 @@ + idx++; + genre_list = genre_list->next; + } ++ if (!genre_list) ++ return 0; ++ return idx; ++} ++ ++static int genre_find_index_str(GList *genre_list, const char* str) ++{ ++ int idx = 0; ++ while (genre_list) ++ { ++ struct genre_item *item = genre_list->data; ++ if (strcmp(item->name, str) == 0) ++ break; ++ idx++; ++ genre_list = genre_list->next; ++ } ++ if (!genre_list) ++ return 0; + return idx; + } + +@@ -83,9 +155,9 @@ + return strcasecmp(ga->name, gb->name); + } + +-static void save_cb(GtkWidget * w, gpointer data) ++static void remove_id3v1(void) + { +- int fd; ++ int fd, len; + struct id3v1tag_t tag; + char *msg = NULL; + +@@ -94,71 +166,36 @@ + + if ((fd = open(current_filename, O_RDWR)) != -1) + { +- int tracknum; +- +- lseek(fd, -128, SEEK_END); ++ len = lseek(fd, -128, SEEK_END); + read(fd, &tag, sizeof (struct id3v1tag_t)); + + if (!strncmp(tag.tag, "TAG", 3)) +- lseek(fd, -128, SEEK_END); +- else +- lseek(fd, 0, SEEK_END); +- tag.tag[0] = 'T'; +- tag.tag[1] = 'A'; +- tag.tag[2] = 'G'; +- get_entry_tag(GTK_ENTRY(title_entry), tag.title, 30); +- get_entry_tag(GTK_ENTRY(artist_entry), tag.artist, 30); +- get_entry_tag(GTK_ENTRY(album_entry), tag.album, 30); +- get_entry_tag(GTK_ENTRY(year_entry), tag.year, 4); +- tracknum = atoi(gtk_entry_get_text(GTK_ENTRY(tracknum_entry))); +- if (tracknum > 0) + { +- get_entry_tag(GTK_ENTRY(comment_entry), +- tag.u.v1_1.comment, 28); +- tag.u.v1_1.__zero = 0; +- tag.u.v1_1.track_number = MIN(tracknum, 255); ++ if (ftruncate(fd, len)) ++ msg = g_strdup_printf(_("%s\n" ++ "Unable to truncate file: %s"), ++ _("Couldn't remove tag!"), ++ strerror(errno)); + } +- else +- get_entry_tag(GTK_ENTRY(comment_entry), +- tag.u.v1_0.comment, 30); +- tag.genre = current_genre; +- if (write(fd, &tag, sizeof (tag)) != sizeof (tag)) +- msg = g_strdup_printf(_("%s\nUnable to write to file: %s"), +- _("Couldn't write tag!"), +- strerror(errno)); + close(fd); + } + else + msg = g_strdup_printf(_("%s\nUnable to open file: %s"), +- _("Couldn't write tag!"), ++ _("Couldn't remove tag!"), + strerror(errno)); + if (msg) + { +- GtkWidget *mwin = xmms_show_message(_("File Info"), msg, +- _("OK"), FALSE, NULL, NULL); ++ GtkWidget *mwin = xmms_show_message(_("File Info"), msg, _("OK"), ++ FALSE, NULL, NULL); + gtk_window_set_transient_for(GTK_WINDOW(mwin), + GTK_WINDOW(window)); + g_free(msg); + } +- else +- gtk_widget_destroy(window); +-} +- +-static void label_set_text(GtkWidget * label, char *str, ...) +-{ +- va_list args; +- char tempstr[MAX_STR_LEN]; +- +- va_start(args, str); +- g_vsnprintf(tempstr, MAX_STR_LEN, str, args); +- va_end(args); +- +- gtk_label_set_text(GTK_LABEL(label), tempstr); + } + +-static void remove_id3_cb(GtkWidget * w, gpointer data) ++static void save_cb(GtkWidget * w, gpointer data) + { +- int fd, len; ++ int fd; + struct id3v1tag_t tag; + char *msg = NULL; + +@@ -167,36 +204,112 @@ + + if ((fd = open(current_filename, O_RDWR)) != -1) + { +- len = lseek(fd, -128, SEEK_END); +- read(fd, &tag, sizeof (struct id3v1tag_t)); ++ if (!GTK_TOGGLE_BUTTON(v1_checkbox)->active) { ++ /* Try to save id3v1 tag */ ++ int tracknum; + +- if (!strncmp(tag.tag, "TAG", 3)) +- { +- if (ftruncate(fd, len)) +- msg = g_strdup_printf( +- _("%s\n" +- "Unable to truncate file: %s"), +- _("Couldn't remove tag!"), +- strerror(errno)); ++ lseek(fd, -128, SEEK_END); ++ read(fd, &tag, sizeof (struct id3v1tag_t)); ++ ++ if (!strncmp(tag.tag, "TAG", 3)) ++ lseek(fd, -128, SEEK_END); ++ else ++ lseek(fd, 0, SEEK_END); ++ tag.tag[0] = 'T'; ++ tag.tag[1] = 'A'; ++ tag.tag[2] = 'G'; ++ get_entry_tag_v1(GTK_ENTRY(v1_title_entry), tag.title, 30); ++ get_entry_tag_v1(GTK_ENTRY(v1_artist_entry), tag.artist, 30); ++ get_entry_tag_v1(GTK_ENTRY(v1_album_entry), tag.album, 30); ++ get_entry_tag_v1(GTK_ENTRY(v1_year_entry), tag.year, 4); ++ tracknum = atoi(gtk_entry_get_text(GTK_ENTRY(v1_tracknum_entry))); ++ if (tracknum > 0) ++ { ++ get_entry_tag_v1(GTK_ENTRY(v1_comment_entry), tag.u.v1_1.comment, 28); ++ tag.u.v1_1.__zero = 0; ++ tag.u.v1_1.track_number = MIN(tracknum, 255); ++ } ++ else ++ get_entry_tag_v1(GTK_ENTRY(v1_comment_entry), ++ tag.u.v1_0.comment, 30); ++ tag.genre = v1_current_genre; ++ if (write(fd, &tag, sizeof (tag)) != sizeof (tag)) ++ msg = g_strdup_printf(_("%s\nUnable to write to file: %s"), ++ _("Couldn't write tag!"), ++ strerror(errno)); ++ } else { ++ /* Remove the id3v1 tag from the file */ ++ remove_id3v1(); + } +- else +- msg = strdup(_("No tag to remove!")); +- close(fd); ++ ++ if (!GTK_TOGGLE_BUTTON(v2_checkbox)->active) { ++ struct id3_tag* id3; ++ ++ lseek(fd, SEEK_SET, 0); ++ id3 = id3_open_fd(fd, 0); ++ if (id3 == NULL) ++ id3 = id3_new(); ++ ++ if (id3 != NULL) ++ { ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TIT2), gtk_entry_get_text(GTK_ENTRY(v2_title_entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TPE1), gtk_entry_get_text(GTK_ENTRY(v2_artist_entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TALB), gtk_entry_get_text(GTK_ENTRY(v2_album_entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TYER), gtk_entry_get_text(GTK_ENTRY(v2_year_entry))); ++ id3_set_comment(id3_get_or_add_frame(id3, ID3_COMM), gtk_entry_get_text(GTK_ENTRY(v2_comment_entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TRCK), gtk_entry_get_text(GTK_ENTRY(v2_tracknum_entry))); ++ if (v2_current_genre != 0xff) ++ { ++ /* Essentially the same behavior as Winamp2's ID3v2 tagger */ ++ char genre[255]; ++ snprintf(genre, sizeof(genre), "(%d)%s", ++ v2_current_genre, ++ gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(v2_genre_combo)->entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TCON), genre); ++ } ++ else ++ { ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TCON), gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(v2_genre_combo)->entry))); ++ } ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TCOM), gtk_entry_get_text(GTK_ENTRY(v2_composer_entry))); ++ id3_set_url(id3_get_or_add_frame(id3, ID3_WCOM), gtk_entry_get_text(GTK_ENTRY(v2_url_entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TOPE), gtk_entry_get_text(GTK_ENTRY(v2_orig_artist_entry))); ++ id3_set_text(id3_get_or_add_frame(id3, ID3_TENC), gtk_entry_get_text(GTK_ENTRY(v2_encoded_by_entry))); ++ ++ id3_write_tag_filename(id3, current_filename); ++ } ++ ++ } else { ++ id3_remove_tag_filename(current_filename); ++ } ++ ++ if (fd) ++ close(fd); + } + else + msg = g_strdup_printf(_("%s\nUnable to open file: %s"), +- _("Couldn't remove tag!"), ++ _("Couldn't write tag!"), + strerror(errno)); + if (msg) + { +- GtkWidget *mwin = xmms_show_message(_("File Info"), msg, +- _("OK"), FALSE, NULL, NULL); ++ GtkWidget *mwin = xmms_show_message(_("File Info"), msg, _("OK"), ++ FALSE, NULL, NULL); + gtk_window_set_transient_for(GTK_WINDOW(mwin), + GTK_WINDOW(window)); + g_free(msg); + } +- else +- gtk_widget_destroy(window); ++} ++ ++static void label_set_text(GtkWidget * label, const char *str, ...) ++{ ++ va_list args; ++ char tempstr[MAX_STR_LEN]; ++ ++ va_start(args, str); ++ g_vsnprintf(tempstr, MAX_STR_LEN, str, args); ++ va_end(args); ++ ++ gtk_label_set_text(GTK_LABEL(label), tempstr); + } + + static void set_mpeg_level_label(gboolean mpeg25, int lsf, int layer) +@@ -219,28 +332,141 @@ + + static void file_info_http(char *filename) + { +- gtk_widget_set_sensitive(id3_frame, FALSE); ++ gtk_widget_set_sensitive(id3v1_frame, FALSE); ++ gtk_widget_set_sensitive(id3v2_frame, FALSE); + if (mpg123_filename && !strcmp(filename, mpg123_filename) && + mpg123_bitrate != 0) + { +- set_mpeg_level_label(mpg123_mpeg25, mpg123_lsf, mpg123_layer); ++ set_mpeg_level_label(mpg123_mpeg25, mpg123_lsf, ++ mpg123_layer); + label_set_text(mpeg_bitrate, _("Bitrate: %d kb/s"), +- mpg123_bitrate); ++ mpg123_bitrate); + label_set_text(mpeg_samplerate, _("Samplerate: %d Hz"), +- mpg123_frequency); ++ mpg123_frequency); + label_set_text(mpeg_flags, "%s", +- channel_mode_name(mpg123_mode)); ++ channel_mode_name(mpg123_mode)); + } + } + +-static void genre_selected(GtkList *list, GtkWidget *w, gpointer data) ++void copy_v2_to_v1_cb(GtkButton *button, gpointer user_data) ++{ ++ copy_entry_tag_v1(GTK_ENTRY(v2_title_entry), GTK_ENTRY(v1_title_entry), 30); ++ copy_entry_tag_v1(GTK_ENTRY(v2_artist_entry), GTK_ENTRY(v1_artist_entry), 30); ++ copy_entry_tag_v1(GTK_ENTRY(v2_album_entry), GTK_ENTRY(v1_album_entry), 30); ++ copy_entry_tag_v1(GTK_ENTRY(v2_year_entry), GTK_ENTRY(v1_year_entry), 4); ++ copy_entry_tag_v1(GTK_ENTRY(v2_comment_entry), GTK_ENTRY(v1_comment_entry), 30); ++ copy_entry_tag_v1(GTK_ENTRY(v2_tracknum_entry), GTK_ENTRY(v1_tracknum_entry), 3); ++ ++ gtk_list_select_item(GTK_LIST(GTK_COMBO(v1_genre_combo)->list), genre_find_index(genre_list, v2_current_genre)); ++ return; ++} ++ ++void copy_v1_to_v2_cb(GtkButton *button, gpointer user_data) ++{ ++ copy_entry_tag_v2(GTK_ENTRY(v1_title_entry), GTK_ENTRY(v2_title_entry)); ++ copy_entry_tag_v2(GTK_ENTRY(v1_artist_entry), GTK_ENTRY(v2_artist_entry)); ++ copy_entry_tag_v2(GTK_ENTRY(v1_album_entry), GTK_ENTRY(v2_album_entry)); ++ copy_entry_tag_v2(GTK_ENTRY(v1_year_entry), GTK_ENTRY(v2_year_entry)); ++ copy_entry_tag_v2(GTK_ENTRY(v1_comment_entry), GTK_ENTRY(v2_comment_entry)); ++ copy_entry_tag_v2(GTK_ENTRY(v1_tracknum_entry), GTK_ENTRY(v2_tracknum_entry)); ++ ++ gtk_list_select_item(GTK_LIST(GTK_COMBO(v2_genre_combo)->list), genre_find_index(genre_list, v1_current_genre)); ++ return; ++} ++ ++void v1_toggle_cb (GtkWidget *widget, gpointer data) ++{ ++ int i = 0; ++ if (GTK_TOGGLE_BUTTON (widget)->active) ++ { ++ // If control reaches here, the toggle button is down ++ // Gray out labels ++ for (i = 0; i < v1_labels_list->len; i++) { ++ gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v1_labels_list, i) ), FALSE); ++ } ++ gtk_widget_set_sensitive(v1_title_entry, FALSE); ++ gtk_widget_set_sensitive(v1_artist_entry, FALSE); ++ gtk_widget_set_sensitive(v1_album_entry, FALSE); ++ gtk_widget_set_sensitive(v1_year_entry, FALSE); ++ gtk_widget_set_sensitive(v1_tracknum_entry, FALSE); ++ gtk_widget_set_sensitive(v1_comment_entry, FALSE); ++ gtk_widget_set_sensitive(v1_genre_combo, FALSE); ++ } else { ++ ++ // If control reaches here, the toggle button is up ++ // Enable labels ++ for (i = 0; i < v1_labels_list->len; i++) { ++ gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v1_labels_list, i) ), TRUE); ++ } ++ gtk_widget_set_sensitive(v1_title_entry, TRUE); ++ gtk_widget_set_sensitive(v1_artist_entry, TRUE); ++ gtk_widget_set_sensitive(v1_album_entry, TRUE); ++ gtk_widget_set_sensitive(v1_year_entry, TRUE); ++ gtk_widget_set_sensitive(v1_tracknum_entry, TRUE); ++ gtk_widget_set_sensitive(v1_comment_entry, TRUE); ++ gtk_widget_set_sensitive(v1_genre_combo, TRUE); ++ } ++} ++ ++void v2_toggle_cb (GtkWidget *widget, gpointer data) ++{ ++ int i = 0; ++ if (GTK_TOGGLE_BUTTON (widget)->active) ++ { ++ // If control reaches here, the toggle button is down ++ // Gray out labels ++ for (i = 0; i < v2_labels_list->len; i++) { ++ gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v2_labels_list, i) ), FALSE); ++ } ++ gtk_widget_set_sensitive(v2_title_entry, FALSE); ++ gtk_widget_set_sensitive(v2_artist_entry, FALSE); ++ gtk_widget_set_sensitive(v2_album_entry, FALSE); ++ gtk_widget_set_sensitive(v2_year_entry, FALSE); ++ gtk_widget_set_sensitive(v2_tracknum_entry, FALSE); ++ gtk_widget_set_sensitive(v2_comment_entry, FALSE); ++ gtk_widget_set_sensitive(v2_composer_entry, FALSE); ++ gtk_widget_set_sensitive(v2_orig_artist_entry, FALSE); ++ gtk_widget_set_sensitive(v2_url_entry, FALSE); ++ gtk_widget_set_sensitive(v2_encoded_by_entry, FALSE); ++ gtk_widget_set_sensitive(v2_genre_combo, FALSE); ++ } else { ++ ++ // If control reaches here, the toggle button is up ++ // Enable labels ++ for (i = 0; i < v2_labels_list->len; i++) { ++ gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v2_labels_list, i) ), TRUE); ++ } ++ gtk_widget_set_sensitive(v2_title_entry, TRUE); ++ gtk_widget_set_sensitive(v2_artist_entry, TRUE); ++ gtk_widget_set_sensitive(v2_album_entry, TRUE); ++ gtk_widget_set_sensitive(v2_year_entry, TRUE); ++ gtk_widget_set_sensitive(v2_tracknum_entry, TRUE); ++ gtk_widget_set_sensitive(v2_comment_entry, TRUE); ++ gtk_widget_set_sensitive(v2_composer_entry, TRUE); ++ gtk_widget_set_sensitive(v2_orig_artist_entry, TRUE); ++ gtk_widget_set_sensitive(v2_url_entry, TRUE); ++ gtk_widget_set_sensitive(v2_encoded_by_entry, TRUE); ++ gtk_widget_set_sensitive(v2_genre_combo, TRUE); ++ } ++} ++static void v1_genre_selected(GtkList *list, GtkWidget *w, gpointer data) + { + void * p; + p = gtk_object_get_data(GTK_OBJECT(w), "genre_id"); + if (p != NULL) +- current_genre = GPOINTER_TO_INT(p); ++ v1_current_genre = GPOINTER_TO_INT(p); + else +- current_genre = 0; ++ v1_current_genre = 0; ++} ++ ++static void v2_genre_selected(GtkList *list, GtkWidget *w, gpointer data) ++{ ++ void * p; ++ p = gtk_object_get_data(GTK_OBJECT(w), "genre_id"); ++ if (p != NULL) ++ v2_current_genre = GPOINTER_TO_INT(p); ++ else ++ v2_current_genre = 0; + } + + static void genre_set_popdown(GtkWidget *combo, GList *genres) +@@ -269,7 +495,7 @@ + void mpg123_file_info_box(char *filename) + { + int i; +- struct id3v1tag_t tag; ++ struct id3v1tag_t id3v1tag; + FILE *fh; + char *tmp, *title; + const char *emphasis[4]; +@@ -284,205 +510,397 @@ + + if (!window) + { +- GtkWidget *vbox, *hbox, *left_vbox, *table; +- GtkWidget *mpeg_frame, *mpeg_box; +- GtkWidget *label, *filename_hbox; +- GtkWidget *bbox, *save, *remove_id3, *cancel; +- ++ GtkWidget *window_vbox, ++ *id3v1_vbox, *id3v2_vbox, *id3v1_frame_vbox, *id3v2_frame_vbox, ++ *mpeg_lvbox, *mpeg_rvbox, *mpeg_hbox, *mpeg_box, *mpeg_frame, ++ *bbox, *save, *close, *copy_to, *copy_from, ++ *table, *label, *filename_hbox; ++ ++ v1_labels_list = g_ptr_array_new(); ++ v2_labels_list = g_ptr_array_new(); ++ + window = gtk_window_new(GTK_WINDOW_DIALOG); +- gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); +- gtk_signal_connect(GTK_OBJECT(window), "destroy", +- gtk_widget_destroyed, &window); +- gtk_signal_connect(GTK_OBJECT(window), "key_press_event", +- file_info_box_keypress_cb, NULL); ++ gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window); ++ gtk_signal_connect(GTK_OBJECT(window), "key_press_event", file_info_box_keypress_cb, NULL); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + +- vbox = gtk_vbox_new(FALSE, 10); +- gtk_container_add(GTK_CONTAINER(window), vbox); +- ++ window_vbox = gtk_vbox_new(FALSE,10); + filename_hbox = gtk_hbox_new(FALSE, 5); +- gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, +- FALSE, TRUE, 0); ++ gtk_box_pack_start(GTK_BOX(window_vbox), filename_hbox, FALSE, TRUE, 0); + + label = gtk_label_new(_("Filename:")); +- gtk_box_pack_start(GTK_BOX(filename_hbox), label, +- FALSE, TRUE, 0); ++ gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0); + filename_entry = xmms_entry_new(); + gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE); +- gtk_box_pack_start(GTK_BOX(filename_hbox), +- filename_entry, TRUE, TRUE, 0); +- +- hbox = gtk_hbox_new(FALSE, 10); +- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); +- +- left_vbox = gtk_vbox_new(FALSE, 10); +- gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0); ++ gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, 0); + +- id3_frame = gtk_frame_new(_("ID3 Tag:")); +- gtk_box_pack_start(GTK_BOX(left_vbox), id3_frame, +- FALSE, FALSE, 0); ++ /* Set up the genres list */ + +- table = gtk_table_new(5, 5, FALSE); ++ if (!genre_list) ++ { ++ struct genre_item *item; ++ ++ for (i = 0; i < GENRE_MAX; i++) ++ { ++ item = g_malloc(sizeof (*item)); ++ item->name = gettext(mpg123_id3_genres[i]); ++ item->id = i; ++ genre_list = g_list_prepend(genre_list, item); ++ } ++ item = g_malloc(sizeof (*item)); ++ item->name = ""; ++ item->id = 0xff; ++ genre_list = g_list_prepend(genre_list, item); ++ genre_list = g_list_sort(genre_list, genre_comp_func); ++ } ++ ++ notebook = gtk_notebook_new (); ++ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP); ++ ++ /* ID3v2 page */ ++ ++ id3v2_vbox = gtk_vbox_new(FALSE, 0); ++ ++ id3v2_frame = gtk_frame_new("ID3v2 Information"); ++ gtk_box_pack_start(GTK_BOX(id3v2_vbox), id3v2_frame, FALSE, FALSE, 0); ++ ++ id3v2_frame_vbox = gtk_vbox_new(FALSE, 0); ++ gtk_container_add(GTK_CONTAINER(id3v2_frame), id3v2_frame_vbox); ++ ++ table = gtk_table_new(6, 6, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); +- gtk_container_add(GTK_CONTAINER(id3_frame), table); ++ gtk_widget_set_usize(GTK_WIDGET(table), 400, -1); ++ gtk_box_pack_start(GTK_BOX(id3v2_frame_vbox), table, FALSE, FALSE, 0); + +- label = gtk_label_new(_("Title:")); ++ v2_checkbox = gtk_check_button_new_with_label ("Disable ID3v2 Tag"); ++ gtk_signal_connect(GTK_OBJECT(v2_checkbox), "toggled", GTK_SIGNAL_FUNC(v2_toggle_cb), NULL); ++ gtk_table_attach(GTK_TABLE(table), v2_checkbox, 1, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 2); ++ ++ label = gtk_label_new("Track number:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); +- gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, +- GTK_FILL, GTK_FILL, 5, 5); ++ gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, ++ GTK_FILL, GTK_FILL, 5,5); + +- title_entry = gtk_entry_new_with_max_length(30); +- gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v2_tracknum_entry = gtk_entry_new_with_max_length(3); ++ gtk_widget_set_usize(v2_tracknum_entry, 20, -1); ++ gtk_table_attach(GTK_TABLE(table), v2_tracknum_entry, 4, 5, 0, 1, ++ GTK_FILL, GTK_FILL, 0, 2); + +- label = gtk_label_new(_("Artist:")); ++ label = gtk_label_new("Title:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); +- gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, +- GTK_FILL, GTK_FILL, 5, 5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 5, 5); + +- artist_entry = gtk_entry_new_with_max_length(30); +- gtk_table_attach(GTK_TABLE(table), artist_entry, 1, 4, 1, 2, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v2_title_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_title_entry, 1, 5, 1, 2, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); + +- label = gtk_label_new(_("Album:")); ++ label = gtk_label_new("Artist:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, +- GTK_FILL, GTK_FILL, 5, 5); ++ GTK_FILL, GTK_FILL, 5, 5); + +- album_entry = gtk_entry_new_with_max_length(30); +- gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v2_artist_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_artist_entry, 1, 5, 2, 3, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); + +- label = gtk_label_new(_("Comment:")); ++ label = gtk_label_new("Album:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, +- GTK_FILL, GTK_FILL, 5, 5); ++ GTK_FILL, GTK_FILL, 5, 5); + +- comment_entry = gtk_entry_new_with_max_length(30); +- gtk_table_attach(GTK_TABLE(table), comment_entry, 1, 4, 3, 4, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v2_album_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_album_entry, 1, 5, 3, 4, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); + +- label = gtk_label_new(_("Year:")); ++ label = gtk_label_new("Comment:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, +- GTK_FILL, GTK_FILL, 5, 5); ++ GTK_FILL, GTK_FILL, 5, 5); + +- year_entry = gtk_entry_new_with_max_length(4); +- gtk_widget_set_usize(year_entry, 40, -1); +- gtk_table_attach(GTK_TABLE(table), year_entry, 1, 2, 4, 5, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v2_comment_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_comment_entry, 1, 5, 4, 5, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); + +- label = gtk_label_new(_("Track number:")); ++ label = gtk_label_new("Year:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); +- gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5, +- GTK_FILL, GTK_FILL, 5, 5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, ++ GTK_FILL, GTK_FILL, 5, 5); + +- tracknum_entry = gtk_entry_new_with_max_length(3); +- gtk_widget_set_usize(tracknum_entry, 40, -1); +- gtk_table_attach(GTK_TABLE(table), tracknum_entry, 3, 4, 4, 5, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v2_year_entry = gtk_entry_new_with_max_length(4); ++ gtk_widget_set_usize(v2_year_entry, 45, -1); ++ gtk_table_attach(GTK_TABLE(table), v2_year_entry, 1, 2, 5, 6, ++ GTK_FILL, GTK_FILL, 0, 2); + +- label = gtk_label_new(_("Genre:")); ++ label = gtk_label_new("Genre:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 2, 3, 5, 6, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v2_genre_combo = gtk_combo_new(); ++ gtk_combo_set_value_in_list(GTK_COMBO(v2_genre_combo), FALSE, TRUE); ++ ++ genre_set_popdown(v2_genre_combo, genre_list); ++ gtk_signal_connect(GTK_OBJECT(GTK_COMBO(v2_genre_combo)->list), ++ "select-child", v2_genre_selected, NULL); ++ ++ gtk_table_attach(GTK_TABLE(table), v2_genre_combo, 3, 5, 5, 6, ++ GTK_FILL | GTK_SHRINK, GTK_FILL | ++ GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("Composer:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v2_composer_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_composer_entry, 1, 5, 6, 7, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("Orig. Artist:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 7, 8, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v2_orig_artist_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_orig_artist_entry, 1, 5, 7, 8, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("URL:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 8, 9, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v2_url_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_url_entry, 1, 5, 8, 9, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ label = gtk_label_new("Encoded By:"); ++ g_ptr_array_add(v2_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 9, 10, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v2_encoded_by_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2); ++ gtk_table_attach(GTK_TABLE(table), v2_encoded_by_entry, 1, 5, 9, 10, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ bbox = gtk_hbutton_box_new(); ++ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START); ++ gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 0); ++ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5); ++ gtk_box_pack_start(GTK_BOX(id3v2_frame_vbox), bbox, FALSE, FALSE, 0); ++ ++ copy_to = gtk_button_new_with_label("ID3v2 to ID3v1"); ++ gtk_signal_connect(GTK_OBJECT(copy_to), "clicked", GTK_SIGNAL_FUNC(copy_v2_to_v1_cb), NULL); ++ /* remove the next line to thicken the button width */ ++ GTK_WIDGET_SET_FLAGS(copy_to, GTK_CAN_DEFAULT); ++ gtk_box_pack_start(GTK_BOX(bbox), copy_to, FALSE, TRUE, 0); ++ ++ label = gtk_label_new ("ID3v2"); ++ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), id3v2_vbox, label); ++ ++ /* ID3v1 page */ ++ ++ id3v1_vbox = gtk_vbox_new(FALSE, 10); ++ id3v1_frame = gtk_frame_new("ID3v1 Information"); ++ gtk_box_pack_start(GTK_BOX(id3v1_vbox), id3v1_frame, TRUE, TRUE, 0); ++ ++ id3v1_frame_vbox = gtk_vbox_new(FALSE,10); ++ gtk_container_add(GTK_CONTAINER(id3v1_frame), id3v1_frame_vbox); ++ ++ table = gtk_table_new(6, 6, FALSE); ++ gtk_container_set_border_width(GTK_CONTAINER(table), 5); ++ //gtk_widget_set_usize(GTK_WIDGET(table), 325, -1); ++ //gtk_container_add(GTK_CONTAINER(id3v1_frame), table); ++ gtk_box_pack_start(GTK_BOX(id3v1_frame_vbox), table, FALSE, FALSE, 0); ++ ++ v1_checkbox = gtk_check_button_new_with_label ("Disable ID3v1 Tag"); ++ gtk_signal_connect(GTK_OBJECT(v1_checkbox), "toggled", GTK_SIGNAL_FUNC(v1_toggle_cb), NULL); ++ gtk_table_attach(GTK_TABLE(table), v1_checkbox, 1, 3, 0, 1, ++ GTK_FILL, GTK_FILL, 0, 2); ++ ++ label = gtk_label_new("Track number:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1, ++ GTK_FILL, GTK_FILL, 5,5); ++ ++ v1_tracknum_entry = gtk_entry_new_with_max_length(3); ++ gtk_widget_set_usize(v1_tracknum_entry, 20, -1); ++ gtk_table_attach(GTK_TABLE(table), v1_tracknum_entry, 4, 5, 0, 1, ++ GTK_FILL, GTK_FILL, 0, 2); ++ ++ label = gtk_label_new("Title:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v1_title_entry = gtk_entry_new_with_max_length(30); ++ gtk_table_attach(GTK_TABLE(table), v1_title_entry, 1, 5, 1, 2, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("Artist:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v1_artist_entry = gtk_entry_new_with_max_length(30); ++ gtk_table_attach(GTK_TABLE(table), v1_artist_entry, 1, 5, 2, 3, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("Album:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v1_album_entry = gtk_entry_new_with_max_length(30); ++ gtk_table_attach(GTK_TABLE(table), v1_album_entry, 1, 5, 3, 4, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("Comment:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, ++ GTK_FILL, GTK_FILL, 5, 5); ++ ++ v1_comment_entry = gtk_entry_new_with_max_length(30); ++ gtk_table_attach(GTK_TABLE(table), v1_comment_entry, 1, 5, 4, 5, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, ++ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2); ++ ++ label = gtk_label_new("Year:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, +- GTK_FILL, GTK_FILL, 5, 5); ++ GTK_FILL, GTK_FILL, 5, 5); + +- genre_combo = gtk_combo_new(); +- gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(genre_combo)->entry), +- FALSE); +- if (!genre_list) +- { +- struct genre_item *item; ++ v1_year_entry = gtk_entry_new_with_max_length(4); ++ gtk_widget_set_usize(v1_year_entry, 45, -1); ++ gtk_table_attach(GTK_TABLE(table), v1_year_entry, 1, 2, 5, 6, ++ GTK_FILL, GTK_FILL, 0, 2); + +- for (i = 0; i < GENRE_MAX; i++) +- { +- item = g_malloc(sizeof (*item)); +- item->name = gettext(mpg123_id3_genres[i]); +- item->id = i; +- genre_list = g_list_prepend(genre_list, item); +- } +- item = g_malloc(sizeof (*item)); +- item->name = ""; +- item->id = 0xff; +- genre_list = g_list_prepend(genre_list, item); +- genre_list = g_list_sort(genre_list, genre_comp_func); +- } +- genre_set_popdown(genre_combo, genre_list); +- gtk_signal_connect(GTK_OBJECT(GTK_COMBO(genre_combo)->list), +- "select-child", genre_selected, NULL); ++ label = gtk_label_new("Genre:"); ++ g_ptr_array_add(v1_labels_list, (gpointer)label); ++ gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); ++ gtk_table_attach(GTK_TABLE(table), label, 2, 3, 5, 6, ++ GTK_FILL, GTK_FILL, 5, 5); + +- gtk_table_attach(GTK_TABLE(table), genre_combo, 1, 4, 5, 6, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, +- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); ++ v1_genre_combo = gtk_combo_new(); ++ gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(v1_genre_combo)->entry), FALSE); ++ genre_set_popdown(v1_genre_combo, genre_list); ++ gtk_signal_connect(GTK_OBJECT(GTK_COMBO(v1_genre_combo)->list), ++ "select-child", v1_genre_selected, NULL); ++ ++ gtk_table_attach(GTK_TABLE(table), v1_genre_combo, 3, 5, 5, 6, ++ GTK_FILL | GTK_SHRINK, GTK_FILL | ++ GTK_SHRINK, 0, 2); + + bbox = gtk_hbutton_box_new(); +- gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), +- GTK_BUTTONBOX_END); +- gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); +- gtk_box_pack_start(GTK_BOX(left_vbox), bbox, FALSE, FALSE, 0); ++ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START); ++ gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 0); ++ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5); ++ gtk_box_pack_start(GTK_BOX(id3v1_frame_vbox), bbox, FALSE, FALSE, 0); + +- save = gtk_button_new_with_label(_("Save")); +- gtk_signal_connect(GTK_OBJECT(save), "clicked", save_cb, NULL); +- GTK_WIDGET_SET_FLAGS(save, GTK_CAN_DEFAULT); +- gtk_box_pack_start(GTK_BOX(bbox), save, TRUE, TRUE, 0); +- gtk_widget_grab_default(save); ++ copy_from = gtk_button_new_with_label("ID3v1 to ID3v2"); ++ gtk_signal_connect(GTK_OBJECT(copy_from), "clicked", GTK_SIGNAL_FUNC(copy_v1_to_v2_cb), NULL); ++ // remove the next line to thicken the button width ++ GTK_WIDGET_SET_FLAGS(copy_from, GTK_CAN_DEFAULT); ++ gtk_box_pack_start(GTK_BOX(bbox), copy_from, FALSE, TRUE, 0); + +- remove_id3 = gtk_button_new_with_label(_("Remove ID3")); +- gtk_signal_connect(GTK_OBJECT(remove_id3), "clicked", +- remove_id3_cb, NULL); +- GTK_WIDGET_SET_FLAGS(remove_id3, GTK_CAN_DEFAULT); +- gtk_box_pack_start(GTK_BOX(bbox), remove_id3, TRUE, TRUE, 0); ++ label = gtk_label_new ("ID3v1"); ++ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), id3v1_vbox, label); + +- cancel = gtk_button_new_with_label(_("Cancel")); +- gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", +- gtk_widget_destroy, GTK_OBJECT(window)); +- GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT); +- gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); ++ /* MPEG info page */ + +- mpeg_frame = gtk_frame_new(_("MPEG Info:")); +- gtk_box_pack_start(GTK_BOX(hbox), mpeg_frame, FALSE, FALSE, 0); ++ mpeg_frame = gtk_frame_new("MPEG Information"); ++ mpeg_hbox = gtk_hbox_new(FALSE,50); ++ gtk_container_add(GTK_CONTAINER(mpeg_frame), mpeg_hbox); ++ ++ mpeg_lvbox = gtk_vbox_new(FALSE, 5); ++ gtk_container_set_border_width(GTK_CONTAINER(mpeg_lvbox), 10); ++ gtk_box_pack_start(GTK_BOX(mpeg_hbox), mpeg_lvbox, FALSE, FALSE, 0); + + mpeg_box = gtk_vbox_new(FALSE, 5); +- gtk_container_add(GTK_CONTAINER(mpeg_frame), mpeg_box); ++ gtk_box_pack_start(GTK_BOX(mpeg_hbox), mpeg_box, FALSE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(mpeg_box), 10); + gtk_box_set_spacing(GTK_BOX(mpeg_box), 0); + + mpeg_level = gtk_label_new(""); +- gtk_widget_set_usize(mpeg_level, 120, -2); +- gtk_misc_set_alignment(GTK_MISC(mpeg_level), 0, 0); +- gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_level, FALSE, FALSE, 0); +- +- mpeg_bitrate = gtk_label_new(""); +- gtk_misc_set_alignment(GTK_MISC(mpeg_bitrate), 0, 0); +- gtk_label_set_justify(GTK_LABEL(mpeg_bitrate), +- GTK_JUSTIFY_LEFT); +- gtk_box_pack_start(GTK_BOX(mpeg_box), +- mpeg_bitrate, FALSE, FALSE, 0); ++ //gtk_widget_set_usize(mpeg_level, 120, -2); ++ gtk_label_set_justify (GTK_LABEL(mpeg_level), GTK_JUSTIFY_LEFT); ++ gtk_misc_set_alignment(GTK_MISC(mpeg_level), 0, 0.5); ++ gtk_box_pack_start(GTK_BOX(mpeg_lvbox), mpeg_level, FALSE, FALSE, 0); + + mpeg_samplerate = gtk_label_new(""); +- gtk_misc_set_alignment(GTK_MISC(mpeg_samplerate), 0, 0); +- gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_samplerate, +- FALSE, FALSE, 0); ++ gtk_label_set_justify (GTK_LABEL(mpeg_samplerate), GTK_JUSTIFY_LEFT); ++ gtk_misc_set_alignment(GTK_MISC(mpeg_samplerate), 0, 0.5); ++ gtk_box_pack_start(GTK_BOX(mpeg_lvbox), mpeg_samplerate, FALSE, FALSE, 0); ++ ++ mpeg_fileinfo = gtk_label_new(""); ++ gtk_label_set_justify (GTK_LABEL(mpeg_fileinfo), GTK_JUSTIFY_LEFT); ++ gtk_misc_set_alignment(GTK_MISC(mpeg_fileinfo), 0, 0.5); ++ gtk_box_pack_start(GTK_BOX(mpeg_lvbox), mpeg_fileinfo, FALSE, FALSE, 0); ++ ++ mpeg_rvbox = gtk_vbox_new(FALSE, 5); ++ gtk_box_pack_start(GTK_BOX(mpeg_hbox), mpeg_rvbox, FALSE, FALSE, 0); ++ gtk_container_set_border_width(GTK_CONTAINER(mpeg_rvbox), 10); ++ ++ mpeg_bitrate = gtk_label_new(""); ++ gtk_label_set_justify (GTK_LABEL(mpeg_bitrate), GTK_JUSTIFY_LEFT); ++ gtk_misc_set_alignment(GTK_MISC(mpeg_bitrate), 0, 0.5); ++ gtk_box_pack_start(GTK_BOX(mpeg_rvbox), mpeg_bitrate, FALSE, FALSE, 0); + + mpeg_flags = gtk_label_new(""); +- gtk_misc_set_alignment(GTK_MISC(mpeg_flags), 0, 0); +- gtk_label_set_justify(GTK_LABEL(mpeg_flags), GTK_JUSTIFY_LEFT); +- gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_flags, +- FALSE, FALSE, 0); ++ gtk_label_set_justify (GTK_LABEL(mpeg_flags), GTK_JUSTIFY_LEFT); ++ gtk_misc_set_alignment(GTK_MISC(mpeg_flags), 0, 0.5); ++ gtk_box_pack_start(GTK_BOX(mpeg_rvbox), mpeg_flags, FALSE, FALSE, 0); + +- mpeg_fileinfo = gtk_label_new(""); +- gtk_misc_set_alignment(GTK_MISC(mpeg_fileinfo), 0, 0); +- gtk_label_set_justify(GTK_LABEL(mpeg_fileinfo), +- GTK_JUSTIFY_LEFT); +- gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_fileinfo, +- FALSE, FALSE, 0); ++ label = gtk_label_new ("MPEG"); ++ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), mpeg_frame, label); ++ ++ /* add notebook to window vbox */ ++ gtk_box_pack_start(GTK_BOX(window_vbox), notebook, FALSE, FALSE, 0); ++ ++ /* add button box to window vbox */ ++ bbox = gtk_hbutton_box_new(); ++ gtk_box_pack_start(GTK_BOX(window_vbox), bbox, FALSE, FALSE, 0); + ++ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); ++ gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 5); ++ ++ save = gtk_button_new_with_label("Save"); ++ gtk_signal_connect(GTK_OBJECT(save), "clicked", GTK_SIGNAL_FUNC(save_cb), NULL); ++ gtk_box_pack_start(GTK_BOX(bbox), save, TRUE, TRUE, 5); ++ ++ close = gtk_button_new_with_label("Close"); ++ gtk_signal_connect_object(GTK_OBJECT(close), "clicked", ++ GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window)); ++ gtk_box_pack_start(GTK_BOX(bbox), close, TRUE, TRUE, 5); ++ ++ gtk_container_add(GTK_CONTAINER(window), window_vbox); + gtk_widget_show_all(window); + } + +@@ -500,73 +918,128 @@ + title = g_strdup(g_basename(filename)); + if ((tmp = strrchr(title, '.')) != NULL) + *tmp = '\0'; +- gtk_entry_set_text(GTK_ENTRY(title_entry), title); ++ gtk_entry_set_text(GTK_ENTRY(v1_title_entry), title); ++ gtk_entry_set_text(GTK_ENTRY(v2_title_entry), title); + g_free(title); + +- gtk_entry_set_text(GTK_ENTRY(artist_entry), ""); +- gtk_entry_set_text(GTK_ENTRY(album_entry), ""); +- gtk_entry_set_text(GTK_ENTRY(year_entry), ""); +- gtk_entry_set_text(GTK_ENTRY(tracknum_entry), ""); +- gtk_entry_set_text(GTK_ENTRY(comment_entry), ""); +- gtk_list_select_item(GTK_LIST(GTK_COMBO(genre_combo)->list), ++ gtk_entry_set_text(GTK_ENTRY(v1_artist_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v1_album_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v1_year_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v1_tracknum_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v1_comment_entry), ""); ++ ++ gtk_list_select_item(GTK_LIST(GTK_COMBO(v1_genre_combo)->list), + genre_find_index(genre_list, 0xff)); ++ ++ gtk_entry_set_text(GTK_ENTRY(v2_artist_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_album_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_year_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_tracknum_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_comment_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_composer_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_orig_artist_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_url_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(v2_encoded_by_entry), ""); ++ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(v2_genre_combo)->entry), ""); ++ + gtk_label_set_text(GTK_LABEL(mpeg_level), "MPEG ?, layer ?"); + gtk_label_set_text(GTK_LABEL(mpeg_bitrate), ""); + gtk_label_set_text(GTK_LABEL(mpeg_samplerate), ""); + gtk_label_set_text(GTK_LABEL(mpeg_flags), ""); + gtk_label_set_text(GTK_LABEL(mpeg_fileinfo), ""); +- + if (!strncasecmp(filename, "http://", 7)) + { + file_info_http(filename); + return; + } + +- gtk_widget_set_sensitive(id3_frame, TRUE); ++ gtk_widget_set_sensitive(id3v1_frame, TRUE); ++ gtk_widget_set_sensitive(id3v2_frame, TRUE); + + if ((fh = fopen(current_filename, "rb")) != NULL) + { + struct frame frm; + gboolean id3_found = FALSE; ++ struct id3_tag *id3 = NULL; + guint8 *buf; + double tpf; + int pos; + xing_header_t xing_header; + guint32 num_frames; +- +- fseek(fh, -sizeof (tag), SEEK_END); +- if (fread(&tag, 1, sizeof (tag), fh) == sizeof (tag)) ++ /* ++ * Try reading ID3v2 tag. ++ */ ++ fseek(fh, 0, SEEK_SET); ++ id3 = id3_open_fp(fh, 0); ++ if (id3 != NULL) + { +- if (!strncmp(tag.tag, "TAG", 3)) ++ struct id3_frame* frame; ++ ++ set_entry_tag_v2(GTK_ENTRY(v2_title_entry), id3, ID3_TIT2); ++ set_entry_tag_v2(GTK_ENTRY(v2_artist_entry), id3, ID3_TPE1); ++ set_entry_tag_v2(GTK_ENTRY(v2_album_entry), id3, ID3_TALB); ++ set_entry_tag_v2(GTK_ENTRY(v2_comment_entry), id3, ID3_COMM); ++ set_entry_tag_v2(GTK_ENTRY(v2_composer_entry), id3, ID3_TCOM); ++ set_entry_tag_v2(GTK_ENTRY(v2_orig_artist_entry), id3, ID3_TOPE); ++ set_entry_tag_v2(GTK_ENTRY(v2_url_entry), id3, ID3_WCOM); ++ set_entry_tag_v2(GTK_ENTRY(v2_encoded_by_entry), id3, ID3_TENC); ++ set_entry_tag_v2(GTK_ENTRY(v2_tracknum_entry), id3, ID3_TRCK); ++ set_entry_tag_v2(GTK_ENTRY(v2_year_entry), id3, ID3_TYER); ++ ++ frame = id3_get_frame(id3, ID3_TCON, 1); ++ if (frame != NULL) + { +- id3_found = TRUE; +- set_entry_tag(GTK_ENTRY(title_entry), +- tag.title, 30); +- set_entry_tag(GTK_ENTRY(artist_entry), +- tag.artist, 30); +- set_entry_tag(GTK_ENTRY(album_entry), +- tag.album, 30); +- set_entry_tag(GTK_ENTRY(year_entry), +- tag.year, 4); +- /* Check for v1.1 tags */ +- if (tag.u.v1_1.__zero == 0 && tag.u.v1_1.track_number > 0) +- { +- char *temp = g_strdup_printf("%d", tag.u.v1_1.track_number); +- set_entry_tag(GTK_ENTRY(comment_entry), +- tag.u.v1_1.comment, 28); +- gtk_entry_set_text(GTK_ENTRY(tracknum_entry), temp); +- g_free(temp); +- } +- else ++ char* genre = id3_get_content(frame); ++ if (genre != NULL) + { +- set_entry_tag(GTK_ENTRY(comment_entry), +- tag.u.v1_0.comment, 30); +- gtk_entry_set_text(GTK_ENTRY(tracknum_entry), ""); ++ int genre_idx = genre_find_index_str(genre_list, genre); ++ if (genre_idx > 0) ++ gtk_list_select_item(GTK_LIST(GTK_COMBO(v2_genre_combo)->list), genre_idx); ++ else ++ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(v2_genre_combo)->entry), genre); + } +- +- gtk_list_select_item(GTK_LIST(GTK_COMBO(genre_combo)->list), genre_find_index(genre_list, tag.genre)); + } ++ ++ id3_close(id3); ++ } ++ else ++ { ++ /* Grey out the id3v2 tab */ ++ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(v2_checkbox), TRUE); ++ } ++ ++ /* ++ * Try reading ID3v1 tag. ++ */ ++ fseek(fh, -sizeof (id3v1tag), SEEK_END); ++ if ( (fread(&id3v1tag, 1, sizeof (id3v1tag), fh) == sizeof (id3v1tag)) && !strncmp(id3v1tag.tag, "TAG", 3)) ++ { ++ id3_found = TRUE; ++ set_entry_tag_v1(GTK_ENTRY(v1_title_entry), id3v1tag.title, 30); ++ set_entry_tag_v1(GTK_ENTRY(v1_artist_entry), id3v1tag.artist, 30); ++ set_entry_tag_v1(GTK_ENTRY(v1_album_entry), id3v1tag.album, 30); ++ set_entry_tag_v1(GTK_ENTRY(v1_year_entry), id3v1tag.year, 4); ++ /* Check for v1.1 tags */ ++ if (id3v1tag.u.v1_1.__zero == 0 && id3v1tag.u.v1_1.track_number > 0) ++ { ++ char *temp = g_strdup_printf("%d", id3v1tag.u.v1_1.track_number); ++ set_entry_tag_v1(GTK_ENTRY(v1_comment_entry), id3v1tag.u.v1_1.comment, 28); ++ gtk_entry_set_text(GTK_ENTRY(v1_tracknum_entry), temp); ++ g_free(temp); ++ } ++ else ++ { ++ set_entry_tag_v1(GTK_ENTRY(v1_comment_entry), id3v1tag.u.v1_0.comment, 30); ++ gtk_entry_set_text(GTK_ENTRY(v1_tracknum_entry), ""); + } ++ gtk_list_select_item(GTK_LIST(GTK_COMBO(v1_genre_combo)->list), genre_find_index(genre_list, id3v1tag.genre)); ++ } ++ else ++ { ++ // Grey out id3v1 tab ++ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(v1_checkbox), TRUE); ++ } ++ + rewind(fh); + + if (!mpg123_get_first_frame(fh, &frm, &buf)) +diff -dPNur xmms-1.2.11/Input/mpg123/id3.c xmms-1.2.11-new/Input/mpg123/id3.c +--- xmms-1.2.11/Input/mpg123/id3.c 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/id3.c 2007-11-24 23:58:41.000000000 +0100 +@@ -22,6 +22,7 @@ + + #include <sys/types.h> + #include <sys/uio.h> ++#include <sys/stat.h> + #include <glib.h> + #include <fcntl.h> + #include <unistd.h> +@@ -49,7 +50,7 @@ + */ + static int id3_seek_mem(struct id3_tag *id3, int offset) + { +- if (id3->id3_pos + offset > id3->id3_tagsize || ++ if (id3->id3_pos + offset > id3->id3_totalsize || + id3->id3_pos + offset < 0) + { + id3_error(id3, "seeking beyond tag boundary"); +@@ -77,7 +78,7 @@ + /* + * Check boundary. + */ +- if (id3->id3_pos + size > id3->id3_tagsize) ++ if (id3->id3_pos + size > id3->id3_totalsize) + return NULL; + + /* +@@ -118,7 +119,7 @@ + /* + * Check boundary. + */ +- if (id3->id3_pos + offset > id3->id3_tagsize || ++ if (id3->id3_pos + offset > id3->id3_totalsize || + id3->id3_pos + offset < 0) + return -1; + +@@ -148,8 +149,8 @@ + /* + * Check boundary. + */ +- if (id3->id3_pos + size > id3->id3_tagsize) +- return NULL; ++ if (id3->id3_pos + size > id3->id3_totalsize) ++ size = id3->id3_totalsize - id3->id3_pos; + + /* + * If buffer is NULL, we use the default buffer. +@@ -205,7 +206,7 @@ + /* + * Check boundary. + */ +- if (id3->id3_pos + offset > id3->id3_tagsize || ++ if (id3->id3_pos + offset > id3->id3_totalsize || + id3->id3_pos + offset < 0) + return -1; + +@@ -263,8 +264,8 @@ + /* + * Check boundary. + */ +- if (id3->id3_pos + size > id3->id3_tagsize) +- size = id3->id3_tagsize - id3->id3_pos; ++ if (id3->id3_pos + size > id3->id3_totalsize) ++ size = id3->id3_totalsize - id3->id3_pos; + + /* + * If buffer is NULL, we use the default buffer. +@@ -338,6 +339,32 @@ + return NULL; + } + ++/* ++ * Function id3_new() ++ * ++ * Creates a new ID3 tag structure. Useful for creating ++ * a new tag. ++ * ++ */ ++struct id3_tag *id3_new() ++{ ++ struct id3_tag *id3; ++ ++ /* ++ * Allocate ID3 structure. ++ */ ++ id3 = g_malloc0( sizeof(struct id3_tag) ); ++ ++ if (id3 != NULL) ++ { ++ id3_init_tag ( id3 ); ++ id3->id3_type = ID3_TYPE_NONE; ++ id3->id3_seek = NULL; ++ id3->id3_read = NULL; ++ } ++ ++ return id3; ++} + + /* + * Function id3_open_fd (fd, flags) +@@ -493,7 +520,7 @@ + if (id3->id3_newtag) + return 0; + else +- return id3->id3_tagsize + 3 + sizeof(id3_taghdr_t); ++ return id3->id3_totalsize + 3 + sizeof(id3_taghdr_t); + } + #endif + +@@ -560,6 +587,81 @@ + return 0; + } + ++/* ++ * Function id3_remove_tag_filename(filename) ++ * ++ * Remove the ID3v2 tag from the file indicated by filename. Takes care of resizing ++ * the file, if needed. Returns 0 upon success, or -1 if an error occured. ++ * ++ */ ++int id3_remove_tag_filename(const char* filename) ++{ ++ struct id3_tag *current_id3; ++ int fd; ++ int current_totalsize; ++ struct stat stat_buf; ++ ++ fd = open(filename, O_RDWR); ++ if (fd == -1) ++ return -1; ++ ++ /* ++ * Figure out how large the current tag is. ++ */ ++ current_id3 = id3_open_fd(fd, 0); ++ if (current_id3 != NULL) ++ { ++ /* We use MAX to make sure an erroneous tag doesn't confuse us */ ++ current_totalsize = MAX(current_id3->id3_totalsize, 0); ++ id3_close(current_id3); ++ } ++ else ++ { ++ current_totalsize = 0; ++ } ++ ++ if (current_totalsize <= 0) ++ return 0; ++ ++ /* ++ * Rewrite the file. ++ */ ++ ++ stat(filename, &stat_buf); ++ ++ /* Re-position all the data current_totalsize bytes backwards */ ++ { ++ int read_pos, write_pos; ++ size_t read_size; ++ char buf[4096]; ++ ++ /* TODO: Add error handling to IO operations */ ++ ++ /* We reposition the data by going forwards, each time reading ++ a block and copying it backward. That way, we never write ++ over a block which we intend to read later. */ ++ write_pos = 0; ++ read_pos = write_pos + current_totalsize; ++ ++ do ++ { ++ lseek(fd, read_pos, SEEK_SET); ++ read_size = read(fd, buf, sizeof(buf)); ++ read_pos += read_size; ++ ++ /* Write whatever block we've got */ ++ lseek(fd, write_pos, SEEK_SET); ++ write(fd, buf, read_size); ++ write_pos += read_size; ++ } ++ while (read_size > 0); ++ ++ ftruncate(fd, stat_buf.st_size - current_totalsize); ++ } ++ ++ close(fd); ++ return 0; ++} + + /* + * Function id3_write_tag (id3, fd) +@@ -567,30 +669,25 @@ + * Wrtite the ID3 tag to the indicated file descriptor. Return 0 + * upon success, or -1 if an error occured. + * ++ * Warning: This function is called by id3_write_tag_filename and should ++ * not be called standalone, as it doesn't perform seeking ++ * and doesn't enlarge the file as necessary, and thus might ++ * OVERWRITE THE AUDIO DATA. ++ * + */ + int id3_write_tag(struct id3_tag *id3, int fd) + { + struct id3_frame *fr; + GList *node; +- int size = 0; + char buf[ID3_TAGHDR_SIZE]; + + /* +- * Calculate size of ID3 tag. +- */ +- for (node = id3->id3_frame; node != NULL; node = node->next) +- { +- fr = node->data; +- size += fr->fr_size + ID3_FRAMEHDR_SIZE; +- } +- +- /* + * Write tag header. + */ + buf[0] = id3->id3_version; + buf[1] = id3->id3_revision; + buf[2] = id3->id3_flags; +- ID3_SET_SIZE28(size, buf[3], buf[4], buf[5], buf[6]); ++ ID3_SET_SIZE28(id3->id3_size, buf[3], buf[4], buf[5], buf[6]); + + if (safe_write(fd, "ID3", 3) == -1) + return -1; +@@ -617,19 +714,203 @@ + * TODO: Support compressed headers, encoded + * headers, and grouping info. + */ +- /* fhdr.fh_id = fr->fr_desc ? g_htonl(fr->fr_desc->fd_id) : 0; */ +- fhdr[3] = (fr->fr_size >> 24) & 0xff; +- fhdr[4] = (fr->fr_size >> 16) & 0xff; +- fhdr[5] = (fr->fr_size >> 8) & 0xff; +- fhdr[6] = fr->fr_size & 0xff; +- fhdr[7] = (fr->fr_flags >> 8) & 0xff; +- fhdr[8] = fr->fr_flags & 0xff; ++ fhdr[0] = fr->fr_desc->fd_idstr[0]; ++ fhdr[1] = fr->fr_desc->fd_idstr[1]; ++ fhdr[2] = fr->fr_desc->fd_idstr[2]; ++ fhdr[3] = fr->fr_desc->fd_idstr[3]; ++ fhdr[4] = (fr->fr_raw_size >> 24) & 0xff; ++ fhdr[5] = (fr->fr_raw_size >> 16) & 0xff; ++ fhdr[6] = (fr->fr_raw_size >> 8) & 0xff; ++ fhdr[7] = fr->fr_raw_size & 0xff; ++ fhdr[8] = (fr->fr_flags >> 8) & 0xff; ++ fhdr[9] = fr->fr_flags & 0xff; + + if (safe_write(fd, fhdr, sizeof(fhdr)) == -1) + return -1; + +- if (safe_write(fd, fr->fr_data, fr->fr_size) == -1) ++ if (safe_write(fd, fr->fr_raw_data, fr->fr_raw_size) == -1) + return -1; + } + return 0; + } ++ ++ ++/* ++ * Function id3_write_tag_file(id3, filename) ++ * ++ * Write the ID3 tag to the file indicated by filename. Takes care of enlarging ++ * the file, if needed. Returns 0 upon success, or -1 if an error occured. ++ * ++ */ ++int id3_write_tag_filename(struct id3_tag *id3, const char* filename) ++{ ++ struct id3_tag *current_id3; ++ int fd; ++ int current_totalsize, new_totalsize; ++ GList* node; ++ ++ fd = open(filename, O_RDWR); ++ if (fd == -1) ++ return -1; ++ ++ /* ++ * Figure out how large the current tag is. ++ */ ++ current_id3 = id3_open_fd(fd, 0); ++ if (current_id3 != NULL) ++ { ++ /* We use MAX to make sure an erroneous tag doesn't confuse us */ ++ current_totalsize = MAX(current_id3->id3_totalsize, 0); ++ id3_close(current_id3); ++ } ++ else ++ { ++ current_totalsize = 0; ++ } ++ ++ /* ++ * Figure out how large the new tag will be. ++ */ ++ new_totalsize = 10; ++ node = id3->id3_frame; ++ while (node != NULL) ++ { ++ struct id3_frame* fr = node->data; ++ ++ { ++ char* text = id3_get_text(fr); ++ if (text != NULL) ++ { ++ int len = strlen(text); ++ g_free(text); ++ ++ if (len == 0) ++ { ++ /* We skip over frames with empty text */ ++ node = node->next; ++ id3_delete_frame(fr); ++ continue; ++ } ++ } ++ } ++ ++ { ++ char* url = id3_get_url(fr); ++ if (url != NULL) ++ { ++ int len = strlen(url); ++ g_free(url); ++ ++ if (len == 0) ++ { ++ /* We skip over frames with empty URLs */ ++ node = node->next; ++ id3_delete_frame(fr); ++ continue; ++ } ++ } ++ } ++ ++ new_totalsize += fr->fr_raw_size + ID3_FRAMEHDR_SIZE; ++ node = node->next; ++ } ++ new_totalsize += 0; /* no extended header, no footer, no padding */ ++ id3->id3_flags = 0; ++ ++ /* ++ * Determine whether we need to rewrite the file to make place for the new tag. ++ */ ++ if (new_totalsize > current_totalsize) ++ { ++ struct stat stat_buf; ++ int grow_size; ++ ++ stat(filename, &stat_buf); ++ grow_size = new_totalsize - current_totalsize; ++ ftruncate(fd, stat_buf.st_size + grow_size); ++ ++ /* truncate adds "sparse" zeros; we'll turn them into real ones, ++ which occupy space on disk, to make sure we actually have ++ the disk space before we start enlarging the file */ ++ { ++ int remaining = grow_size; ++ char buf[1024] = { 0 }; ++ lseek(fd, stat_buf.st_size, SEEK_SET); ++ while (remaining > 0) ++ { ++ int ret = write(fd, buf, MIN(sizeof(buf), remaining)); ++ if (ret >= 0) ++ remaining -= ret; ++ else ++ { ++ id3_error(id3, "Unable to enlarge file for the new tag"); ++ ftruncate(fd, stat_buf.st_size); ++ close(fd); ++ return -1; ++ } ++ } ++ } ++ ++ /* and now, re-position all the data grow_size bytes forward */ ++ { ++ int area_to_move_size = stat_buf.st_size - current_totalsize; ++ int read_pos, write_pos; ++ size_t read_size, read_size_desired; ++ char buf[4096]; ++ ++ /* TODO: Add error handling to IO operations */ ++ ++ /* We reposition the data by going backwards, each time reading ++ a block and copying it forward. That way, we never write ++ over a block which we intend to read later. */ ++ write_pos = lseek(fd, 0, SEEK_END); ++ read_pos = write_pos - grow_size; ++ ++ /* While we still have bytes to move... */ ++ while(area_to_move_size > 0) ++ { ++ /* Get 1 block or the remaining bytes -- the smallest of the two */ ++ read_size_desired = MIN(area_to_move_size, sizeof(buf)); ++ read_pos -= read_size_desired; ++ lseek(fd, read_pos, SEEK_SET); ++ read_size = read(fd, buf, read_size_desired); ++ ++ /* Write whatever block we've got */ ++ write_pos -= read_size; ++ lseek(fd, write_pos, SEEK_SET); ++ write(fd, buf, read_size); ++ ++ area_to_move_size -= read_size; ++ } ++ } ++ } ++ else ++ { ++ new_totalsize = current_totalsize; ++ } ++ ++ id3->id3_size = new_totalsize - 10; ++ ++ /* Zero-out the ID3v2 tag area */ ++ { ++ char buf[1024] = {0}; ++ size_t remaining; ++ ++ lseek(fd, 0, SEEK_SET); ++ for(remaining = new_totalsize; remaining > 0; remaining -= MIN(remaining,sizeof(buf))) ++ { ++ write(fd, buf, MIN(remaining,sizeof(buf))); ++ } ++ } ++ ++ /* Write the new tag */ ++ lseek(fd, 0, SEEK_SET); ++ if (id3_write_tag(id3, fd) == -1) ++ { ++ close(fd); ++ return -1; ++ } ++ ++ close(fd); ++ return 0; ++} +diff -dPNur xmms-1.2.11/Input/mpg123/id3_frame.c xmms-1.2.11-new/Input/mpg123/id3_frame.c +--- xmms-1.2.11/Input/mpg123/id3_frame.c 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/id3_frame.c 2007-11-24 23:58:41.000000000 +0100 +@@ -283,7 +283,7 @@ + */ + if (!((buf[0] >= '0' && buf[0] <= '9') || (buf[0] >= 'A' && buf[0] <= 'Z'))) + { +- id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); ++ id3->id3_seek(id3, id3->id3_totalsize - id3->id3_pos); + return 0; + } + id = ID3_FRAME_ID(buf[0], buf[1], buf[2], buf[3]); +@@ -308,7 +308,7 @@ + */ + + frame->fr_desc = find_frame_description(id); +- ++ + /* + * Check if frame had a valid id. + */ +@@ -385,6 +385,29 @@ + } + + /* ++ * Function id3_get_or_add_frame (id3, type) ++ * ++ * Search in the list of frames for the ID3-tag, and return the first frame ++ * of the indicated type. If no frame of the indicated type exists yet, ++ * it will add one and return it. ++ * ++ */ ++struct id3_frame *id3_get_or_add_frame(struct id3_tag *id3, guint32 type) ++{ ++ struct id3_frame* fr; ++ ++ fr = id3_get_frame(id3, type, 1); ++ if (fr != NULL) ++ { ++ return fr; ++ } ++ else ++ { ++ return id3_add_frame(id3, type); ++ } ++} ++ ++/* + * Function decompress_frame(frame) + * + * Uncompress the indicated frame. Return 0 upon success, or -1 if +@@ -517,27 +540,26 @@ + */ + int id3_delete_frame(struct id3_frame *frame) + { +- GList *list = frame->fr_owner->id3_frame; ++ struct id3_tag* id3 = frame->fr_owner; ++ GList *list = id3->id3_frame; + int ret; + + /* + * Search for frame in list. + */ +- if (g_list_find(list, frame) != NULL) +- { +- /* +- * Frame does not exist in frame list. +- */ +- ret = -1; +- } +- else +- { ++ if (g_list_find(list, frame) != NULL) { + /* + * Remove frame from frame list. + */ + list = g_list_remove(list, frame); +- frame->fr_owner->id3_altered = 1; +- ret = 0; ++ id3->id3_frame = list; ++ id3->id3_altered = 1; ++ ret = 0; ++ } else { ++ /* ++ * Frame does not exist in frame list. ++ */ ++ ret = -1; + } + + /* +@@ -704,7 +726,7 @@ + */ + if (!((buf[0] >= '0' && buf[0] <= '9') || (buf[0] >= 'A' && buf[0] <= 'Z'))) + { +- id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); ++ id3->id3_seek(id3, id3->id3_size - id3->id3_pos); + return 0; + } + +diff -dPNur xmms-1.2.11/Input/mpg123/id3_frame_text.c xmms-1.2.11-new/Input/mpg123/id3_frame_text.c +--- xmms-1.2.11/Input/mpg123/id3_frame_text.c 2007-11-24 23:58:20.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/id3_frame_text.c 2007-11-24 23:58:41.000000000 +0100 +@@ -155,6 +155,11 @@ + char *id3_get_text(struct id3_frame *frame) + { + int offset = 0; ++ ++ /* Do we even have data for this frame */ ++ if (!frame->fr_data) ++ return NULL; ++ + /* Type check */ + if (frame->fr_desc->fd_idstr[0] != 'T') + return NULL; +@@ -374,3 +379,54 @@ + return id3_string_decode(ID3_TEXT_FRAME_ENCODING(frame), + ID3_TEXT_FRAME_PTR(frame) + offset); + } ++ ++/* ++ * Function id3_set_comment (frame, text) ++ * ++ * Set text for the indicated frame. Return 0 upon ++ * success, or -1 if an error occured. ++ * ++ */ ++int id3_set_comment(struct id3_frame *frame, char *text) ++{ ++ int *intp; ++ ++ /* Type check */ ++ if (frame->fr_desc->fd_id != ID3_COMM) ++ return -1; ++ ++ /* ++ * Release memory occupied by previous data. ++ */ ++ id3_frame_clear_data(frame); ++ ++ /* ++ * Allocate memory for new data. ++ */ ++ frame->fr_raw_size = 13 + strlen(text); ++ frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); /* <encode>XXXComments\0<comment><\0> ++ ++ /* Save time... we just need to zero out the start, not the whole ++ * block, so don't waste time with a calloc() ++ */ ++ ++ ((guint8 *)frame->fr_raw_data)[0] = ID3_ENCODING_ISO_8859_1; ++ ((guint8 *)frame->fr_raw_data)[1] = 0x58; ++ ((guint8 *)frame->fr_raw_data)[2] = 0x58; ++ ((guint8 *)frame->fr_raw_data)[3] = 0x58; ++ ++ memcpy((char *) frame->fr_raw_data + 4, "Comments", 9); ++ ++ /* ++ * Copy contents. ++ */ ++ memcpy((char *) frame->fr_raw_data + 13, text, strlen(text) + 1); ++ ++ frame->fr_altered = 1; ++ frame->fr_owner->id3_altered = 1; ++ ++ frame->fr_data = frame->fr_raw_data; ++ frame->fr_size = frame->fr_raw_size; ++ ++ return 0; ++} +diff -dPNur xmms-1.2.11/Input/mpg123/id3_frame_url.c xmms-1.2.11-new/Input/mpg123/id3_frame_url.c +--- xmms-1.2.11/Input/mpg123/id3_frame_url.c 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/id3_frame_url.c 2007-11-24 23:58:41.000000000 +0100 +@@ -34,6 +34,11 @@ + char *id3_get_url(struct id3_frame *frame) + { + int offset = 0; ++ ++ /* Do we even have data for this frame */ ++ if (!frame->fr_data) ++ return NULL; ++ + /* Type check */ + if (frame->fr_desc->fd_idstr[0] != 'W') + return NULL; +@@ -80,3 +85,32 @@ + return id3_string_decode(ID3_TEXT_FRAME_ENCODING(frame), + ID3_TEXT_FRAME_PTR(frame)); + } ++ ++/* ++ * Function id3_set_url (frame) ++ * ++ * Sets URL of frame. ++ * ++ */ ++void id3_set_url(struct id3_frame *frame, const char* url) ++{ ++ /* Type check */ ++ if ( frame->fr_desc->fd_idstr[0] != 'W' ) ++ return; ++ ++ /* Check if frame is compressed */ ++ if (id3_decompress_frame(frame) == -1) ++ return; ++ ++ /* ++ * Allocate memory for new data. ++ */ ++ frame->fr_raw_size = strlen(url) + 1; ++ frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); ++ ++ /* ++ * Copy contents. ++ */ ++ *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; ++ memcpy((char *) frame->fr_raw_data + 1, url, frame->fr_raw_size); ++} +diff -dPNur xmms-1.2.11/Input/mpg123/id3.h xmms-1.2.11-new/Input/mpg123/id3.h +--- xmms-1.2.11/Input/mpg123/id3.h 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/id3.h 2007-11-24 23:58:41.000000000 +0100 +@@ -22,6 +22,7 @@ + #define ID3_H + + #include <glib.h> ++#include <string.h> + + /* + * Option flags to id3_open_*(). +@@ -49,8 +50,9 @@ + + int id3_version; /* Major ID3 version number */ + int id3_revision; /* ID3 revision number */ ++ int id3_size; /* Size of ID3 tag (as dictated by header) */ + +- int id3_tagsize; /* Total size of ID3 tag */ ++ int id3_totalsize; /* Total size of ID3 tag (including header, footer and padding) */ + int id3_pos; /* Current position within tag */ + + char *id3_error_msg; /* Last error message */ +@@ -140,8 +142,6 @@ + #define ID3_ENCODING_UTF16BE 0x02 + #define ID3_ENCODING_UTF8 0x03 + +- +- + /* + * ID3 frame id numbers. + */ +@@ -322,50 +322,51 @@ + */ + + /* From id3.c */ +-struct id3_tag *id3_open_mem(void *, int); +-struct id3_tag *id3_open_fd(int, int); +-struct id3_tag *id3_open_fp(FILE *, int); +-int id3_set_output(struct id3_tag *, char *); +-int id3_close(struct id3_tag *); +-int id3_tell(struct id3_tag *); +-int id3_alter_file(struct id3_tag *); +-int id3_write_tag(struct id3_tag *, int); ++struct id3_tag *id3_new(); ++struct id3_tag *id3_open_mem(void *ptr, int flags); ++struct id3_tag *id3_open_fd(int fd, int flags); ++struct id3_tag *id3_open_fp(FILE *fp, int flags); ++int id3_close(struct id3_tag *id3); ++int id3_tell(struct id3_tag *id3); ++int id3_alter_file(struct id3_tag *id3); ++int id3_write_tag(struct id3_tag *id3, int fd); ++int id3_write_tag_filename(struct id3_tag *id3, const char* filename); ++int id3_remove_tag_filename(const char* filename); + + /* From id3_frame.c */ + int id3_read_frame(struct id3_tag *id3); +-struct id3_frame *id3_get_frame(struct id3_tag *, guint32, int); ++struct id3_frame *id3_get_frame(struct id3_tag *id3, guint32 type, int num); + int id3_delete_frame(struct id3_frame *frame); +-struct id3_frame *id3_add_frame(struct id3_tag *, guint32); +-int id3_decompress_frame(struct id3_frame *); +-void id3_destroy_frames(struct id3_tag *id); ++struct id3_frame *id3_add_frame(struct id3_tag *id3, guint32 type); ++struct id3_frame *id3_get_or_add_frame(struct id3_tag *id3, guint32 type); ++int id3_decompress_frame(struct id3_frame *frame); ++void id3_destroy_frames(struct id3_tag *id3); + void id3_frame_clear_data(struct id3_frame *frame); + + /* From id3_frame_text.c */ + guint id3_string_size(guint8 encoding, const char* text); + char* id3_string_decode(guint8 encoding, const char* text); +-gint8 id3_get_encoding(struct id3_frame *); +-int id3_set_encoding(struct id3_frame *, gint8); +-char *id3_get_text(struct id3_frame *); +-char *id3_get_comment(struct id3_frame *); +-char *id3_get_text_desc(struct id3_frame *); +-int id3_get_text_number(struct id3_frame *); +-int id3_set_text(struct id3_frame *, char *); +-int id3_set_text_number(struct id3_frame *, int); ++gint8 id3_get_encoding(struct id3_frame *frame); ++int id3_set_encoding(struct id3_frame *frame, gint8 encoding); ++char *id3_get_text(struct id3_frame *frame); ++char *id3_get_comment(struct id3_frame *frame); ++char *id3_get_text_desc(struct id3_frame *frame); ++int id3_get_text_number(struct id3_frame *frame); ++int id3_set_text(struct id3_frame *frame, char *text); ++int id3_set_comment(struct id3_frame *frame, char *comment); ++int id3_set_text_number(struct id3_frame *frame, int number); + gboolean id3_frame_is_text(struct id3_frame *frame); + + /* From id3_frame_content.c */ +-char *id3_get_content(struct id3_frame *); ++char *id3_get_content(struct id3_frame *frame); + + /* From id3_frame_url.c */ +-char *id3_get_url(struct id3_frame *); +-char *id3_get_url_desc(struct id3_frame *); ++char *id3_get_url(struct id3_frame *frame); ++char *id3_get_url_desc(struct id3_frame *frame); ++void id3_set_url(struct id3_frame *frame, const char* url); + + /* From id3_tag.c */ + void id3_init_tag(struct id3_tag *id3); + int id3_read_tag(struct id3_tag *id3); + +-char *convert_from_utf16(const unsigned char *utf16); +-char *convert_from_utf16be(const unsigned char *utf16); +- +- + #endif /* ID3_H */ +diff -dPNur xmms-1.2.11/Input/mpg123/id3_header.h xmms-1.2.11-new/Input/mpg123/id3_header.h +--- xmms-1.2.11/Input/mpg123/id3_header.h 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/id3_header.h 2007-11-24 23:58:41.000000000 +0100 +@@ -39,22 +39,21 @@ + #define ID3_THFLAG_USYNC 0x80 + #define ID3_THFLAG_EXT 0x40 + #define ID3_THFLAG_EXP 0x20 ++#define ID3_THFLAG_FOOTER 0x10 + + #define ID3_SET_SIZE28(size, a, b, c, d) \ +-do { \ +- a = (size >> (24 + 3)) & 0x7f; \ +- b = (size >> (16 + 2)) & 0x7f; \ +- c = (size >> ( 8 + 1)) & 0x7f; \ ++{ \ ++ a = (size >> (24 - 3)) & 0x7f; \ ++ b = (size >> (16 - 2)) & 0x7f; \ ++ c = (size >> ( 8 - 1)) & 0x7f; \ + d = size & 0x7f; \ +-} while (0) ++} + + #define ID3_GET_SIZE28(a, b, c, d) \ +-(((a & 0x7f) << (24 - 3)) | \ +- ((b & 0x7f) << (16 - 2)) | \ +- ((c & 0x7f) << ( 8 - 1)) | \ +- ((d & 0x7f))) +- +- ++ (((a & 0x7f) << (24 - 3)) | \ ++ ((b & 0x7f) << (16 - 2)) | \ ++ ((c & 0x7f) << ( 8 - 1)) | \ ++ ((d & 0x7f))) \ + + /* + * Layout for the extended header. +diff -dPNur xmms-1.2.11/Input/mpg123/id3_tag.c xmms-1.2.11-new/Input/mpg123/id3_tag.c +--- xmms-1.2.11/Input/mpg123/id3_tag.c 2005-05-21 20:05:56.000000000 +0200 ++++ xmms-1.2.11-new/Input/mpg123/id3_tag.c 2007-11-24 23:58:41.000000000 +0100 +@@ -39,7 +39,8 @@ + id3->id3_version = 3; + id3->id3_revision = 0; + id3->id3_flags = ID3_THFLAG_USYNC | ID3_THFLAG_EXP; +- id3->id3_tagsize = 0; ++ id3->id3_size = 0; ++ id3->id3_totalsize = 0; + + id3->id3_altered = 1; + id3->id3_newtag = 1; +@@ -63,13 +64,14 @@ + int id3_read_tag(struct id3_tag *id3) + { + char *buf; ++ guint8 padding; + + /* + * We know that the tag will be at least this big. + * + * tag header + "ID3" + */ +- id3->id3_tagsize = ID3_TAGHDR_SIZE + 3; ++ id3->id3_totalsize = ID3_TAGHDR_SIZE + 3; + + if (!(id3->id3_oflags & ID3_OPENF_NOCHK)) + { +@@ -100,9 +102,11 @@ + id3->id3_version = buf[0]; + id3->id3_revision = buf[1]; + id3->id3_flags = buf[2]; +- id3->id3_tagsize = ID3_GET_SIZE28(buf[3], buf[4], buf[5], buf[6]); ++ id3->id3_size = ID3_GET_SIZE28(buf[3], buf[4], buf[5], buf[6]); ++ id3->id3_totalsize += id3->id3_size; ++ if (id3->id3_flags & ID3_THFLAG_FOOTER) ++ id3->id3_totalsize += 10; + id3->id3_newtag = 0; +- id3->id3_pos = 0; + + if (id3->id3_version < 2 || id3->id3_version > 4) + return -1; +@@ -120,14 +124,34 @@ + /* + * Parse frames. + */ +- while (id3->id3_pos < id3->id3_tagsize) ++ while (id3->id3_pos < id3->id3_size) + { + if (id3_read_frame(id3) == -1) + return -1; + } + +- if (id3->id3_frame == NULL) +- return -1; ++ /* ++ * Like id3lib, we try to find unstandard padding (not within ++ * the tag size). This is important to know when we strip ++ * the tag or replace it. ++ * Another option might be looking for an MPEG sync, but we don't do it. ++ */ ++ ++ id3->id3_seek(id3, id3->id3_totalsize - id3->id3_pos); ++ ++ /* Temporarily increase totalsize, to try reading beyong the boundary */ ++ ++id3->id3_totalsize; ++ ++ while (id3->id3_read(id3, &padding, sizeof(padding)) != NULL) ++ { ++ if (padding == 0) ++ ++id3->id3_totalsize; ++ else ++ break; ++ } ++ ++ /* Decrease totalsize after we temporarily increased it */ ++ --id3->id3_totalsize; + + return 0; + } +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.c xmms-1.2.11-new/Input/mpg123/mpg123.c +--- xmms-1.2.11/Input/mpg123/mpg123.c 2007-11-24 23:58:20.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.c 2007-11-24 23:58:41.000000000 +0100 +@@ -129,9 +129,9 @@ + + #ifdef USE_SIMD + fr->dct36 = funcs_dct36[0]; +- ++ + if (CPU_HAS_3DNOW() && !p8 && +- (mpg123_cfg.default_synth == SYNTH_3DNOW || ++ (mpg123_cfg.default_synth == SYNTH_3DNOW || + mpg123_cfg.default_synth == SYNTH_AUTO)) + { + fr->synth = funcs[3][ds]; /* 3DNow! optimized synth_1to1() */ +@@ -320,11 +320,11 @@ + if (!strncasecmp(filename, "http://", 7)) + { /* We assume all http:// (except those ending in .ogg) are mpeg -- why do we do that? */ + ext = strrchr(filename, '.'); +- if (ext) ++ if (ext) + { +- if (!strncasecmp(ext, ".ogg", 4)) ++ if (!strncasecmp(ext, ".ogg", 4)) + return FALSE; +- if (!strncasecmp(ext, ".rm", 3) || ++ if (!strncasecmp(ext, ".rm", 3) || + !strncasecmp(ext, ".ra", 3) || + !strncasecmp(ext, ".rpm", 4) || + !strncasecmp(ext, ".fla", 4) || +@@ -534,7 +534,7 @@ + * Function mpg123_get_id3v2 (id3d, tag) + * + * Get desired contents from the indicated id3tag and store it in +- * `tag'. ++ * `tag'. + * + */ + struct id3v2tag_t* mpg123_id3v2_get(struct id3_tag *id3d) +@@ -550,6 +550,10 @@ + tag->track_number = id3v2_get_num(id3d, ID3_TRCK); + tag->comment = id3v2_get_text(id3d, ID3_COMM); + tag->genre = id3v2_get_text(id3d, ID3_TCON); ++ tag->composer = id3v2_get_text(id3d, ID3_TCOM); ++ tag->orig_artist = id3v2_get_text(id3d, ID3_TOPE); ++ tag->url = id3v2_get_text(id3d, ID3_WCOM); ++ tag->encoded_by = id3v2_get_text(id3d, ID3_TENC); + + return tag; + } +@@ -829,7 +833,7 @@ + static int mpg123_seek(struct frame *fr, xing_header_t *xh, gboolean vbr, int time) + { + int jumped = -1; +- ++ + if (xh) + { + int percent = ((double) time * 100.0) / +@@ -995,7 +999,7 @@ + mpg123_info->output_audio = FALSE; + continue; + } +- ++ + } + } + if(mpg123_freqs[fr.sampling_frequency] != mpg123_frequency || mpg123_stereo != fr.stereo) +@@ -1033,12 +1037,12 @@ + mpg123_info->output_audio = FALSE; + continue; + } +- } ++ } + } +- ++ + if (tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index] != mpg123_bitrate) + mpg123_bitrate = tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index]; +- ++ + if (!disp_count) + { + disp_count = 20; +@@ -1154,7 +1158,7 @@ + + if (aboutbox != NULL) + return; +- ++ + aboutbox = xmms_show_message( + _("About MPEG Layer 1/2/3 plugin"), + _("mpg123 decoding engine by Michael Hipp <mh@mpg123.de>\n" +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.h xmms-1.2.11-new/Input/mpg123/mpg123.h +--- xmms-1.2.11/Input/mpg123/mpg123.h 2007-11-24 23:58:20.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.h 2007-11-24 23:58:41.000000000 +0100 +@@ -1,5 +1,5 @@ + /* +- * mpg123 defines ++ * mpg123 defines + * used source: musicout.h from mpegaudio package + */ + +@@ -79,6 +79,10 @@ + char *album; + char *comment; + char *genre; ++ char *composer; ++ char *orig_artist; ++ char *url; ++ char *encoded_by; + int year; + int track_number; + }; +@@ -300,7 +304,6 @@ + int mpg123_decode_header(struct frame *fr, unsigned long newhead); + double mpg123_compute_bpf(struct frame *fr); + double mpg123_compute_tpf(struct frame *fr); +-guint mpg123_strip_spaces(char *src, size_t n); + struct id3v2tag_t* mpg123_id3v2_get(struct id3_tag *id3d); + void mpg123_id3v2_destroy(struct id3v2tag_t* tag); + char *mpg123_format_song_title(struct id3v2tag_t *tag, char *filename); diff --git a/3rdparty/mpg123/2020_all_mpg123-vorbis-ssl.patch b/3rdparty/mpg123/2020_all_mpg123-vorbis-ssl.patch new file mode 100644 index 0000000..453c91b --- /dev/null +++ b/3rdparty/mpg123/2020_all_mpg123-vorbis-ssl.patch @@ -0,0 +1,766 @@ +diff -dPNur xmms-1.2.11/configure.in xmms-1.2.11-new/configure.in +--- xmms-1.2.11/configure.in 2007-11-16 22:52:30.000000000 +0100 ++++ xmms-1.2.11-new/configure.in 2007-11-25 00:00:09.000000000 +0100 +@@ -144,6 +144,22 @@ + fi + AC_SUBST([PTHREAD_LIBS]) + ++dnl *** OpenSSL support ++AC_ARG_ENABLE( ssl, ++[ --disable-ssl Disable HTTP SSL in plugin(s) [default=enabled]],, ++ enable_ssl="yes") ++ ++if test "x$enable_ssl" = xyes; then ++ SSL_LIBS="" ++ AC_CHECK_LIB(ssl, SSL_read, [SSL_LIBS="-lssl" ++ AC_DEFINE(HTTP_SSL,,[Define if OpenSSL is available]) ++ AC_DEFINE(OPENSSL_NO_KRB5,,[Define if OpenSSL is available])], ++ echo "*** SSL support requires openssl and openssl-devel packages ***") ++ LIBS="$LIBS $SSL_LIBS" ++else ++ AC_MSG_RESULT([*** Disabling SSL in plugin(s) per user request ***]) ++ have_ssl=no ++fi + + dnl *** + dnl *** OpenGL +diff -dPNur xmms-1.2.11/Input/mpg123/common.c xmms-1.2.11-new/Input/mpg123/common.c +--- xmms-1.2.11/Input/mpg123/common.c 2007-11-24 23:59:35.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/common.c 2007-11-25 00:00:09.000000000 +0100 +@@ -464,7 +464,11 @@ + void mpg123_open_stream(char *bs_filenam, int fd, unsigned long range) + { + filept_opened = 1; ++#ifdef HTTP_SSL ++ if (!strncasecmp(bs_filenam, "http://", 7) || !strncasecmp(bs_filenam, "https://", 8)) ++#else + if (!strncasecmp(bs_filenam, "http://", 7)) ++#endif + { + filept = NULL; + mpg123_info->filesize = 0; +diff -dPNur xmms-1.2.11/Input/mpg123/http.c xmms-1.2.11-new/Input/mpg123/http.c +--- xmms-1.2.11/Input/mpg123/http.c 2007-11-24 23:53:33.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/http.c 2007-11-25 00:00:09.000000000 +0100 +@@ -33,6 +33,14 @@ + #include "mpg123.h" + #include "libxmms/util.h" + ++#ifdef HTTP_SSL ++#include <openssl/ssl.h> ++#include <openssl/err.h> ++#include <openssl/x509.h> ++#include <openssl/pem.h> ++#include <openssl/crypto.h> ++#endif ++ + #define min(x,y) ((x)<(y)?(x):(y)) + #define min3(x,y,z) (min(x,y)<(z)?min(x,y):(z)) + #define min4(x,y,z,w) (min3(x,y,z)<(w)?min3(x,y,z):(w)) +@@ -117,7 +125,11 @@ + return res; + } + ++#ifdef HTTP_SSL ++static void parse_url(const gchar * url, gchar ** user, gchar ** pass, gchar ** host, int *port, gchar ** filename, int *ssl) ++#else + static void parse_url(const gchar * url, gchar ** user, gchar ** pass, gchar ** host, int *port, gchar ** filename) ++#endif + { + gchar *h, *p, *pt, *f, *temp, *ptr; + +@@ -126,6 +138,14 @@ + + if (!strncasecmp("http://", ptr, 7)) + ptr += 7; ++#ifdef HTTP_SSL ++ if (!strncasecmp("https://", ptr, 8)) { ++ ptr += 8; ++ *ssl = 1; ++ } else ++ *ssl = 0; ++#endif ++ + h = strchr(ptr, '@'); + f = strchr(ptr, '/'); + if (h != NULL && (!f || h < f)) +@@ -160,7 +180,12 @@ + { + if (f) + *f = '\0'; +- *port = 80; ++#ifdef HTTP_SSL ++ if (*ssl) ++ *port = 443; ++ else ++#endif ++ *port = 80; + } + *host = g_strdup(h); + +@@ -302,16 +327,27 @@ + return FALSE; + } + ++#ifdef HTTP_SSL ++gint mpg123_http_read_line(gchar * buf, gint size, SSL *ssl_c) ++#else + gint mpg123_http_read_line(gchar * buf, gint size) ++#endif + { +- gint i = 0; ++ gint i = 0, rc; + + while (going && i < size - 1) + { + if (http_check_for_data()) + { +- if (read(sock, buf + i, 1) <= 0) +- return -1; ++#ifdef HTTP_SSL ++ if (ssl_c) { ++ while ((rc = SSL_read(ssl_c, buf + i, 1)) == -1); ++ if (rc <= 0) ++ return -1; ++ } else ++#endif ++ if (read(sock, buf + i, 1) <= 0) ++ return -1; + if (buf[i] == '\n') + break; + if (buf[i] != '\r') +@@ -342,7 +378,13 @@ + struct sockaddr_in address; + #endif + struct timeval tv; +- ++#ifdef HTTP_SSL ++ SSL *ssl_c = NULL; ++ SSL_CTX *ssl_ctx = NULL; ++ BIO *b = NULL; ++ gint ssl=0; ++#endif ++ + url = (gchar *) arg; + do + { +@@ -350,7 +392,11 @@ + + g_strstrip(url); + ++#ifdef HTTP_SSL ++ parse_url(url, &user, &pass, &host, &port, &filename, &ssl); ++#else + parse_url(url, &user, &pass, &host, &port, &filename); ++#endif + + if ((!filename || !*filename) && url[strlen(url) - 1] != '/') + temp = g_strconcat(url, "/", NULL); +@@ -362,6 +408,26 @@ + chost = mpg123_cfg.use_proxy ? mpg123_cfg.proxy_host : host; + cport = mpg123_cfg.use_proxy ? mpg123_cfg.proxy_port : port; + ++#ifdef HTTP_SSL ++ if (ssl) { ++ SSL_library_init(); ++ OpenSSL_add_ssl_algorithms(); ++ SSL_load_error_strings(); ++ ++ ssl_ctx = SSL_CTX_new(SSLv23_client_method()); ++ if (ssl_ctx == NULL) { ++ fprintf(stderr, "SSL_CTX_new() failed."); ++ eof = TRUE; ++ } ++ ++ ssl_c = SSL_new(ssl_ctx); ++ if (ssl_c == NULL) { ++ fprintf(stderr, "SSL_new() failed.\n"); ++ eof = TRUE; ++ } ++ } ++#endif ++ + #ifdef USE_IPV6 + g_snprintf(service, 6, "%d", cport); + memset(&hints, 0, sizeof(hints)); +@@ -441,7 +507,20 @@ + eof = TRUE; + } + } ++#ifdef HTTP_SSL ++ if (ssl) { ++ b = BIO_new_socket(sock, BIO_NOCLOSE); ++ if (b == NULL) { ++ printf("BIO_new_socket() failed.\n"); ++ eof = TRUE; ++ } ++ ++ // cannot fail ++ SSL_set_bio(ssl_c, b, b); ++ } ++#endif + #endif ++ + while (going) + { + tv.tv_sec = 0; +@@ -466,6 +545,24 @@ + break; + } + } ++#ifdef HTTP_SSL ++ if (ssl) { ++ int rc; ++ ++ SSL_set_connect_state(ssl_c); ++ ++ while ((rc = SSL_connect(ssl_c)) == -1); ++ if (rc <= 0) { ++ fprintf(stderr, "SSL_connect() error. SSL error code: %d.\n", ++ SSL_get_error(ssl_c, rc)); ++ } ++ while ((rc = SSL_do_handshake(ssl_c)) == -1); ++ if (rc <= 0) { ++ fprintf(stderr, "SSL_do_handshake() error. SSL error code: %d.\n", ++ SSL_get_error(ssl_c, rc)); ++ } ++ } ++#endif + if (!eof) + { + gchar *auth = NULL, *proxy_auth = NULL; +@@ -517,14 +614,30 @@ + g_free(proxy_auth); + if(auth) + g_free(auth); +- write(sock, temp, strlen(temp)); ++#ifdef HTTP_SSL ++ if (ssl) { ++ int rc; ++ while ((rc = SSL_write(ssl_c, temp, strlen(temp))) == -1); ++ if (rc <= 0) { ++ fprintf(stderr, "SSL_write() error. SSL error code: %d.\n", ++ SSL_get_error(ssl_c, rc)); ++ eof = TRUE; ++ } ++ } else ++#endif ++ write(sock, temp, strlen(temp)); ++ + g_free(temp); + mpg123_ip.set_info_text(_("CONNECTED: WAITING FOR REPLY")); + while (going && !eof) + { + if (http_check_for_data()) + { ++#ifdef HTTP_SSL ++ if (mpg123_http_read_line(line, 1024, ssl_c)) ++#else + if (mpg123_http_read_line(line, 1024)) ++#endif + { + status = strchr(line, ' '); + if (status) +@@ -537,7 +650,11 @@ + { + if(http_check_for_data()) + { ++#ifdef HTTP_SSL ++ if((cnt = mpg123_http_read_line(line, 1024, ssl_c)) != -1) ++#else + if((cnt = mpg123_http_read_line(line, 1024)) != -1) ++#endif + { + if(!cnt) + break; +@@ -579,7 +696,11 @@ + { + if (http_check_for_data()) + { ++#ifdef HTTP_SSL ++ if ((cnt = mpg123_http_read_line(line, 1024, ssl_c)) != -1) ++#else + if ((cnt = mpg123_http_read_line(line, 1024)) != -1) ++#endif + { + if (!cnt) + break; +@@ -617,6 +738,10 @@ + fclose(output_file); + output_file = NULL; + } ++#ifdef HTTP_SSL ++ if (ssl) ++ SSL_shutdown(ssl_c); ++#endif + close(sock); + g_free(user); + g_free(pass); +@@ -634,6 +759,10 @@ + fname = file; + if (!strncasecmp(fname, "http://", 7)) + fname += 7; ++#ifdef HTTP_SSL ++ if (!strncasecmp(fname, "https://", 8)) ++ fname += 8; ++#endif + temp = strrchr(fname, '.'); + if (temp && !strcasecmp(temp, ".mp3")) + *temp = '\0'; +@@ -668,7 +797,12 @@ + cnt = min(http_free(), buffer_length - wr_index); + if (cnt > 1024) + cnt = 1024; +- written = read(sock, buffer + wr_index, cnt); ++#ifdef HTTP_SSL ++ if (ssl) ++ while ((written = SSL_read(ssl_c, buffer + wr_index, cnt)) == -1); ++ else ++#endif ++ written = read(sock, buffer + wr_index, cnt); + if (written <= 0) + { + eof = TRUE; +@@ -715,6 +849,10 @@ + fclose(output_file); + output_file = NULL; + } ++#ifdef HTTP_SSL ++ if (ssl) ++ SSL_shutdown(ssl_c); ++#endif + close(sock); + if (udp_sock != 0) + close(udp_sock); +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.c xmms-1.2.11-new/Input/mpg123/mpg123.c +--- xmms-1.2.11/Input/mpg123/mpg123.c 2007-11-24 23:59:35.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.c 2007-11-25 00:00:09.000000000 +0100 +@@ -317,7 +317,11 @@ + char *ext; + guint16 wavid; + ++#ifdef HTTP_SSL ++ if (!strncasecmp(filename, "http://", 7) || !strncasecmp(filename, "https://", 8)) ++#else + if (!strncasecmp(filename, "http://", 7)) ++#endif + { /* We assume all http:// (except those ending in .ogg) are mpeg -- why do we do that? */ + ext = strrchr(filename, '.'); + if (ext) +@@ -801,7 +805,11 @@ + /* + * TODO: Getting song info from http streams. + */ ++#ifdef HTTP_SSL ++ if (strncasecmp(filename, "http://", 7) && strncasecmp(filename, "https://", 8)) ++#else + if (strncasecmp(filename, "http://", 7)) ++#endif + { + if ((file = fopen(filename, "rb")) != NULL) + { +@@ -890,7 +898,12 @@ + mpg123_init_layer3(fr.down_sample_sblimit); + + mpg123_info->tpf = mpg123_compute_tpf(&fr); ++ ++#ifdef HTTP_SSL ++ if (strncasecmp(filename, "http://", 7) && strncasecmp(filename, "https://", 8)) ++#else + if (strncasecmp(filename, "http://", 7)) ++#endif + { + if (mpg123_stream_check_for_xing_header(&fr, &xing_header)) + { +@@ -937,7 +950,11 @@ + mpg123_mode = fr.mode; + mpg123_length = mpg123_info->num_frames * mpg123_info->tpf * 1000; + ++#ifdef HTTP_SSL ++ if (strncasecmp(filename, "http://", 7) && strncasecmp(filename, "https://", 8)) ++#else + if (strncasecmp(filename, "http://", 7)) ++#endif + { + if (!mpg123_title) + mpg123_title = get_song_title(NULL,filename); +@@ -1050,7 +1067,11 @@ + { + /* FIXME networks streams */ + disp_bitrate = mpg123_bitrate; ++#ifdef HTTP_SSL ++ if(!have_xing_header && strncasecmp(filename,"http://",7) && strncasecmp(filename, "https://", 8)) ++#else + if(!have_xing_header && strncasecmp(filename,"http://",7)) ++#endif + { + double rel = mpg123_relative_pos(); + if (rel) +diff -dPNur xmms-1.2.11/Input/vorbis/fileinfo.c xmms-1.2.11-new/Input/vorbis/fileinfo.c +--- xmms-1.2.11/Input/vorbis/fileinfo.c 2005-05-15 02:01:20.000000000 +0200 ++++ xmms-1.2.11-new/Input/vorbis/fileinfo.c 2007-11-25 00:00:09.000000000 +0100 +@@ -227,7 +227,12 @@ + vcedit_state *state; + vorbis_comment *comment; + ++#ifdef HTTP_SSL ++ if (!g_strncasecmp(vte.filename, "http://", 7) || ++ !g_strncasecmp(vte.filename, "https://", 8)) ++#else + if (!g_strncasecmp(vte.filename, "http://", 7)) ++#endif + return; + + state = vcedit_new_state(); +@@ -303,7 +308,12 @@ + vcedit_state *state; + vorbis_comment *comment; + ++#ifdef HTTP_SSL ++ if (!g_strncasecmp(vte.filename, "http://", 7) || ++ !g_strncasecmp(vte.filename, "https://", 8)) ++#else + if (!g_strncasecmp(vte.filename, "http://", 7)) ++#endif + return; + + state = vcedit_new_state(); +@@ -800,7 +810,12 @@ + } else + gdk_window_raise(window->window); + ++#ifdef HTTP_SSL ++ if (!g_strncasecmp(vte.filename, "http://", 7) || ++ !g_strncasecmp(vte.filename, "https://", 8)) ++#else + if (!g_strncasecmp(vte.filename, "http://", 7)) ++#endif + gtk_widget_set_sensitive(tag_frame, FALSE); + else + gtk_widget_set_sensitive(tag_frame, TRUE); +diff -dPNur xmms-1.2.11/Input/vorbis/http.c xmms-1.2.11-new/Input/vorbis/http.c +--- xmms-1.2.11/Input/vorbis/http.c 2007-11-16 22:51:24.000000000 +0100 ++++ xmms-1.2.11-new/Input/vorbis/http.c 2007-11-25 00:03:11.000000000 +0100 +@@ -39,6 +39,10 @@ + #include "xmms/plugin.h" + #include "xmms/i18n.h" + ++#ifdef HTTP_SSL ++#include <openssl/ssl.h> ++#endif ++ + #define min(x,y) ((x)<(y)?(x):(y)) + #define min3(x,y,z) (min(x,y)<(z)?min(x,y):(z)) + #define min4(x,y,z,w) (min3(x,y,z)<(w)?min3(x,y,z):(w)) +@@ -116,7 +120,11 @@ + return res; + } + ++#ifdef HTTP_SSL ++static void parse_url(const gchar * url, gchar ** user, gchar ** pass, gchar ** host, int *port, gchar ** filename, int *ssl) ++#else + static void parse_url(const gchar * url, gchar ** user, gchar ** pass, gchar ** host, int *port, gchar ** filename) ++#endif + { + gchar *h, *p, *pt, *f, *temp, *ptr; + +@@ -125,6 +133,14 @@ + + if (!strncasecmp("http://", ptr, 7)) + ptr += 7; ++#ifdef HTTP_SSL ++ if (!strncasecmp("https://", ptr, 8)) { ++ ptr += 8; ++ *ssl = 1; ++ } else ++ *ssl = 0; ++#endif ++ + h = strchr(ptr, '@'); + f = strchr(ptr, '/'); + if (h != NULL && (!f || h < f)) +@@ -159,7 +175,12 @@ + { + if (f) + *f = '\0'; +- *port = 80; ++#ifdef HTTP_SSL ++ if (*ssl) ++ *port = 443; ++ else ++#endif ++ *port = 80; + } + *host = g_strdup(h); + +@@ -257,16 +278,27 @@ + return FALSE; + } + ++#ifdef HTTP_SSL ++gint vorbis_http_read_line(gchar * buf, gint size, SSL *ssl_c) ++#else + gint vorbis_http_read_line(gchar * buf, gint size) ++#endif + { +- gint i = 0; ++ gint i = 0, rc; + + while (going && i < size - 1) + { + if (http_check_for_data()) + { +- if (read(sock, buf + i, 1) <= 0) +- return -1; ++#ifdef HTTP_SSL ++ if (ssl_c) { ++ while ((rc = SSL_read(ssl_c, buf + i, 1)) == -1); ++ if (rc <= 0) ++ return -1; ++ } else ++#endif ++ if (read(sock, buf + i, 1) <= 0) ++ return -1; + if (buf[i] == '\n') + break; + if (buf[i] != '\r') +@@ -296,6 +328,12 @@ + struct sockaddr_in address; + #endif + struct timeval tv; ++#ifdef HTTP_SSL ++ SSL *ssl_c = NULL; ++ SSL_CTX *ssl_ctx = NULL; ++ BIO *b = NULL; ++ gint ssl=0; ++#endif + + url = (gchar *) arg; + do +@@ -304,7 +342,11 @@ + + g_strstrip(url); + ++#ifdef HTTP_SSL ++ parse_url(url, &user, &pass, &host, &port, &filename, &ssl); ++#else + parse_url(url, &user, &pass, &host, &port, &filename); ++#endif + + if ((!filename || !*filename) && url[strlen(url) - 1] != '/') + temp = g_strconcat(url, "/", NULL); +@@ -316,6 +358,26 @@ + chost = vorbis_cfg.use_proxy ? vorbis_cfg.proxy_host : host; + cport = vorbis_cfg.use_proxy ? vorbis_cfg.proxy_port : port; + ++#ifdef HTTP_SSL ++ if (ssl) { ++ SSL_library_init(); ++ OpenSSL_add_ssl_algorithms(); ++ SSL_load_error_strings(); ++ ++ ssl_ctx = SSL_CTX_new(SSLv23_client_method()); ++ if (ssl_ctx == NULL) { ++ fprintf(stderr, "SSL_CTX_new() failed."); ++ eof = TRUE; ++ } ++ ++ ssl_c = SSL_new(ssl_ctx); ++ if (ssl_c == NULL) { ++ fprintf(stderr, "SSL_new() failed.\n"); ++ eof = TRUE; ++ } ++ } ++#endif ++ + #ifdef USE_IPV6 + g_snprintf(service, 6, "%d", cport); + memset(&hints, 0, sizeof(hints)); +@@ -394,6 +456,18 @@ + eof = TRUE; + } + } ++#ifdef HTTP_SSL ++ if (ssl) { ++ b = BIO_new_socket(sock, BIO_NOCLOSE); ++ if (b == NULL) { ++ printf("BIO_new_socket() failed.\n"); ++ eof = TRUE; ++ } ++ ++ // cannot fail ++ SSL_set_bio(ssl_c, b, b); ++ } ++#endif + #endif + while (going) + { +@@ -419,6 +493,24 @@ + break; + } + } ++#ifdef HTTP_SSL ++ if (ssl) { ++ int rc; ++ ++ SSL_set_connect_state(ssl_c); ++ ++ while ((rc = SSL_connect(ssl_c)) == -1); ++ if (rc <= 0) { ++ fprintf(stderr, "SSL_connect() error. SSL error code: %d.\n", ++ SSL_get_error(ssl_c, rc)); ++ } ++ while ((rc = SSL_do_handshake(ssl_c)) == -1); ++ if (rc <= 0) { ++ fprintf(stderr, "SSL_do_handshake() error. SSL error code: %d.\n", ++ SSL_get_error(ssl_c, rc)); ++ } ++ } ++#endif + if (!eof) + { + gchar *auth = NULL, *proxy_auth = NULL; +@@ -449,14 +541,30 @@ + g_free(proxy_auth); + if(auth) + g_free(auth); +- write(sock, temp, strlen(temp)); ++#ifdef HTTP_SSL ++ if (ssl) { ++ int rc; ++ while ((rc = SSL_write(ssl_c, temp, strlen(temp))) == -1); ++ if (rc <= 0) { ++ fprintf(stderr, "SSL_write() error. SSL error code: %d.\n", ++ SSL_get_error(ssl_c, rc)); ++ eof = TRUE; ++ } ++ } else ++#endif ++ write(sock, temp, strlen(temp)); ++ + g_free(temp); + vorbis_ip.set_info_text(_("CONNECTED: WAITING FOR REPLY")); + while (going && !eof) + { + if (http_check_for_data()) + { ++#ifdef HTTP_SSL ++ if (vorbis_http_read_line(line, 1024, ssl_c)) ++#else + if (vorbis_http_read_line(line, 1024)) ++#endif + { + status = strchr(line, ' '); + if (status) +@@ -469,7 +577,11 @@ + { + if(http_check_for_data()) + { ++#ifdef HTTP_SSL ++ if((cnt = vorbis_http_read_line(line, 1024, ssl_c)) != -1) ++#else + if((cnt = vorbis_http_read_line(line, 1024)) != -1) ++#endif + { + if(!cnt) + break; +@@ -511,7 +623,11 @@ + { + if (http_check_for_data()) + { ++#ifdef HTTP_SSL ++ if ((cnt = vorbis_http_read_line(line, 1024, ssl_c)) != -1) ++#else + if ((cnt = vorbis_http_read_line(line, 1024)) != -1) ++#endif + { + if (!cnt) + break; +@@ -537,6 +653,10 @@ + fclose(output_file); + output_file = NULL; + } ++#ifdef HTTP_SSL ++ if (ssl) ++ SSL_shutdown(ssl_c); ++#endif + close(sock); + g_free(user); + g_free(pass); +@@ -554,6 +674,9 @@ + fname = file; + if (!strncasecmp(fname, "http://", 7)) + fname += 7; ++ if (!strncasecmp(fname, "https://", 8)) ++ fname += 8; ++ + temp = strrchr(fname, '.'); + if (temp && !strcasecmp(temp, ".ogg")) + *temp = '\0'; +@@ -588,7 +711,12 @@ + cnt = min(http_free(), buffer_length - wr_index); + if (cnt > 1024) + cnt = 1024; +- written = read(sock, buffer + wr_index, cnt); ++#ifdef HTTP_SSL ++ if (ssl) ++ while ((written = SSL_read(ssl_c, buffer + wr_index, cnt)) == -1); ++ else ++#endif ++ written = read(sock, buffer + wr_index, cnt); + if (written <= 0) + { + eof = TRUE; +@@ -629,6 +757,10 @@ + fclose(output_file); + output_file = NULL; + } ++#ifdef HTTP_SSL ++ if (ssl) ++ SSL_shutdown(ssl_c); ++#endif + close(sock); + + +diff -dPNur xmms-1.2.11/Input/vorbis/vorbis.c xmms-1.2.11-new/Input/vorbis/vorbis.c +--- xmms-1.2.11/Input/vorbis/vorbis.c 2006-07-16 15:40:04.000000000 +0200 ++++ xmms-1.2.11-new/Input/vorbis/vorbis.c 2007-11-25 00:00:09.000000000 +0100 +@@ -138,7 +138,12 @@ + char *ext; + + /* is this our http resource? */ ++#ifdef HTTP_SSL ++ if (strncasecmp(filename, "http://", 7) == 0 || ++ strncasecmp(filename, "https://", 8) == 0) { ++#else + if (strncasecmp(filename, "http://", 7) == 0) { ++#endif + ext = strrchr(filename, '.'); + if (ext) { + if (!strncasecmp(ext, ".ogg", 4)) { +@@ -332,7 +337,12 @@ + + memset(&vf, 0, sizeof(vf)); + ++#ifdef HTTP_SSL ++ if (strncasecmp("http://", filename, 7) && ++ strncasecmp("https://", filename, 8)) { ++#else + if (strncasecmp("http://", filename, 7) != 0) { ++#endif + /* file is a real file */ + if ((stream = fopen(filename, "r")) == NULL) { + vorbis_eos = TRUE; +@@ -536,7 +546,12 @@ + FILE *stream; + OggVorbis_File vf; /* avoid thread interaction */ + ++#ifdef HTTP_SSL ++ if (strncasecmp(filename, "http://", 7) && ++ strncasecmp(filename, "https://", 8)) { ++#else + if (strncasecmp(filename, "http://", 7)) { ++#endif + if ((stream = fopen(filename, "r")) == NULL) + return; + @@ -0,0 +1,86 @@ +Prerequisites +------------- + The patched XMMS can be compiled without any additional dependency, + but to get recoding on you will need LibRCC (http://rusxmms.sf.net). + The LibRCC (Russian Charset Conversion Library) supports several + ways of encoding autodetection. To get this feature on the LibRCD, + Enca, db4 libraries should be installed prior to LibRCC compilation. + + Starting from version 0.2.0 LibRCC supports language autodetection using + aspell and language translation using libtranslate (the internet connection + is required). + + So, to get fully functional system, with multi-language playlist recoding, + you will need following libraries: + 1. LibRCD (http://rusxmms.sf.net) + 2. Enca + 3. DB4 (Brekley DB) + 4. LibXML2 + 5. LibRCC + To get language auto-detection: + 6. Aspell with dictionaries + To get language translation: + 7. Libtranslate + Internet Connection + +Compilation +----------- +1. Copy RusXMMS into the root of xmms source distribution + Run 'apply.sh' to get RusXMMS with ID3v2 enabled mpg123 + * Patches from Gentoo XMMS Distribution is used to provide ID3v2 + Custom: Just apply patches you need + * all files from source/*.[ch] should be copied into the + libxmms directory +2. Run 'aclocal && automake && autoconf' in the root of XMMS source tree in + order to regenerate Makefiles. +3. configure, compile and install as usual + +Patches +------- + xmms-ds-rusxmms: Base RusXMMS patch (required!) + xmms-ds-rusxmms-charset: UTF16/RCC for libxmms/charset.c. + * Required by Id3v2 tag editor. + xmms-ds-playlist: PlayList Recoding (Save/Load/Display) + * Recodes file names from playlist files + * Recodes titles from playlist files + * Recodes titles from plugins if AutoEngine enabled + xmms-ds-shade: Enables font selection for Shade Windows + * After applying the non-English titles will be + displayed correctly in the shade window + xmms-ds-textbox: Corrects UTF-8 displaying in xmms 'TextBox' + + xmms-ds-mpg123: Recodes mpg123 titles + editor: Enables editing of ID3 tags (v.1 and v.2) + keys: Enables fast keys + Esc, Enter: Cancel, Save and Exit + Ctrl+Left, Ctrl+Right: Navigate tabs + Ctrl+PgDn, Ctrl+PgUp: Navigate records + xmms-ds-vorbis-*: The same functionalities for vorbis plugin + ( No recoding patch is required ) + +Extra Patches +------------- + Some extra functionality, which is not included in default "apply.sh" + scripts and could be considered a bad or/and dangerous idea. + + xmms-ds-mpg123-wrongencoding.patch: + The ID3 v.2 defines 4 types of encodings: Latin1, UTF16, UTF16BE, UTF8. + Original version of XMMS assumes the tag broken if other encoding is + specified. This patch, assumes Latin1 for such encodings. + +Minimal Configurations: + xmms-ds-rusxmms + xmms-ds-playlist: + In the case then the autoengine is available, this solution will + give completely recoded playlist window. The recoding of plugins + will work as well. + xmms-ds-rusxmms + xmms-ds-mpg123(no editor and keys): + This solution will give completely recoded playlist even if no + autoengine is available, but playlists are unsupported. + +Notes +----- + * Edited ID3 tags and playlists will be saved in the corresponded + encodings selected using 'RusXMMS' preference page. + + +Project Page: http://rusxmms.sf.net +Author: Suren A. Chilingaryan <darksoft@dside.dyndns.org> diff --git a/apply.sh b/apply.sh new file mode 100755 index 0000000..69c4ea4 --- /dev/null +++ b/apply.sh @@ -0,0 +1,50 @@ +#! /bin/bash + +TOP_DIR=`pwd | sed -e s/\\\/RusXMMS2$//` +if [ ! -d $TOP_DIR/RusXMMS2 ]; then + PATCH_DIR=$TOP_DIR/../ + if [ ! -d $PATCH_DIR/RusXMMS2 ]; then + exit 1 + fi +else + PATCH_DIR=$TOP_DIR +fi + +if [ ! -d $TOP_DIR/libxmms ]; then + exit 1 +fi + +echo "Patching: $TOP_DIR" + +cp $PATCH_DIR/RusXMMS2/source/* $TOP_DIR/libxmms/ + +# ID3 fixes +cat $PATCH_DIR/RusXMMS2/3rdparty/mpg123/*.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** gentoo mpg123 patches ***"; exit 1; fi + +# RusXMMS core +cat $PATCH_DIR/RusXMMS2/patches/xmms-ds-rusxmms.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-rusxmms ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/xmms-ds-rusxmms-charset.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-rusxmms-charset ***"; exit 1; fi + +# RusXMMS plugins +cat $PATCH_DIR/RusXMMS2/patches/plugins/xmms-ds-mpg123.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-mpg123 ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/plugins/xmms-ds-mpg123-editor.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-mpg123-editor ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/plugins/xmms-ds-mpg123-editor-keys.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-mpg123-editor-keys ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/plugins/xmms-ds-vorbis-editor.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-vorbis-editor ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/plugins/xmms-ds-vorbis-editor-keys.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-vorbis-editor-keys ***"; exit 1; fi + +# RusXMMS extra +cat $PATCH_DIR/RusXMMS2/patches/xmms-ds-playlist.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-playlist ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/xmms-ds-shade.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-shade ***"; exit 1; fi +cat $PATCH_DIR/RusXMMS2/patches/xmms-ds-textbox.patch | patch -d $TOP_DIR -p1 +if [ $? -ne 0 ]; then echo -e "\n[01;31mFailed:[00m *** xmms-ds-textbox ***"; exit 1; fi + diff --git a/configs/libtranslate/services.xml b/configs/libtranslate/services.xml new file mode 100644 index 0000000..14d0548 --- /dev/null +++ b/configs/libtranslate/services.xml @@ -0,0 +1,258 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE services SYSTEM "services.dtd"> +<services> + <custom-language tag="zh-TW" name="Chinese (Taiwan)"/> + + <service nick="Google" name="google"> + <group> + <language to="*" tag="en"/> + <language to="en,de" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en" tag="it"/> + <language to="en" tag="pt"/> + <language to="en" tag="es"/> + <language to="en" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en" tag="ar"/> + <text-translation url="http://www.google.com/translate_t?text=${text:escape}&langpair=${from}|${to}&ie=utf8&oe=utf8"> + <pre-marker text="id=result_box"/> + <pre-marker text="mouseover"/> + <pre-marker text=">"/> + <post-marker text="<br>"/> + </text-translation> + <web-page-translation url="http://www.google.com/translate_c?u=${url:escape}&langpair=${from}|${to}"/> + </group> + </service> + + <service nick="FreeTranslation" name="freetranslation" max-chunk-len="600"> + <group> + <language to="en" tag="nl" service-tag="dutch"/> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="fr" service-tag="french"/> + <language to="en" tag="de" service-tag="german"/> + <language to="en" tag="it" service-tag="italian"/> + <language tag="no" service-tag="norwegian"/> + <language to="en" tag="pt" service-tag="portuguese"/> + <language to="en" tag="es" service-tag="spanish"/> + <text-translation url="http://ets.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + <web-page-translation url="http://fets5.freetranslation.com/?sequence=core&url=${url:escape}&language=${from}/${to}"/> + </group> + <group> + <language tag="zh" service-tag="simplifiedchinese"/> + <language tag="zh-TW" service-tag="traditionalchinese"/> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="ru" service-tag="russian"/> + <text-translation url="http://ets6.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + </group> + <group> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="ja" service-tag="japanese"/> + <text-translation url="http://tets9.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + </group> + </service> + + <service nick="Pereklad" name="pereklad"> + <group> + <language to="*" tag="ru" service-tag="Rus"/> + <language to="*" tag="uk" service-tag="Ukr"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="*" tag="en" service-tag="Eng"/> + <language to="*" tag="de" service-tag="Ger"/> + <language to="*" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="en,de,fr" tag="ru" service-tag="Rus"/> + <language to="en,de,fr" tag="uk" service-tag="Ukr"/> + <language to="" tag="en" service-tag="Eng"/> + <language to="" tag="de" service-tag="Ger"/> + <language to="" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="ru" service-tag="Rus"/> + <language to="" tag="uk" service-tag="Ukr"/> + <language to="ru,uk" tag="en" service-tag="Eng"/> + <language to="ru,uk" tag="de" service-tag="Ger"/> + <language to="ru,uk" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="ru" service-tag="Rus"/> + <language to="" tag="uk" service-tag="Ukr"/> + <language to="ru,uk" tag="lv" service-tag="Lat"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="*" tag="lv" service-tag="Lat"/> + <language to="" tag="en" service-tag="Eng"/> + <language to="" tag="de" service-tag="Ger"/> + <language to="" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="lv" service-tag="Lat"/> + <language to="lv" tag="ru" service-tag="Rus"/> + <language to="lv" tag="uk" service-tag="Ukr"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-4"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="lv" service-tag="Lat"/> + <language to="lv" tag="en" service-tag="Eng"/> + <language to="lv" tag="de" service-tag="Ger"/> + <language to="lv" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-4"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + </service> + + <service nick="Promt" name="promt"> + <group> + <language to="*" tag="ru" service-tag="r"/> + <language to="ru,de,fr,es" tag="en" service-tag="e"/> + <language to="ru,en,fr,es" tag="de" service-tag="g"/> + <language to="ru,en,de,es" tag="fr" service-tag="f"/> + <language to="ru,en" tag="it" service-tag="i"/> + <language to="ru,en,de,fr" tag="es" service-tag="s"/> + <language to="en" tag="pt" service-tag="p"/> + <text-translation + url="http://www.translate.ru/Default.aspx/Text" + post="__EVENTTARGET=&__EVENTTARGUMENT=&ctl00$SiteContent$MA_trasnlform$bTranslate=Translate&ctl00$SiteContent$MA_trasnlform$DropDownList2=&ctl00$SiteContent$trasnlform$sLang=${from}&ctl00$SiteContent$MA_trasnlform$rLang=${to}&ctl00$SiteContent$MA_trasnlform$sourceText=${text:escape}&ctl00$SiteContent$MA_trasnlform$rblTemplates=General"> + <pre-marker text="ctl00$SiteContent$MA_trasnlform$tbPismo"/> + <pre-marker text=">"/> + <post-marker text="</textarea"/> + + </text-translation> + </group> + </service> + + <service nick="SYSTRAN" name="systran"> + <group> + <language to="en" tag="ar"/> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW" service-tag="zt"/> + <language to="en,fr" tag="nl"/> + <language to="*" tag="en"/> + <language to="nl,en,de,it,pt,es" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en,fr" tag="it"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en,fr" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en,fr" tag="es"/> + <language to="en" tag="sv"/> + <http-header value="http://www.systransoft.com/" name="Referer"/> + <text-translation + url="http://www.systranet.com/tt?lp=${from}_${to}&service=translate" + post=". ${text}."> + <pre-marker text=". "/> + <post-marker text="."/> + </text-translation> + </group> + </service> + + <service nick="Babel Fish" name="babelfish"> + <group> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW" service-tag="zt"/> + <language to="*" tag="en"/> + <language to="en,fr" tag="nl"/> + <language to="en,de,el,it,pt,nl,es" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en,fr" tag="el"/> + <language to="en,fr" tag="it"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en,fr" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en,fr" tag="es"/> + <text-translation + url="http://babelfish.yahoo.com/translate_txt" + post="trtext=${text:escape}&lp=${from}_${to}&ei=UTF-8"> + <pre-marker text="id="result""/> + <pre-marker text="<div"/> + <pre-marker text=">"/> + <post-marker text="</div"/> + </text-translation> +<!-- + <web-page-translation url="http://babelfish.altavista.com/babelfish/trurl_load?url=${url:escape}&lp=${from}_${to}&enc=utf8"/> +!--> + </group> + </service> + +<!-- + <service nick="Kataku" name="kataku"> + <group> + <language to="*" tag="en"/> + <language to="*" tag="id" service-tag="in"/> + <text-translation url="http://www.toggletext.com/kataku_trial.php" post="input_text=${text:charset=ISO8859-1,escape}&langset_text=${from}_${to}"> + <pre-marker text="Translation:"/> + <pre-marker text="<pre"/> + <pre-marker text=">"/> + <post-marker text=" </pre>"/> + </text-translation> + <web-page-translation url="http://www.toggletext.com/kataku_webpage_translate.php?input=${url:escape}&langset=${from}_${to}"/> + </group> + </service> +--> + +</services>
\ No newline at end of file diff --git a/configs/xmms/config b/configs/xmms/config new file mode 100644 index 0000000..f3094a0 --- /dev/null +++ b/configs/xmms/config @@ -0,0 +1,5 @@ +[xmms] +playlist_font=-misc-ar pl shanheisun uni-medium-r-normal-*-14-*-*-*-p-*-iso10646-1 +use_fontsets=TRUE +mainwin_use_xfont=TRUE +mainwin_font=-misc-ar pl shanheisun uni-medium-r-normal-*-14-*-*-*-p-*-iso10646-1 diff --git a/docs/Notes.txt b/docs/Notes.txt new file mode 100644 index 0000000..c0a998d --- /dev/null +++ b/docs/Notes.txt @@ -0,0 +1,27 @@ +Fonts +===== +Some fonts used together with certain broken ID3 strings (for example having +chinese tags in ru_RU.KOI8-R locale) causes my Xorg system to crash. +For, example: + -misc-ar pl new sung-medium-r-normal-*-*-100-*-*-c-*-iso10646-1 + +The tested font configuration for RusXMMS (KOI8 locale) is: + shade_font=-misc-fixed-medium-r-semicondensed-*-*-120-*-*-c-*-koi8-r + playlist_font=-adobe_koi8_1-helvetica-bold-r-*-*-10-* + mainwin_font=-adobe_koi8_1-helvetica-medium-r-*-*-8-* + +Fonts containing both cyrillic and chinese glyphs + Arphic family + +Autotools +========== +I got a problem with autotools 1.9 (complaining about invalid AM_PROG_LIBTOOL), +with 1.10 everything is smooth. + +Checking Actual Tags +==================== + eyeD3 --debug -v + reports invalid ecnodings as latin1 + + eyeD3 --strict --debug -v + throws ValueError exception on invalid encoding diff --git a/docs/RusXMMS2.sxw b/docs/RusXMMS2.sxw Binary files differnew file mode 100644 index 0000000..834c24c --- /dev/null +++ b/docs/RusXMMS2.sxw diff --git a/docs/RusXMMS2.sxw.pdf b/docs/RusXMMS2.sxw.pdf Binary files differnew file mode 100644 index 0000000..c3df222 --- /dev/null +++ b/docs/RusXMMS2.sxw.pdf diff --git a/docs/patches/amarok.txt b/docs/patches/amarok.txt new file mode 100644 index 0000000..e2f6b5d --- /dev/null +++ b/docs/patches/amarok.txt @@ -0,0 +1,27 @@ +Amarok (1.4.8) ÕÓÔÒÏÅÎ ÐÒÉÍÅÒÎÏ ÓÌÅÄÕÀÝÉÍ ÏÂÒÁÚÏÍ. åÓÌÉ ÍÙ ÉÍÅÅÍ ÄÅÌÏ Ó +ÌÏËÁÌØÎÙÍÉ ÆÁÊÌÁÍÉ, ÔÏ ×ÓÅ ÔÜÇÉ ÐÏÌÕÞÁÀÔÓÑ ÞÅÒÅÚ Taglib (× ÆÕÎËÃÉÉ +MetaBundle::readTags ÉÚ metabundle.cpp). + +ïÄÎÁËÏ, taglib (1.5 É ÒÁÎØÛÅ) ÎÅ ÕÍÅÅÔ ÚÁ ÔÁÇÁÍÉ ÐÏ ÓÅÔÉ ÌÁÚÉÔØ. ðÏ-ÜÔÏÍÕ +smb, nfs É Ô.Ð. ÏÂÒÁÂÁÔÙ×ÁÀÔÓÑ ÐÏ ÄÒÕÇÏÍÕ. +1. ÷Ï-ÐÅÒ×ÙÈ × ÔÏÍÖÅ metabundle.cpp ÅÓÔØ: + MetaBundle::init( const KFileMetaInfo& info ) + ËÏÔÏÒÙÊ ÍÏÖÅÔ ÐÒÉÎÉÍÁÔØ ÔÜÇÉ × ÎÅËÏÊ KDEÛÎÏÊ ÓÔÒÕËÔÕÒÕ. ðÏÄÏÚÒÅ×ÁÀ, ÞÔÏ + ÜÔÏ Ó×ÑÚÁÎÏ Ó KIO. ÷ÐÒÏÞÅÍ, ÎÅ×ÁÖÎÏ ÄÌÑ SMB ÆÁÊÌÏ× ÜÔÁ ÆÕÎËÃÉÑ ÎÅ ÚÁÐÕÓËÁÅÔÓÑ. +2. òÅÁÌØÎÏ ÄÌÑ smb ÆÁÊÌÏ× ÔÜÇÉ ÌÏ×ÑÔÓÑ ÆÕÎËÃÉÅÊ slotEngineMetaData (ÉÚ + enginecontroller.cpp). ÷ÙÚÙ×ÁÅÔÓÑ ÄÁÎÎÁÑ ÆÕÎËÃÉÑ ÐÏ ÐÒÉÈÏÄÕ ÓÉÇÎÁÌÁ + "metaData". + + îÁÓËÏÌØËÏ Ñ ÐÏÎÑÌ, ÄÁÎÎÙÊ ÓÉÇÎÁÌ ÐÏÓÙÌÁÀÔ ×ÓÑËÉÅ enginÙ, ËÏÔÏÒÙÅ ÐÒÏÉÇÒÙ×ÁÀÔ + ÍÕÚÙËÕ ÄÌÑ ÁÍÁÒÏË. ôÉÐÁ engine/yauap, engine/xine É Ô.Ð. ÷ÏÔ ×ÉÄÁÔØ ÏÎÉ + ÞÉÔÁÀÔ ÔÜÇÉ (ËÒÉ×Ï, ÐÏÓËÏÌØËÕ ÎÅ Ó ÌÉÎËÏ×ÁÎÙ Ó taglib ÉÌÉ ÅÝÅ ÞÅÍ Ó RusXMMS + ÐÁÔÞÅÍ). + +3. íÏÖÅÔ ÅÝÅ ÞÅÇÏ ÅÓÔØ ;) + + +÷ÏÏÂÝÅÍ, ÒÅÚÀÍÅ. ðÁÔÞÉÔØ ÎÁÄÏ ÌÉÂÏ ÜÔÉ Ä×ÉÖËÉ, ÌÉÂÏ, ÞÔÏ ÍÎÅ (ÎÁ ÐÅÒ×ÙÊ ×ÚÇÌÑÄ) +ËÁÖÅÔÓÑ ÐÒÏÝÅ, ÎÁÄÏ ÐÏÄÃÅÐÉÔÓÑ Ë slotEngineMetaData. ôÒÁÂÌÁ ÔÁÍ ÔÏÌØËÏ × ÔÏÍ, +ÞÔÏ ÐÒÉÈÏÄÉÔ ÔÕÄÁ ÔÜÇÉ ÕÖÅ × UTF-8, ÎÅËÏÒÅËÔÎÏ ÐÅÒÅËÏÄÉÒÏ×ÁÎÎÏÍ. ðÏÜÔÏÍÕ, +ÓÎÁÞÁÌÁ ÎÁÄÏ ËÏÎ×ÅÒÔÕÔØ UTF-8 ÏÂÒÁÔÎÏ × Latin1, Á ÕÖÅ ÐÏÔÏÍ ÎÁÔÒÁ×ÌÉ×ÁÔØ +librcc. ÷ÐÒÏÞÅÍ, ÐÅÒÅËÏÄÉÒÏ×ËÕ UTF->Latin ÔÏÖÅ ÍÏÖÎÏ ÓÄÅÌÁÔØ ÞÅÒÅÚ librcc. diff --git a/fixes/libguess-fixes/README b/fixes/libguess-fixes/README new file mode 100644 index 0000000..bad7594 --- /dev/null +++ b/fixes/libguess-fixes/README @@ -0,0 +1 @@ +This patch adds BIG5 encoding detection into the Chinese detection engine. diff --git a/fixes/libguess-fixes/libguess-ds-cn.patch b/fixes/libguess-fixes/libguess-ds-cn.patch new file mode 100644 index 0000000..7c2384b --- /dev/null +++ b/fixes/libguess-fixes/libguess-ds-cn.patch @@ -0,0 +1,62 @@ +diff -dPNur libguess-0.2.0-d7/guess.c libguess-0.2.0-d7-new/guess.c +--- libguess-0.2.0-d7/guess.c 2006-12-05 17:59:32.000000000 +0100 ++++ libguess-0.2.0-d7-new/guess.c 2007-06-26 19:56:59.000000000 +0200 +@@ -44,7 +44,7 @@ + /* ORDER_** &highest, &second, ... &lowest */ + #define ORDER_JP &utf8, &sjis, &eucj + #define ORDER_TW &utf8, &big5 +-#define ORDER_CN &utf8, &gb2312, &gb18030 ++#define ORDER_CN &utf8, &gb2312, &gb18030, &big5 + #define ORDER_KR &utf8, &euck, &johab + + /* workaround for that glib's g_convert can't convert +@@ -252,6 +252,8 @@ + guess_dfa gb2312 = DFA_INIT(guess_gb2312_st, guess_gb2312_ar); + guess_dfa utf8 = DFA_INIT(guess_utf8_st, guess_utf8_ar); + guess_dfa gb18030 = DFA_INIT(guess_gb18030_st, guess_gb18030_ar); ++ guess_dfa big5 = DFA_INIT(guess_big5_st, guess_big5_ar); ++ + guess_dfa *top = NULL; + + guess_dfa *order[] = { ORDER_CN, NULL }; +@@ -287,22 +289,27 @@ + } + + if (DFA_ALIVE(gb2312)) { +- if (!DFA_ALIVE(utf8) && !DFA_ALIVE(gb18030)) ++ if (!DFA_ALIVE(utf8) && !DFA_ALIVE(gb18030) && !DFA_ALIVE(big5)) + return "GB2312"; + DFA_NEXT(gb2312, c); + } + if (DFA_ALIVE(utf8)) { +- if (!DFA_ALIVE(gb2312) && !DFA_ALIVE(gb18030)) ++ if (!DFA_ALIVE(gb2312) && !DFA_ALIVE(gb18030) && !DFA_ALIVE(big5)) + return "UTF-8"; + DFA_NEXT(utf8, c); + } + if (DFA_ALIVE(gb18030)) { +- if (!DFA_ALIVE(utf8) && !DFA_ALIVE(gb2312)) ++ if (!DFA_ALIVE(utf8) && !DFA_ALIVE(gb2312) && !DFA_ALIVE(big5)) + return "GB18030"; + DFA_NEXT(gb18030, c); + } ++ if (DFA_ALIVE(big5)) { ++ if (!DFA_ALIVE(utf8) && !DFA_ALIVE(gb2312) && !DFA_ALIVE(gb18030)) ++ return "big5"; ++ DFA_NEXT(big5, c); ++ } + +- if (!DFA_ALIVE(gb2312) && !DFA_ALIVE(utf8) && !DFA_ALIVE(gb18030)) { ++ if (!DFA_ALIVE(gb2312) && !DFA_ALIVE(utf8) && !DFA_ALIVE(gb18030) && !DFA_ALIVE(big5)) { + /* we ran out the possibilities */ + return NULL; + } +@@ -323,6 +330,8 @@ + return "UTF-8"; + if (top == &gb18030) + return "GB18030"; ++ if (top == &big5) ++ return "BIG5"; + return NULL; + } + diff --git a/fixes/libtranslate-fixes/README b/fixes/libtranslate-fixes/README new file mode 100644 index 0000000..814a2ee --- /dev/null +++ b/fixes/libtranslate-fixes/README @@ -0,0 +1,38 @@ +It is highly recommended to apply all attached patches to libtranslate. They +are fixing several serious bugs and providing better support of various +translation services. Additionaly, it is highly recommended to obtain latest +valid service description file (services.xml) from http://RusXMMS.sf.net. + +*** IMPORTANT *** +Please, not you should apply "libtranslate-ds-fixcharset.patch" patch after +"libtranslate-ds-timed.patch" otherwise the process would fail. + + +Official Patches +================ +charsetparse: Patch fixing HTTP charset parsing +condfix: Patch fixing occasional translate_session_translate_text() + lockup + +DarkSoft Patches +================ +memory: Fixes memory exhaustion on 64bit platforms. +empty: Fixes segmentation in the case if the Web Server closes + connection prior to sending any data. +promt: Allows "entities" keyword to send ISO8859-1 source text in the + HTML Entities encoding as required by translate.ru service + (Look usage example in services.xml) +fixcharset: This patch enables support for translation services returning + wrong charset in Content-Type header (pereklad.ua for example). + The "response-charset" attribute could be used to declare + correct charset. + (Look usage example in services.xml) +timed: Provides time limited translation API functions. + + + +Configuration +============= +services.xml Example services.xml including translate.ru and pereklad.ua + services. This is an example only. Please, find the latest + version of the service.xml on the http://rusxmms.sf.net diff --git a/fixes/libtranslate-fixes/libtranslate-0.99-charsetparse.diff b/fixes/libtranslate-fixes/libtranslate-0.99-charsetparse.diff new file mode 100644 index 0000000..1626f25 --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-0.99-charsetparse.diff @@ -0,0 +1,47 @@ +--- src/modules/translate-generic-service.c.orig Mon Apr 11 23:08:47 2005 ++++ src/modules/translate-generic-service.c Mon Apr 11 23:15:54 2005 +@@ -484,7 +484,7 @@ + + if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + { +- const char *charset = NULL; ++ char *charset = NULL; + + if (flags & TRANSFER_CONVERT) + { +@@ -493,14 +493,31 @@ + content_type = translate_generic_service_get_header(message, &info, "Content-Type"); + if (content_type) + { +- charset = translate_ascii_strcasestr(content_type, "charset="); +- if (charset) +- charset += 8; ++ const char *tmp; ++ ++ tmp = translate_ascii_strcasestr(content_type, "charset="); ++ if (tmp) ++ { ++ int len; ++ ++ tmp += 8; ++ if (*tmp == '\'' || *tmp == '"') ++ tmp++; ++ ++ len = strlen(tmp); ++ if (len > 0 && (tmp[len - 1] == '\'' || tmp[len - 1] == '"')) ++ len--; ++ ++ charset = g_strndup(tmp, len); ++ } + } + } + + if (charset) +- response = g_convert(message->response.body, message->response.length, "UTF-8", charset, NULL, NULL, err); ++ { ++ response = g_convert(message->response.body, message->response.length, "UTF-8", charset, NULL, NULL, err); ++ g_free(charset); ++ } + else + { + if ((flags & TRANSFER_CONVERT) && ! g_utf8_validate(message->response.body, message->response.length, NULL)) diff --git a/fixes/libtranslate-fixes/libtranslate-0.99-condfix.diff b/fixes/libtranslate-fixes/libtranslate-0.99-condfix.diff new file mode 100644 index 0000000..4011dcd --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-0.99-condfix.diff @@ -0,0 +1,38 @@ +--- src/translate-session.c.orig Mon Apr 11 22:44:53 2005 ++++ src/translate-session.c Mon Apr 11 22:51:48 2005 +@@ -703,7 +703,14 @@ + GError *tmp_err = NULL; + + g_mutex_lock(info->mutex); +- ret = info->err != NULL; ++ if (info->err) ++ { ++ ret = TRUE; ++ if (info->progress_cond) ++ g_cond_signal(info->progress_cond); ++ } ++ else ++ ret = FALSE; + g_mutex_unlock(info->mutex); + + if (ret) +@@ -728,6 +735,9 @@ + else + g_propagate_error(&info->err, tmp_err); + ++ if (info->progress_cond) ++ g_cond_signal(info->progress_cond); ++ + g_mutex_unlock(info->mutex); + + return; +@@ -759,6 +769,9 @@ + info->err = g_error_new(TRANSLATE_SESSION_ERROR, + TRANSLATE_SESSION_ERROR_NO_SERVICE, + _("no service could translate chunk")); ++ ++ if (info->progress_cond) ++ g_cond_signal(info->progress_cond); + } + + g_mutex_unlock(info->mutex); diff --git a/fixes/libtranslate-fixes/libtranslate-ds-empty.patch b/fixes/libtranslate-fixes/libtranslate-ds-empty.patch new file mode 100644 index 0000000..1a6a25d --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-ds-empty.patch @@ -0,0 +1,17 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2007-06-27 17:26:10.000000000 +0200 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2007-06-27 17:23:55.000000000 +0200 +@@ -1042,6 +1042,13 @@ + + g_free(response); + } ++ ++ if (!answer) { ++ g_set_error(err, ++ TRANSLATE_GENERIC_SERVICE_ERROR, ++ TRANSLATE_GENERIC_SERVICE_ERROR_PARSE, ++ _("empty server response")); ++ } + + return answer ? g_string_free(answer, FALSE) : NULL; + } diff --git a/fixes/libtranslate-fixes/libtranslate-ds-fixcharset.patch b/fixes/libtranslate-fixes/libtranslate-ds-fixcharset.patch new file mode 100644 index 0000000..0665d2f --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-ds-fixcharset.patch @@ -0,0 +1,93 @@ +diff -dPNur libtranslate-0.99-new/src/modules/translate-generic-parser.c libtranslate-0.99-new-uk/src/modules/translate-generic-parser.c +--- libtranslate-0.99-new/src/modules/translate-generic-parser.c 2005-01-17 17:46:24.000000000 +0100 ++++ libtranslate-0.99-new-uk/src/modules/translate-generic-parser.c 2007-06-27 22:40:04.000000000 +0200 +@@ -726,6 +726,7 @@ + { + const char *url; + const char *post; ++ const char *charset; + const char *content_type; + + g_return_if_fail(info != NULL); +@@ -740,6 +741,7 @@ + "url", REQUIRED, &url, + "post", OPTIONAL, &post, + "content-type", OPTIONAL, &content_type, ++ "response-charset", OPTIONAL, &charset, + NULL); + + if (! *err) +@@ -748,6 +750,7 @@ + (*location)->url = g_strdup(url); + (*location)->post = g_strdup(post); + (*location)->content_type = g_strdup(content_type ? content_type : "application/x-www-form-urlencoded"); ++ (*location)->response_charset = g_strdup(charset); + } + } + +@@ -759,6 +762,7 @@ + g_free(location->url); + g_free(location->post); + g_free(location->content_type); ++ g_free(location->response_charset); + g_slist_foreach(location->http_headers, (GFunc) translate_generic_http_header_free, NULL); + g_slist_free(location->http_headers); + g_free(location); +diff -dPNur libtranslate-0.99-new/src/modules/translate-generic-parser.h libtranslate-0.99-new-uk/src/modules/translate-generic-parser.h +--- libtranslate-0.99-new/src/modules/translate-generic-parser.h 2005-01-17 17:46:30.000000000 +0100 ++++ libtranslate-0.99-new-uk/src/modules/translate-generic-parser.h 2007-06-27 22:34:13.000000000 +0200 +@@ -51,6 +51,7 @@ + char *url; + char *post; + char *content_type; ++ char *response_charset; + GSList *http_headers; + } TranslateGenericLocation; + +diff -dPNur libtranslate-0.99-new/src/modules/translate-generic-service.c libtranslate-0.99-new-uk/src/modules/translate-generic-service.c +--- libtranslate-0.99-new/src/modules/translate-generic-service.c 2007-06-27 17:23:55.000000000 +0200 ++++ libtranslate-0.99-new-uk/src/modules/translate-generic-service.c 2007-06-27 22:40:29.000000000 +0200 +@@ -129,6 +129,7 @@ + static char *translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, ++ const char *response_charset, + const GSList *headers, + TransferFlags flags, + GTimeVal *deadline, +@@ -407,6 +408,7 @@ + translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, ++ const char *response_charset, + const GSList *headers, + TransferFlags flags, + GTimeVal *deadline, +@@ -550,9 +552,9 @@ + } + } + +- if (charset) ++ if ((charset)||(response_charset)) + { +- response = g_convert(message->response.body, message->response.length, "UTF-8", charset, NULL, NULL, err); ++ response = g_convert(message->response.body, message->response.length, "UTF-8", response_charset?response_charset:charset, NULL, NULL, err); + g_free(charset); + } + else +@@ -941,6 +943,7 @@ + response = translate_generic_service_get(url, + post, + group->text_location->content_type, ++ group->text_location->response_charset, + headers, + TRANSFER_FOLLOW_REFRESH | TRANSFER_CONVERT, + deadline, +@@ -1339,6 +1342,7 @@ + response = translate_generic_service_get(translation_url, + post, + group->web_page_location->content_type, ++ group->web_page_location->response_charset, + headers, + 0, + NULL, diff --git a/fixes/libtranslate-fixes/libtranslate-ds-memory.patch b/fixes/libtranslate-fixes/libtranslate-ds-memory.patch new file mode 100644 index 0000000..e05c7b4 --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-ds-memory.patch @@ -0,0 +1,12 @@ +diff -dPNur libtranslate-0.99/src/translate-util.c libtranslate-0.99-new/src/translate-util.c +--- libtranslate-0.99/src/translate-util.c 2005-01-17 16:45:45.000000000 +0000 ++++ libtranslate-0.99-new/src/translate-util.c 2005-12-29 18:35:04.000000000 +0000 +@@ -136,7 +136,7 @@ + g_return_val_if_fail(big != NULL, NULL); + g_return_val_if_fail(little != NULL, NULL); + +- lower_big = g_ascii_strdown(big, big_len); ++ lower_big = g_ascii_strdown(big, (int)big_len); + lower_little = g_ascii_strdown(little, -1); + + s = strstr(lower_big, lower_little); diff --git a/fixes/libtranslate-fixes/libtranslate-ds-promt.patch b/fixes/libtranslate-fixes/libtranslate-ds-promt.patch new file mode 100644 index 0000000..6b30145 --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-ds-promt.patch @@ -0,0 +1,27 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2007-06-27 17:26:10.000000000 +0200 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2007-06-27 17:23:55.000000000 +0200 +@@ -1238,7 +1245,22 @@ + { + if (modifier_value) + g_warning(_("%s: value specified for \"escape\" modifier"), warning_prefix); +- modified = soup_uri_encode(value, NULL); ++ modified = soup_uri_encode(value, "&"); ++ } ++ else if (! strcmp(modifier_name, "entities")) ++ { ++ int i; ++ char *ptr; ++ ++ modified = g_malloc(strlen(value)*6 + 1); ++ for (i=0,ptr=modified;value[i];i++) { ++ if ((unsigned char)(value[i])<160) *(ptr++)=value[i]; ++ else { ++ sprintf(ptr, "&#%u;", (unsigned char)(value[i])); ++ ptr+=6; ++ } ++ } ++ *ptr = 0; + } + else if (! strcmp(modifier_name, "charset")) + { diff --git a/fixes/libtranslate-fixes/libtranslate-ds-timed.patch b/fixes/libtranslate-fixes/libtranslate-ds-timed.patch new file mode 100644 index 0000000..c98868a --- /dev/null +++ b/fixes/libtranslate-fixes/libtranslate-ds-timed.patch @@ -0,0 +1,352 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2005-01-17 17:46:38.000000000 +0100 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2005-07-27 22:13:33.000000000 +0200 +@@ -131,6 +131,7 @@ + const char *post_content_type, + const GSList *headers, + TransferFlags flags, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); +@@ -181,6 +182,15 @@ + gpointer user_data, + GError **err); + ++static char *translate_generic_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); ++ + char *translate_generic_service_expand (const char *warning_prefix, + const char *str, + ...); +@@ -248,6 +258,7 @@ + + service_class->get_pairs = translate_generic_service_get_pairs; + service_class->translate_text = translate_generic_service_translate_text; ++ service_class->timed_translate_text = translate_generic_service_timed_translate_text; + service_class->translate_web_page = translate_generic_service_translate_web_page; + + g_object_class_install_property(object_class, +@@ -387,12 +398,18 @@ + return TRUE; /* continue */ + } + ++static void send_message_cb(SoupMessage *req, gpointer user_data) { ++ g_object_ref(req); ++ *(gboolean*)user_data = TRUE; ++} ++ + static char * + translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, + const GSList *headers, + TransferFlags flags, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -400,6 +417,8 @@ + TransferInfo info; + SoupMessage *message; + const GSList *l; ++ GTimeVal tv; ++ gboolean completed = 0, canceled = 0; + char *response = NULL; + + g_return_val_if_fail(uri != NULL, FALSE); +@@ -479,9 +498,27 @@ + if (translate_generic_debug_flags & TRANSLATE_GENERIC_DEBUG_LOG_TRANSFERS) + translate_generic_service_log_connect(message); + ++ if (deadline) { ++ soup_session_queue_message(info.session, message, send_message_cb, &completed); ++ ++ do { ++ g_main_iteration (FALSE); ++ if (completed) break; ++ ++ g_get_current_time(&tv); ++ } while ((tv.tv_sec < deadline->tv_sec)||((tv.tv_sec == deadline->tv_sec)&&(tv.tv_usec < deadline->tv_usec))); ++ ++ if (!completed) { ++ soup_session_cancel_message(info.session, message); ++ canceled = 1; ++ } ++ } else + soup_session_send_message(info.session, message); + g_object_unref(info.session); + ++ if (canceled) ++ g_set_error(err, TRANSLATE_ERROR, TRANSLATE_ERROR_CANCELLED, _("Timeout")); ++ else + if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + { + const char *charset = NULL; +@@ -833,10 +870,11 @@ + } + + static char * +-translate_generic_service_translate_text (TranslateService *service, ++translate_generic_service_timed_translate_text (TranslateService *service, + const char *text, + const char *from, + const char *to, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -882,16 +920,16 @@ + + headers = g_slist_copy(group->http_headers); + headers = g_slist_concat(headers, g_slist_copy(group->text_location->http_headers)); +- ++ + response = translate_generic_service_get(url, + post, + group->text_location->content_type, + headers, + TRANSFER_FOLLOW_REFRESH | TRANSFER_CONVERT, ++ deadline, + progress_func, + user_data, + err); +- + g_free(url); + g_free(post); + g_slist_free(headers); +@@ -991,6 +1029,18 @@ + return answer ? g_string_free(answer, FALSE) : NULL; + } + ++static char * ++translate_generic_service_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ return translate_generic_service_timed_translate_text(service, text, from, to, NULL, progress_func, user_data, err); ++} ++ + char * + translate_generic_service_expand (const char *warning_prefix, + const char *str, +@@ -1252,6 +1302,7 @@ + group->web_page_location->content_type, + headers, + 0, ++ NULL, + progress_func, + user_data, + err); +@@ -1311,7 +1362,7 @@ + g_free(proxy_text_uri); + } + +- session = soup_session_sync_new_with_options(SOUP_SESSION_PROXY_URI, proxy_uri, NULL); ++ session = soup_session_async_new_with_options(SOUP_SESSION_PROXY_URI, proxy_uri, NULL); + + if (proxy_uri) + soup_uri_free(proxy_uri); +diff -dPNur libtranslate-0.99/src/translate-service.c libtranslate-0.99-new/src/translate-service.c +--- libtranslate-0.99/src/translate-service.c 2005-01-17 17:45:23.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service.c 2005-07-27 17:18:07.000000000 +0200 +@@ -372,6 +372,28 @@ + } + + char * ++translate_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ g_return_val_if_fail(TRANSLATE_IS_SERVICE(service), NULL); ++ g_return_val_if_fail(TRANSLATE_SERVICE_GET_CLASS(service)->translate_text != NULL, NULL); ++ g_return_val_if_fail(text != NULL, NULL); ++ g_return_val_if_fail(from != NULL, NULL); ++ g_return_val_if_fail(to != NULL, NULL); ++ ++ if (TRANSLATE_SERVICE_GET_CLASS(service)->timed_translate_text) ++ return TRANSLATE_SERVICE_GET_CLASS(service)->timed_translate_text(service, text, from, to, deadline, progress_func, user_data, err); ++ ++ return TRANSLATE_SERVICE_GET_CLASS(service)->translate_text(service, text, from, to, progress_func, user_data, err); ++} ++ ++char * + translate_service_translate_web_page (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-service.h libtranslate-0.99-new/src/translate-service.h +--- libtranslate-0.99/src/translate-service.h 2005-01-17 17:45:29.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service.h 2005-07-27 16:54:46.000000000 +0200 +@@ -73,6 +73,14 @@ + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); ++ char *(*timed_translate_text)(TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *(*translate_web_page) (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-service-private.h libtranslate-0.99-new/src/translate-service-private.h +--- libtranslate-0.99/src/translate-service-private.h 2005-01-17 17:45:17.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service-private.h 2005-07-27 17:30:00.000000000 +0200 +@@ -41,6 +41,14 @@ + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); ++char *translate_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *translate_service_translate_web_page (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-session.c libtranslate-0.99-new/src/translate-session.c +--- libtranslate-0.99/src/translate-session.c 2005-01-17 17:45:35.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-session.c 2005-07-27 16:52:46.000000000 +0200 +@@ -62,6 +62,8 @@ + { + GMutex *mutex; + GCond *progress_cond; ++ ++ GTimeVal *deadline; + + TranslateSession *session; + GSList *services; +@@ -487,6 +489,7 @@ + * @text: a nul-terminated string. + * @from: a RFC 3066 language tag. + * @to: a RFC 3066 language tag. ++ * @timeout: timeout in microseconds. + * @progress_func: a function to call when progressing, or %NULL. + * @user_data: data to pass to @progress_func, or %NULL. + * @err: a location to report errors, or %NULL. Any of the errors in +@@ -505,10 +508,11 @@ + * when no longer needed. + **/ + char * +-translate_session_translate_text (TranslateSession *session, ++translate_session_timed_translate_text (TranslateSession *session, + const char *text, + const char *from, + const char *to, ++ gulong timeout, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -519,6 +523,7 @@ + unsigned int max_threads; + GThreadPool *pool; + GSList *l; ++ GTimeVal deadline; + unsigned int max_chunk_len = 0; + char *translated = NULL; + +@@ -527,6 +532,11 @@ + g_return_val_if_fail(from != NULL, NULL); + g_return_val_if_fail(to != NULL, NULL); + ++ if (timeout) { ++ g_get_current_time(&deadline); ++ g_time_val_add(&deadline, timeout); ++ } ++ + LOCK(session); + info.services = translate_session_get_services_for_translation(session, + TRANSLATE_PAIR_TEXT, +@@ -560,7 +570,8 @@ + chunks = translate_session_split(text, max_chunk_len); + + info.mutex = g_mutex_new(); +- info.progress_cond = progress_func ? g_cond_new() : NULL; ++ info.progress_cond = (progress_func||timeout) ? g_cond_new() : NULL; ++ info.deadline = timeout ? &deadline : NULL; + info.session = session; + info.chunks = NULL; + info.from = from; +@@ -614,6 +625,11 @@ + GSList *l; + int n_chunks; + ++ if (timeout) { ++ if (!g_cond_timed_wait(info.progress_cond, info.mutex, info.deadline)) ++ info.err = g_error_new(TRANSLATE_ERROR,TRANSLATE_ERROR_CANCELLED,_("timeout")); ++ break; ++ } else + g_cond_wait(info.progress_cond, info.mutex); + + if (info.err) +@@ -680,6 +696,18 @@ + return translated; + } + ++char * ++translate_session_translate_text (TranslateSession *session, ++ const char *text, ++ const char *from, ++ const char *to, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ return translate_session_timed_translate_text(session, text, from, to, 0, progress_func, user_data, err); ++} ++ + static void + translate_session_translate_thread (gpointer data, gpointer user_data) + { +@@ -709,10 +737,11 @@ + if (ret) + return; + +- chunk_info->translated = translate_service_translate_text(service, ++ chunk_info->translated = translate_service_timed_translate_text(service, + chunk_info->chunk, + info->from, + info->to, ++ info->deadline, + info->progress_cond ? translate_session_translate_progress_cb : NULL, + info->progress_cond ? chunk_info : NULL, + &tmp_err); +diff -dPNur libtranslate-0.99/src/translate-session.h libtranslate-0.99-new/src/translate-session.h +--- libtranslate-0.99/src/translate-session.h 2005-01-17 17:45:40.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-session.h 2005-07-27 14:41:05.000000000 +0200 +@@ -93,6 +93,14 @@ + unsigned int translate_session_get_max_threads (TranslateSession *session); + int translate_session_get_max_retries (TranslateSession *session); + ++char *translate_session_timed_translate_text (TranslateSession *session, ++ const char *text, ++ const char *from, ++ const char *to, ++ gulong timeout, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *translate_session_translate_text (TranslateSession *session, + const char *text, + const char *from, diff --git a/fixes/libtranslate-fixes/services.xml b/fixes/libtranslate-fixes/services.xml new file mode 100644 index 0000000..c27dd2e --- /dev/null +++ b/fixes/libtranslate-fixes/services.xml @@ -0,0 +1,260 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE services SYSTEM "services.dtd"> +<services> + <custom-language tag="zh-TW" name="Chinese (Taiwan)"/> + + <service nick="Google" name="google"> + <group> + <language to="*" tag="en"/> + <language to="en,de" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en" tag="it"/> + <language to="en" tag="pt"/> + <language to="en" tag="es"/> + <language to="en" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en" tag="ar"/> + <text-translation url="http://www.google.com/translate_t?text=${text:escape}&langpair=${from}|${to}&ie=utf8&oe=utf8"> + <pre-marker text="id=result_box"/> + <pre-marker text=">"/> + <post-marker text="</div>"/> + </text-translation> + <web-page-translation url="http://www.google.com/translate_c?u=${url:escape}&langpair=${from}|${to}"/> + </group> + </service> + + <service nick="FreeTranslation" name="freetranslation" max-chunk-len="600"> + <group> + <language to="en" tag="nl" service-tag="dutch"/> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="fr" service-tag="french"/> + <language to="en" tag="de" service-tag="german"/> + <language to="en" tag="it" service-tag="italian"/> + <language tag="no" service-tag="norwegian"/> + <language to="en" tag="pt" service-tag="portuguese"/> + <language to="en" tag="es" service-tag="spanish"/> + <text-translation url="http://ets.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + <web-page-translation url="http://fets5.freetranslation.com/?sequence=core&url=${url:escape}&language=${from}/${to}"/> + </group> + <group> + <language tag="zh" service-tag="simplifiedchinese"/> + <language tag="zh-TW" service-tag="traditionalchinese"/> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="ru" service-tag="russian"/> + <text-translation url="http://ets6.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + </group> + <group> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="ja" service-tag="japanese"/> + <text-translation url="http://tets9.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + </group> + </service> + + <service nick="Pereklad" name="pereklad"> + <group> + <language to="*" tag="ru" service-tag="Rus"/> + <language to="*" tag="uk" service-tag="Ukr"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=CP1251,escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="*" tag="en" service-tag="Eng"/> + <language to="*" tag="de" service-tag="Ger"/> + <language to="*" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=ISO-8859-1,escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="en,de,fr" tag="ru" service-tag="Rus"/> + <language to="en,de,fr" tag="uk" service-tag="Ukr"/> + <language to="" tag="en" service-tag="Eng"/> + <language to="" tag="de" service-tag="Ger"/> + <language to="" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=CP1251,escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="ru" service-tag="Rus"/> + <language to="" tag="uk" service-tag="Ukr"/> + <language to="ru,uk" tag="en" service-tag="Eng"/> + <language to="ru,uk" tag="de" service-tag="Ger"/> + <language to="ru,uk" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=ISO-8859-1,escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="ru" service-tag="Rus"/> + <language to="" tag="uk" service-tag="Ukr"/> + <language to="ru,uk" tag="lv" service-tag="Lat"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=ISO-8859-4,escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="*" tag="lv" service-tag="Lat"/> + <language to="" tag="en" service-tag="Eng"/> + <language to="" tag="de" service-tag="Ger"/> + <language to="" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=ISO-8859-4,escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="lv" service-tag="Lat"/> + <language to="lv" tag="ru" service-tag="Rus"/> + <language to="lv" tag="uk" service-tag="Ukr"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=CP1251,escape}" + response-charset="ISO-8859-4"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="lv" service-tag="Lat"/> + <language to="lv" tag="en" service-tag="Eng"/> + <language to="lv" tag="de" service-tag="Ger"/> + <language to="lv" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:charset=ISO-8859-1,escape}" + response-charset="ISO-8859-4"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + </service> + + <service nick="Promt" name="promt"> + <group> + <language to="" tag="ru" service-tag="r"/> + <language to="ru,de,fr,es" tag="en" service-tag="e"/> + <language to="ru,en,fr,es" tag="de" service-tag="g"/> + <language to="ru,en,de,es" tag="fr" service-tag="f"/> + <language to="ru,en" tag="it" service-tag="i"/> + <language to="ru,en,de,fr" tag="es" service-tag="s"/> + <language to="en" tag="pt" service-tag="p"/> + <text-translation + url="http://www.translate.ru/text.asp" + post="lang=en&transliterate=ON&direction=${from}${to}&source=${text:charset=ISO8859-1,entities,escape}&status=translate"> + <pre-marker text="id="r_text""/> + <pre-marker text=">"/> + <post-marker text="</span>"/> + </text-translation> + </group> + <group> + <language to="*" tag="ru" service-tag="r"/> + <language to="" tag="de" service-tag="g"/> + <language to="" tag="fr" service-tag="f"/> + <language to="" tag="it" service-tag="i"/> + <language to="" tag="es" service-tag="s"/> + <text-translation url="http://www.translate.ru/text.asp?lang=ru&transliterate=ON&direction=r${to}&source=${text:charset=CP1251,escape}&status=translate"> + <pre-marker text="id="r_text""/> + <pre-marker text=">"/> + <post-marker text="</span>"/> + </text-translation> + </group> + </service> + + <service nick="SYSTRAN" name="systran"> + <group> + <language to="en" tag="ar"/> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW" service-tag="zt"/> + <language to="en,fr" tag="nl"/> + <language to="*" tag="en"/> + <language to="nl,en,de,it,pt,es" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en,fr" tag="it"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en,fr" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en,fr" tag="es"/> + <language to="en" tag="sv"/> + <http-header value="http://www.systransoft.com/" name="Referer"/> + <text-translation url="http://www.systranbox.com/systran/box?systran_charset=utf-8&ttype=text&systran_text=${text:escape}&systran_lp=${from}_${to}"> + <pre-marker text="<textarea name="translation""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + <web-page-translation url="http://www.systranbox.com/systran/box?systran_id=SystranSoft-en&systran_url=${url:escape}&systran_lp=${from}_${to}&systran_f=${time}"/> + </group> + </service> + + <service nick="Babel Fish" name="babelfish"> + <group> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW" service-tag="zt"/> + <language to="*" tag="en"/> + <language to="en,fr" tag="nl"/> + <language to="en,de,el,it,pt,nl,es" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en,fr" tag="el"/> + <language to="en,fr" tag="it"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en,fr" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en,fr" tag="es"/> + <text-translation url="http://babelfish.altavista.com/babelfish/tr?urltext=${text:escape}&lp=${from}_${to}&enc=utf8"> + <pre-marker text="<form action="http://www.altavista.com/web/results"/> + <pre-marker text="px;>"/> + <post-marker text="</div>"/> + </text-translation> + <web-page-translation url="http://babelfish.altavista.com/babelfish/trurl_load?url=${url:escape}&lp=${from}_${to}&enc=utf8"/> + </group> + </service> + + <service nick="Kataku" name="kataku"> + <group> + <language to="*" tag="en"/> + <language to="*" tag="id" service-tag="in"/> + <text-translation url="http://www.toggletext.com/kataku_trial.php" post="input_text=${text:charset=ISO8859-1,escape}&langset_text=${from}_${to}"> + <pre-marker text="Translation:"/> + <pre-marker text="<pre"/> + <pre-marker text=">"/> + <post-marker text=" </pre>"/> + </text-translation> + <web-page-translation url="http://www.toggletext.com/kataku_webpage_translate.php?input=${url:escape}&langset=${from}_${to}"/> + </group> + </service> +</services>
\ No newline at end of file diff --git a/fixes/mac-fixes/README b/fixes/mac-fixes/README new file mode 100644 index 0000000..072233e --- /dev/null +++ b/fixes/mac-fixes/README @@ -0,0 +1,41 @@ +mac is unsupported port for Monkey Audio Loseless Codec (ape) Acutally, it is +known for lot of problems on 64bit platforms. Here is patch fixing another one. + + +Some description for future use +=============================== + The problems is actully related to converting pointers to/from int type. +The portability requires intptr_t to be used for that purposes. However, +in many places 'int' still specified. Therefore, if acutal pointer is +above int size on AMD64, the crashes occurs. + +It looks new/malloc on my Gentoo system in the beginning allocates memory +in the lower segments and everything goes smoothly. However, after a while +the allocation from higher regions is started. This could be traced by +monitoring the result of + mac_info = (PlayerInfo *)g_malloc0(sizeof(PlayerInfo)); + decompress = CreateIAPEDecompress(pUTF16, &nRetVal); +in function 'decompress_init' of mac.cpp (xmms-mac). After few iterations they +would return high address ptr. Actually, the good method of accelerating +crashes, is usage of following code (within decompress_init): + + rep: + decompress = CreateIAPEDecompress(pUTF16, &nRetVal); + if (decompress < (void*)0x7FFFFFFF) { + void *a=malloc((int)1000*rand()); + delete decompress; + free(a); + goto rep; + } + +Few notes on mac +================ +MACLib.cpp - C(stdcall) functions for class construction +APEDecompress - main working class which widly utilizes +UnBitArray - classes to work with actual data (many int usages within) + pIO - after a lot of black magick is initialiozed by function + call: + CAPEDecompress::GetInfo + which in his order calls: + CAPEInfo::GetInfo + diff --git a/fixes/mac-fixes/mac-3.99-u4-b5-s4-ds-fix.patch b/fixes/mac-fixes/mac-3.99-u4-b5-s4-ds-fix.patch new file mode 100644 index 0000000..aba0379 --- /dev/null +++ b/fixes/mac-fixes/mac-3.99-u4-b5-s4-ds-fix.patch @@ -0,0 +1,12 @@ +diff -dPNur mac-3.99-u4-b5-s4/src/MACLib/APEDecompress.cpp mac-3.99-u4-b5-s4-new/src/MACLib/APEDecompress.cpp +--- mac-3.99-u4-b5-s4/src/MACLib/APEDecompress.cpp 2006-06-01 11:00:58.000000000 +0200 ++++ mac-3.99-u4-b5-s4-new/src/MACLib/APEDecompress.cpp 2008-04-12 17:39:39.000000000 +0200 +@@ -369,7 +369,7 @@ + *****************************************************************************************/ + intptr_t CAPEDecompress::GetInfo(APE_DECOMPRESS_FIELDS Field, intptr_t nParam1, intptr_t nParam2) + { +- int nRetVal = 0; ++ intptr_t nRetVal = 0; + BOOL bHandled = TRUE; + + switch (Field) diff --git a/fixes/taglib-fixes/taglib-1.4_wchar.diff b/fixes/taglib-fixes/taglib-1.4_wchar.diff new file mode 100644 index 0000000..b84a614 --- /dev/null +++ b/fixes/taglib-fixes/taglib-1.4_wchar.diff @@ -0,0 +1,31 @@ +diff -ruN taglib-1.4.org/taglib/toolkit/tstring.cpp taglib-1.4/taglib/toolkit/tstring.cpp +--- taglib-1.4.org/taglib/toolkit/tstring.cpp 2005-07-26 06:31:15.000000000 +0900 ++++ taglib-1.4/taglib/toolkit/tstring.cpp 2006-05-26 12:02:55.000000000 +0900 +@@ -202,12 +202,22 @@ + s.resize(d->data.size()); + + if(!unicode) { +- std::string::iterator targetIt = s.begin(); +- for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { +- *targetIt = char(*it); +- ++targetIt; ++ bool cjk = false; ++ //pre-scan: is there any cjk unicode character? if so, convert the string into utf-8. ++ for(unsigned int i=0; i< d->data.size(); i++){ ++ if(d->data[i] > 0xff){ ++ cjk = true; ++ break; ++ } ++ } ++ if(!cjk){ ++ std::string::iterator targetIt = s.begin(); ++ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { ++ *targetIt = char(*it); ++ ++targetIt; ++ } ++ return s; + } +- return s; + } + + const int outputBufferSize = d->data.size() * 3 + 1; diff --git a/fixes/xmms-fixes/gcc41/xmms-1.2.10-gcc41.patch b/fixes/xmms-fixes/gcc41/xmms-1.2.10-gcc41.patch new file mode 100644 index 0000000..0041851 --- /dev/null +++ b/fixes/xmms-fixes/gcc41/xmms-1.2.10-gcc41.patch @@ -0,0 +1,10 @@ +--- xmms-1.2.10.orig/Output/esd/esdout.h 2005-11-22 19:53:38.000000000 +0600 ++++ xmms-1.2.10/Output/esd/esdout.h 2005-11-22 19:56:04.197329014 +0600 +@@ -58,6 +58,7 @@ + ESDConfig; + + extern ESDConfig esd_cfg; ++extern void esdout_reset_playerid(void); + + void esdout_init(void); + void esdout_about(void); diff --git a/fixes/xmms-fixes/gcc41/xmms-1.2.10-locale_fix.patch b/fixes/xmms-fixes/gcc41/xmms-1.2.10-locale_fix.patch new file mode 100644 index 0000000..cfb1cd1 --- /dev/null +++ b/fixes/xmms-fixes/gcc41/xmms-1.2.10-locale_fix.patch @@ -0,0 +1,11 @@ +diff -ruN xmms-1.2.10.orig/xmms/playlist.c xmms-1.2.10/xmms/playlist.c +--- xmms-1.2.10.orig/xmms/playlist.c 2005-11-25 05:14:47.000000000 +0600 ++++ xmms-1.2.10/xmms/playlist.c 2005-11-25 05:18:59.894581237 +0600 +@@ -23,6 +23,7 @@ + #include "libxmms/rcc.h" + #include <sys/stat.h> + #include <unistd.h> ++#include <locale.h> + + GList *playlist = NULL; + GList *shuffle_list = NULL; diff --git a/fixes/zinf-fixes/zinf-ds-noutfrecoding.patch b/fixes/zinf-fixes/zinf-ds-noutfrecoding.patch new file mode 100644 index 0000000..6100a1d --- /dev/null +++ b/fixes/zinf-fixes/zinf-ds-noutfrecoding.patch @@ -0,0 +1,20 @@ +diff -dPNur zinf-2.2.5/plm/metadata/id3lib/id3lib.cpp zinf-2.2.5-new/plm/metadata/id3lib/id3lib.cpp +--- zinf-2.2.5/plm/metadata/id3lib/id3lib.cpp 2004-01-30 13:06:02.000000000 +0100 ++++ zinf-2.2.5-new/plm/metadata/id3lib/id3lib.cpp 2005-07-19 23:08:05.000000000 +0200 +@@ -321,16 +321,8 @@ + if (field) + if (field->Get (buffer, sizeof buffer) > 0) { + #ifdef HAVE_GLIB +- if (g_utf8_validate (buffer, -1 , NULL)){ + result = buffer; + return true; +- } +- else { +- utfbuffer=g_convert(buffer, sizeof buffer, "UTF-8", charset.c_str(), NULL, NULL, NULL); +- result=utfbuffer; +- g_free(utfbuffer); +- return true; +- } + #else + result=buffer; + return true; diff --git a/fixes/zinf-fixes/zinf-ds.patch b/fixes/zinf-fixes/zinf-ds.patch new file mode 100644 index 0000000..4e4b839 --- /dev/null +++ b/fixes/zinf-fixes/zinf-ds.patch @@ -0,0 +1,229 @@ +diff -dPNur zinf-2.2.5/plm/metadata/id3lib/id3lib.cpp zinf-2.2.5-new/plm/metadata/id3lib/id3lib.cpp +--- zinf-2.2.5/plm/metadata/id3lib/id3lib.cpp 2004-01-30 13:06:02.000000000 +0100 ++++ zinf-2.2.5-new/plm/metadata/id3lib/id3lib.cpp 2005-07-19 23:37:11.000000000 +0200 +@@ -304,10 +304,45 @@ + } + + ++static int rccGetCurrentEncoding(char *result, unsigned int n) { ++ unsigned int i; ++ char *l; ++ ++ if ((!result)||(!n)) return -1; ++ ++ l = getenv("CHARSET"); ++#ifdef HAVE_CODESET ++ if (!l) l = nl_langinfo(CODESET); ++#endif ++ if (l) { ++ if (strlen(l)>=n) return -1; ++ strcpy(result, l); ++ return 0; ++ } ++ ++ l = setlocale(LC_CTYPE, NULL); ++ if (!l) return -1; ++ ++ for (i=0;((l[i])&&(l[i]!='.')&&(l[i]!='_'));i++); ++ if (i>=n) return -1; ++ ++ l = strrchr(l, '.'); ++ if (!l) return -1; ++ ++ for (i=0;((l[i])&&(l[i]!='@'));i++); ++ if (i>=n) return -1; ++ ++ strncpy(result,l+1,i-1); ++ result[i]=0; ++ ++ return 0; ++} ++ + static + bool getTag(ID3_Tag&tag, ID3_FrameID frameid, string &result) + { +- static char buffer[1024]; ++ int err; ++ static char buffer[1024], locale[64]; + #ifdef HAVE_GLIB + gchar *utfbuffer; + #endif +@@ -326,7 +361,8 @@ + return true; + } + else { +- utfbuffer=g_convert(buffer, sizeof buffer, "UTF-8", charset.c_str(), NULL, NULL, NULL); ++ err = rccGetCurrentEncoding(locale, 64); ++ utfbuffer=g_convert(buffer, sizeof buffer, "UTF-8", err?charset.c_str():locale, NULL, NULL, NULL); + result=utfbuffer; + g_free(utfbuffer); + return true; +diff -dPNur zinf-2.2.5/ui/ncurses/Makefile.am zinf-2.2.5-new/ui/ncurses/Makefile.am +--- zinf-2.2.5/ui/ncurses/Makefile.am 2003-09-16 19:35:31.000000000 +0200 ++++ zinf-2.2.5-new/ui/ncurses/Makefile.am 2005-07-19 23:51:02.000000000 +0200 +@@ -3,11 +3,11 @@ + plugin_LTLIBRARIES = ncurses-ui.la + + ncurses_ui_la_SOURCES = ncursesUI.cpp +-ncurses_ui_la_LIBADD = $(NCURSES_LIBS) ++ncurses_ui_la_LIBADD = $(NCURSES_LIBS) $(GLIB_LIBS) + ncurses_ui_la_LDFLAGS = $(plugin_ldflags) + + noinst_HEADERS = ncursesUI.h + +-AM_CPPFLAGS = $(THREAD_CFLAGS) $(base_includes) ++AM_CPPFLAGS = $(THREAD_CFLAGS) $(base_includes) $(GLIB_CFLAGS) + + # arch-tag: 19b44c0b-0802-4cfc-9d47-519f9049c888 +diff -dPNur zinf-2.2.5/ui/ncurses/Makefile.in zinf-2.2.5-new/ui/ncurses/Makefile.in +--- zinf-2.2.5/ui/ncurses/Makefile.in 2004-02-09 01:48:25.000000000 +0100 ++++ zinf-2.2.5-new/ui/ncurses/Makefile.in 2005-07-20 00:23:03.823574339 +0200 +@@ -231,7 +231,7 @@ + + noinst_HEADERS = ncursesUI.h + +-AM_CPPFLAGS = $(THREAD_CFLAGS) $(base_includes) ++AM_CPPFLAGS = $(THREAD_CFLAGS) $(base_includes) $(GLIB_CFLAGS) + subdir = ui/ncurses + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +diff -dPNur zinf-2.2.5/ui/ncurses/ncursesUI.cpp zinf-2.2.5-new/ui/ncurses/ncursesUI.cpp +--- zinf-2.2.5/ui/ncurses/ncursesUI.cpp 2003-09-16 19:35:31.000000000 +0200 ++++ zinf-2.2.5-new/ui/ncurses/ncursesUI.cpp 2005-07-20 00:03:31.000000000 +0200 +@@ -32,6 +32,7 @@ + #include <termios.h> + #include <signal.h> + ++ + using namespace std; + #include "config.h" + #include "i18n.h" +@@ -41,6 +42,10 @@ + #include "thread.h" + #include "eventdata.h" + ++#ifdef HAVE_GLIB ++#include <glib.h> ++#endif ++ + #define stdinfd 0 + + extern "C" { +@@ -262,6 +267,40 @@ + + } + ++static int rccGetCurrentEncoding(char *result, unsigned int n) { ++ unsigned int i; ++ char *l; ++ ++ if ((!result)||(!n)) return -1; ++ ++ l = getenv("CHARSET"); ++#ifdef HAVE_CODESET ++ if (!l) l = nl_langinfo(CODESET); ++#endif ++ if (l) { ++ if (strlen(l)>=n) return -1; ++ strcpy(result, l); ++ return 0; ++ } ++ ++ l = setlocale(LC_CTYPE, NULL); ++ if (!l) return -1; ++ ++ for (i=0;((l[i])&&(l[i]!='.')&&(l[i]!='_'));i++); ++ if (i>=n) return -1; ++ ++ l = strrchr(l, '.'); ++ if (!l) return -1; ++ ++ for (i=0;((l[i])&&(l[i]!='@'));i++); ++ if (i>=n) return -1; ++ ++ strncpy(result,l+1,i-1); ++ result[i]=0; ++ ++ return 0; ++} ++ + Error ncursesUI::AcceptEvent(Event *e) { + if (e) { + switch (e->Type()) { +@@ -342,36 +381,69 @@ + break; + md = pItem->GetMetaData(); + ++ char *recoded; ++ char locale[64]; ++#ifdef HAVE_GLIB ++ if (rccGetCurrentEncoding(locale, 64)) strcpy(locale, "UTF-8"); ++#else ++ recoded = NULL; ++#endif ++ ++ + clear(); + move(0,0); + showInfo(); + move(2, 0); + addstr(_("Title : ")); +- if (md.Title().c_str()[0] != '\0') +- addstr((char *)md.Title().c_str()); +- else ++ if (md.Title().c_str()[0] != '\0') { ++#ifdef HAVE_GLIB ++ recoded = g_convert(md.Title().c_str(), -1, locale, "UTF-8", NULL, NULL, NULL); ++#endif ++ addstr(recoded?recoded:(char *)md.Title().c_str()); ++ } else + addstr(pmvi->m_filename.c_str()); ++ ++#ifdef HAVE_GLIB ++ if (recoded) free(recoded); ++ recoded = g_convert(md.Artist().c_str(), -1, locale, "UTF-8", NULL, NULL, NULL); ++#endif + addstr(_("\nArtist : ")); +- addstr((char *)md.Artist().c_str()); ++ addstr(recoded?recoded:(char *)md.Artist().c_str()); ++#ifdef HAVE_GLIB ++ if (recoded) free(recoded); ++ recoded = g_convert(md.Album().c_str(), -1, locale, "UTF-8", NULL, NULL, NULL); ++#endif + addstr(_("\nAlbum : ")); +- addstr((char *)md.Album().c_str()); ++ addstr(recoded?recoded:(char *)md.Album().c_str()); + addstr(_("\nYear : ")); + if (md.Year() != 0) + { + sprintf(buf, "%d", md.Year()); + addstr(buf); + } ++#ifdef HAVE_GLIB ++ if (recoded) free(recoded); ++ recoded = g_convert(md.Genre().c_str(), -1, locale, "UTF-8", NULL, NULL, NULL); ++#endif + addstr(_("\nGenre : ")); +- addstr((char *)md.Genre().c_str()); ++ addstr(recoded?recoded:(char *)md.Genre().c_str()); + addstr(_("\nTrack : ")); + if (md.Track() != 0) + { + sprintf(buf, "%d", md.Track()); + addstr(buf); + } ++#ifdef HAVE_GLIB ++ if (recoded) free(recoded); ++ recoded = g_convert(md.Comment().c_str(), -1, locale, "UTF-8", NULL, NULL, NULL); ++#endif + addstr(_("\nComment: ")); +- addstr((char *)md.Comment().c_str()); ++ addstr(recoded?recoded:(char *)md.Comment().c_str()); + addstr("\n"); ++ ++#ifdef HAVE_GLIB ++ if (recoded) free(recoded); ++#endif + refresh(); + + counter = 0; diff --git a/licenses.txt b/licenses.txt new file mode 100644 index 0000000..aaa10a1 --- /dev/null +++ b/licenses.txt @@ -0,0 +1,25 @@ +taglib - LGPL 2, MPL +libid3tag - GPL 2 or later +xmms - GPL 2 +xmms-wma - GPL 2 +7zip - LGPL +unzip - Info-ZIP +gftp - GPL 2 +moc - GPL 2 +mpg123 - LGPL 2.1 +id3lib - LGPL 2 + +------------------------ +glib2 - LGPL 2 +gtk+2 - LGPL 2 + +iconv - LGPL 2 +libxml - BSD like +enca - GPL 2 +db4 - Open Source License for Oracle Berkeley DB + (GPL compatible, but not LGPL?) + + +libtranslate - BSD like? +libguess - BSD like? +aspell - LGPL 2.1 diff --git a/misc/brokentags.c b/misc/brokentags.c new file mode 100644 index 0000000..e850057 --- /dev/null +++ b/misc/brokentags.c @@ -0,0 +1,16 @@ +/* I tried to use it to fix broken tags (call id3_get_text), but +it really didn't help much (half of title tag, instead of one fourth) */ +void id3_fix_text(struct id3_frame *frame, int offset) { + int i, size; + char *string; + + size = frame->fr_size - offset - 1; + string = ID3_TEXT_FRAME_PTR(frame) + offset; + + for (offset=0, i=0;i<size;i++) { + if (!string[i]) offset++; + else if (offset) string[i-offset] = string[i]; + } + + for (;offset>0;offset--) string[i-offset]=0; +} diff --git a/patches/gftp/gftp-ds-rcc.patch b/patches/gftp/gftp-ds-rcc.patch new file mode 100644 index 0000000..a704deb --- /dev/null +++ b/patches/gftp/gftp-ds-rcc.patch @@ -0,0 +1,822 @@ +diff -dPNur gftp-2.0.18-orig/configure.in gftp-2.0.18-new/configure.in +--- gftp-2.0.18-orig/configure.in 2005-02-04 16:42:32.000000000 +0100 ++++ gftp-2.0.18-new/configure.in 2005-07-23 18:54:53.000000000 +0200 +@@ -288,6 +288,20 @@ + fi + AC_SUBST(SSL_LIBS) + ++AC_CHECK_LIB(rccui, rccUiInit,[ ++ AC_CHECK_HEADERS(librcc.h librccui.h,[ ++ LIBRCC_LIBS="-lrccui" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) ++ + AM_GNU_GETTEXT + + AC_CHECK_PROG(DB2HTML, db2html, true, false) +diff -dPNur gftp-2.0.18-orig/lib/gftp.h gftp-2.0.18-new/lib/gftp.h +--- gftp-2.0.18-orig/lib/gftp.h 2005-01-19 00:09:58.000000000 +0100 ++++ gftp-2.0.18-new/lib/gftp.h 2005-07-23 20:57:03.000000000 +0200 +@@ -362,6 +362,7 @@ + { + int protonum; /* Current number of the protocol this is + set to */ ++ int language, charset; /* Remote language and encoding */ + char *hostname, /* Hostname we will connect to */ + *username, /* Username for host*/ + *password, /* Password for host */ +@@ -928,6 +929,12 @@ + const char *filename, + mode_t * mode ); + ++void gftp_set_language ( gftp_request * request, ++ int language ); ++ ++void gftp_set_charset ( gftp_request * request, ++ int charset ); ++ + void gftp_set_hostname ( gftp_request * request, + const char *hostname ); + +diff -dPNur gftp-2.0.18-orig/lib/Makefile.am gftp-2.0.18-new/lib/Makefile.am +--- gftp-2.0.18-orig/lib/Makefile.am 2005-01-16 17:10:12.000000000 +0100 ++++ gftp-2.0.18-new/lib/Makefile.am 2005-07-23 18:58:12.000000000 +0200 +@@ -4,6 +4,6 @@ + noinst_LIBRARIES = libgftp.a + libgftp_a_SOURCES=bookmark.c cache.c config_file.c fsp.c ftps.c https.c \ + local.c misc.c mkstemps.c protocols.c pty.c rfc959.c \ +- rfc2068.c sshv2.c sslcommon.c +-INCLUDES=@GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" -DLOCALE_DIR=\"$(datadir)/locale\" +-noinst_HEADERS=gftp.h ftpcommon.h httpcommon.h options.h ++ rfc2068.c sshv2.c sslcommon.c rcc.c ++INCLUDES=@LIBRCC_INCLUDES@ @GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" -DLOCALE_DIR=\"$(datadir)/locale\" ++noinst_HEADERS=gftp.h ftpcommon.h httpcommon.h options.h rcc.h +diff -dPNur gftp-2.0.18-orig/lib/rcc.c gftp-2.0.18-new/lib/rcc.c +--- gftp-2.0.18-orig/lib/rcc.c 1970-01-01 01:00:00.000000000 +0100 ++++ gftp-2.0.18-new/lib/rcc.c 2005-07-24 01:53:25.000000000 +0200 +@@ -0,0 +1,289 @@ ++#include <stdlib.h> ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <librccui.h> ++#endif /* HAVE_LIBRCC */ ++ ++#include "rcc.h" ++ ++#ifdef HAVE_LIBRCC ++static rcc_class classes[] = { ++ { "ftp", RCC_CLASS_STANDARD, NULL, NULL, "FTP Encoding", 0 }, ++ { "http", RCC_CLASS_STANDARD, NULL, NULL, "HTTP Encoding", 0 }, ++ { "ssh", RCC_CLASS_STANDARD, NULL, NULL, "SSH Encoding", 0 }, ++ { "fs", RCC_CLASS_STANDARD, NULL, NULL, "FS Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, NULL, NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++rcc_context ctx; ++rcc_ui_context uictx; ++static int rcc_initialized = 0; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccUiFreeContext(uictx); ++ rccFreeContext(ctx); ++ rccUiFree(); ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) { ++ rccLoad(ctx, "ftp"); ++ rccInitDb4(ctx, NULL, 0); ++ rccUiInit(); ++ uictx = rccUiCreateContext(ctx); ++ if (uictx) rcc_initialized = 1; ++ else { ++ rccUiFree(); ++ rccFreeContext(ctx); ++ rccFree(); ++ } ++ } else rccFree(); ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++#ifdef HAVE_LIBRCC ++static char *rcc_languages[RCC_MAX_LANGUAGES+1]; ++static char *rcc_charsets[RCC_MAX_CHARSETS+1]; ++#endif /* HAVE_LIBRCC */ ++ ++char **rccPatchGetLanguageList() { ++#ifdef HAVE_LIBRCC ++ unsigned int i, num; ++ ++ if (rcc_initialized) { ++ num = rccGetLanguageNumber(ctx); ++ for (i=0;i<(num?num:1);i++) ++ rcc_languages[i] = (char*)rccUiGetLanguageName(uictx, (rcc_language_id)i); ++ ++ rcc_languages[i] = NULL; ++ return rcc_languages; ++ } ++#endif /* HAVE_LIBRCC */ ++ ++ return NULL; ++ ++} ++ ++char **rccPatchGetCharsetList(int lid) { ++#ifdef HAVE_LIBRCC ++ unsigned int i, num; ++ rcc_language_config config; ++ ++ if (rcc_initialized) { ++ config = rccGetConfig(ctx, (rcc_language_id)lid); ++ num = rccConfigGetCharsetNumber(config); ++ for (i=0;i<(num?num:1);i++) ++ rcc_charsets[i] = (char*)rccUiGetCharsetName(uictx, (rcc_language_id)lid, (rcc_class_id)0 /* first class, they are equal*/, (rcc_charset_id)i); ++ ++ rcc_charsets[i] = NULL; ++ return rcc_charsets; ++ } ++#endif /* HAVE_LIBRCC */ ++ ++ return NULL; ++} ++ ++char *rccPatchFrom(gftp_request * request, const char *str) { ++#ifdef HAVE_LIBRCC ++ rcc_class_id cl; ++ if (rcc_initialized) { ++ switch (request->protonum) { ++ case GFTP_FTP_NUM: ++ case GFTP_FTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FTP; ++ break; ++ case GFTP_HTTP_NUM: ++ case GFTP_HTTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_HTTP; ++ break; ++ case GFTP_SSHV2_NUM: ++ cl = (rcc_class_id)RCC_CLASS_SSH; ++ break; ++ case GFTP_LOCAL_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FS; ++ break; ++ default: ++ return NULL; ++ } ++ ++ if ((cl == RCC_CLASS_FTP)||(cl == RCC_CLASS_HTTP)||(cl == RCC_CLASS_SSH)) { ++ if (request->language) rccSetLanguage(ctx, (rcc_language_id)request->language); ++ if (request->charset) rccSetCharset(ctx, cl, (rcc_charset_id)request->charset); ++ } ++ ++ return rccRecodeFromCharset(ctx, cl, "UTF-8", str); ++ } ++#endif /* HAVE_LIBRCC */ ++ return NULL; ++} ++ ++char *rccPatchTo(gftp_request * request, const char *str) { ++#ifdef HAVE_LIBRCC ++ rcc_class_id cl; ++ if (rcc_initialized) { ++ switch (request->protonum) { ++ case GFTP_FTP_NUM: ++ case GFTP_FTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FTP; ++ break; ++ case GFTP_HTTP_NUM: ++ case GFTP_HTTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_HTTP; ++ break; ++ case GFTP_SSHV2_NUM: ++ cl = (rcc_class_id)RCC_CLASS_SSH; ++ break; ++ case GFTP_LOCAL_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FS; ++ break; ++ default: ++ return NULL; ++ } ++ ++ if ((cl == RCC_CLASS_FTP)||(cl == RCC_CLASS_HTTP)||(cl == RCC_CLASS_SSH)) { ++ if (request->language) rccSetLanguage(ctx, (rcc_language_id)request->language); ++ if (request->charset) rccSetCharset(ctx, cl, (rcc_charset_id)request->charset); ++ } ++ ++ return rccRecodeToCharset(ctx, cl, "UTF-8", str); ++ } ++#endif /* HAVE_LIBRCC */ ++ return NULL; ++} ++ ++char *rccPatch(gftp_request *from, gftp_request *to, const char *str) { ++ char *res, *ret; ++ const char *tmp; ++ ++ if (from->protonum == to->protonum) return NULL; ++ printf("%u %u\n", from->protonum, to->protonum); ++ ++ tmp = strstr(str, to->directory); ++ if (!tmp) tmp = str; ++ ++ res = rccPatchTo(from, tmp); ++ if (!res) res = (char*)tmp; ++ ++ ret = rccPatchFrom(to, res); ++ if (ret) { ++ if (res!=tmp) free(res); ++ } else { ++ if (res!=tmp) ret = res; ++ else return NULL; ++ } ++ ++ if (tmp != str) { ++ res = (char*)malloc((strlen(ret) + (tmp-str) + 1)*sizeof(char)); ++ if (res) { ++ memcpy(res, str, (tmp-str)); ++ strcpy(res+(tmp-str), ret); ++ } ++ free(ret); ++ if (res) puts(res); ++ return res; ++ } ++ ++ return ret; ++} ++ ++char *rccPatchFromClass(gftp_request * request, int from, const char *str) { ++#ifdef HAVE_LIBRCC ++ rcc_class_id cl; ++ if (rcc_initialized) { ++ switch (request->protonum) { ++ case GFTP_FTP_NUM: ++ case GFTP_FTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FTP; ++ break; ++ case GFTP_HTTP_NUM: ++ case GFTP_HTTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_HTTP; ++ break; ++ case GFTP_SSHV2_NUM: ++ cl = (rcc_class_id)RCC_CLASS_SSH; ++ break; ++ case GFTP_LOCAL_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FS; ++ break; ++ default: ++ return NULL; ++ } ++ ++ if ((cl == RCC_CLASS_FTP)||(cl == RCC_CLASS_HTTP)||(cl == RCC_CLASS_SSH)) { ++ if (request->language) rccSetLanguage(ctx, (rcc_language_id)request->language); ++ if (request->charset) rccSetCharset(ctx, cl, (rcc_charset_id)request->charset); ++ } ++ ++ return rccRecode(ctx, (rcc_class_id)from, cl, str); ++ } ++#endif /* HAVE_LIBRCC */ ++ return NULL; ++} ++ ++char *rccPatchToClass(gftp_request * request, int to, const char *str) { ++#ifdef HAVE_LIBRCC ++ rcc_class_id cl; ++ if (rcc_initialized) { ++ switch (request->protonum) { ++ case GFTP_FTP_NUM: ++ case GFTP_FTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FTP; ++ break; ++ case GFTP_HTTP_NUM: ++ case GFTP_HTTPS_NUM: ++ cl = (rcc_class_id)RCC_CLASS_HTTP; ++ break; ++ case GFTP_SSHV2_NUM: ++ cl = (rcc_class_id)RCC_CLASS_SSH; ++ break; ++ case GFTP_LOCAL_NUM: ++ cl = (rcc_class_id)RCC_CLASS_FS; ++ break; ++ default: ++ return NULL; ++ } ++ ++ if ((cl == RCC_CLASS_FTP)||(cl == RCC_CLASS_HTTP)||(cl == RCC_CLASS_SSH)) { ++ if (request->language) rccSetLanguage(ctx, (rcc_language_id)request->language); ++ if (request->charset) rccSetCharset(ctx, cl, (rcc_charset_id)request->charset); ++ } ++ ++ return rccRecode(ctx, cl, (rcc_class_id)to, str); ++ } ++#endif /* HAVE_LIBRCC */ ++ return NULL; ++} ++ ++ ++char *rccPatchUTF2OUT(const char *str) { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ return rccRecodeFromCharset(ctx, RCC_CLASS_OUT, "UTF-8", str); ++ } ++#endif /* HAVE_LIBRCC */ ++ return NULL; ++} ++ ++char *rccPatchOUT2UTF(const char *str) { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ return rccRecodeToCharset(ctx, RCC_CLASS_OUT, "UTF-8", str); ++ } ++#endif /* HAVE_LIBRCC */ ++ return NULL; ++} +diff -dPNur gftp-2.0.18-orig/lib/rcc.h gftp-2.0.18-new/lib/rcc.h +--- gftp-2.0.18-orig/lib/rcc.h 1970-01-01 01:00:00.000000000 +0100 ++++ gftp-2.0.18-new/lib/rcc.h 2005-07-24 01:49:20.000000000 +0200 +@@ -0,0 +1,28 @@ ++#ifndef _RCC_H ++#define _RCC_H ++ ++#include "gftp.h" ++ ++#define RCC_CLASS_FTP 0 ++#define RCC_CLASS_HTTP 1 ++#define RCC_CLASS_SSH 2 ++#define RCC_CLASS_FS 3 ++#define RCC_CLASS_OUT 4 ++ ++void rccPatchFree(); ++void rccPatchInit(); ++ ++char **rccPatchGetLanguageList(); ++char **rccPatchGetCharsetList(int lid); ++ ++char *rccPatchFrom(gftp_request * request, const char *str); ++char *rccPatchTo(gftp_request * request, const char *str); ++char *rccPatch(gftp_request *from, gftp_request *to, const char *str); ++ ++char *rccPatchFromClass(gftp_request * request, int from, const char *str); ++char *rccPatchToClass(gftp_request * request, int to, const char *str); ++ ++char *rccPatchUTF2OUT(const char *str); ++char *rccPatchOUT2UTF(const char *str); ++ ++#endif /* _RCC_H */ +diff -dPNur gftp-2.0.18-orig/src/gtk/gtkui.c gftp-2.0.18-new/src/gtk/gtkui.c +--- gftp-2.0.18-orig/src/gtk/gtkui.c 2005-01-26 04:22:05.000000000 +0100 ++++ gftp-2.0.18-new/src/gtk/gtkui.c 2005-07-24 00:40:47.000000000 +0200 +@@ -351,6 +351,8 @@ + filelist = wdata->files; + templist = get_next_selection (templist, &filelist, &num); + curfle = filelist->data; ++ cdata->source_string = gftp_string_to_utf8(wdata->request, curfle->file); ++ if (!cdata->source_string) + cdata->source_string = g_strdup (curfle->file); + + tempstr = g_strdup_printf (_("What would you like to rename %s to?"), +diff -dPNur gftp-2.0.18-orig/src/gtk/Makefile.am gftp-2.0.18-new/src/gtk/Makefile.am +--- gftp-2.0.18-orig/src/gtk/Makefile.am 2005-01-16 17:12:08.000000000 +0100 ++++ gftp-2.0.18-new/src/gtk/Makefile.am 2005-07-23 19:16:26.000000000 +0200 +@@ -5,6 +5,6 @@ + gftp_gtk_SOURCES = bookmarks.c chmod_dialog.c delete_dialog.c dnd.c \ + gftp-gtk.c gtkui.c gtkui_transfer.c menu-items.c \ + misc-gtk.c options_dialog.c transfer.c view_dialog.c +-INCLUDES = @GTK_CFLAGS@ @PTHREAD_CFLAGS@ -I../../intl +-LDADD = ../../lib/libgftp.a ../../lib/fsplib/libfsp.a ../uicommon/libgftpui.a @GTK_LIBS@ @PTHREAD_LIBS@ @EXTRA_LIBS@ @GTHREAD_LIBS@ @SSL_LIBS@ @LIBINTL@ ++INCLUDES = @LIBRCC_INCLUDES@ @GTK_CFLAGS@ @PTHREAD_CFLAGS@ -I../../intl ++LDADD = ../../lib/libgftp.a ../../lib/fsplib/libfsp.a ../uicommon/libgftpui.a @GTK_LIBS@ @PTHREAD_LIBS@ @EXTRA_LIBS@ @GTHREAD_LIBS@ @SSL_LIBS@ @LIBINTL@ @LIBRCC_LIBS@ + noinst_HEADERS = gftp-gtk.h +diff -dPNur gftp-2.0.18-orig/src/text/gftp-text.c gftp-2.0.18-new/src/text/gftp-text.c +--- gftp-2.0.18-orig/src/text/gftp-text.c 2005-01-25 02:11:00.000000000 +0100 ++++ gftp-2.0.18-new/src/text/gftp-text.c 2005-07-24 01:54:25.000000000 +0200 +@@ -18,6 +18,7 @@ + /*****************************************************************************/ + + #include "gftp-text.h" ++#include "../../lib/rcc.h" + static const char cvsid[] = "$Id: gftp-text.c,v 1.45 2005/01/25 01:11:00 masneyb Exp $"; + + unsigned int +@@ -93,6 +94,7 @@ + const char *string, ...) + { + char tempstr[512], *utf8_str = NULL, *outstr; ++ char *locale_str; + va_list argp; + + g_return_if_fail (string != NULL); +@@ -140,7 +142,14 @@ + } + + if (level == gftp_logging_misc_nolog) ++{ ++ locale_str = rccPatchUTF2OUT(outstr); ++ if (locale_str) { ++ printf ("%s", locale_str); ++ free(locale_str); ++ } else + printf ("%s", outstr); ++} + else + gftp_text_write_string (request, outstr); + +@@ -158,6 +167,7 @@ + gchar *locale_question; + sigset_t sig, sigsave; + char *pos, *termname; ++ char *tmp; + int singlechar; + FILE *infd; + +@@ -247,6 +257,9 @@ + #else + char tempstr[512]; + #endif ++ char *recoded = NULL; ++ ++ rccPatchInit(); + + gftpui_common_init (&argc, &argv, gftp_text_log); + +@@ -298,9 +311,11 @@ + g_snprintf (prompt, sizeof (prompt), "%sftp%s> ", GFTPUI_COMMON_COLOR_BLUE, GFTPUI_COMMON_COLOR_DEFAULT); + while ((tempstr = readline (prompt))) + { ++ if (recoded) free(recoded); ++ recoded = rccPatchFromClass(gftp_text_remreq, RCC_CLASS_OUT, tempstr); + if (gftpui_common_process_command (locuidata, gftp_text_locreq, + remuidata, gftp_text_remreq, +- tempstr) == 0) ++ recoded?recoded:tempstr) == 0) + break; + + add_history (tempstr); +@@ -310,16 +325,20 @@ + printf ("%sftp%s> ", GFTPUI_COMMON_COLOR_BLUE, GFTPUI_COMMON_COLOR_DEFAULT); + while (fgets (tempstr, sizeof (tempstr), stdin) != NULL) + { ++ if (recoded) free(recoded); ++ recoded = rccPatchFromClass(gftp_tetxt_remreq, RCC_CLASS_OUT, tempstr); + if (gftpui_common_process_command (locuidata, gftp_text_locreq, + remuidata, gftp_text_remreq, +- tempstr) == 0) ++ recoded?recoded:tempstr) == 0) + break; + + printf ("%sftp%s> ", GFTPUI_COMMON_COLOR_BLUE, GFTPUI_COMMON_COLOR_DEFAULT); + } + #endif +- ++ if (recoded) free(recoded); ++ + gftp_shutdown (); ++ rccPatchFree(); + return (0); + } + +diff -dPNur gftp-2.0.18-orig/src/text/Makefile.am gftp-2.0.18-new/src/text/Makefile.am +--- gftp-2.0.18-orig/src/text/Makefile.am 2005-01-16 17:12:00.000000000 +0100 ++++ gftp-2.0.18-new/src/text/Makefile.am 2005-07-23 19:16:39.000000000 +0200 +@@ -3,7 +3,7 @@ + bin_PROGRAMS = @GFTP_TEXT@ + EXTRA_PROGRAMS = gftp-text + gftp_text_SOURCES=gftp-text.c textui.c +-INCLUDES=@GLIB_CFLAGS@ -I../../intl +-LDADD = ../../lib/libgftp.a ../../lib/fsplib/libfsp.a ../uicommon/libgftpui.a @GLIB_LIBS@ @EXTRA_LIBS@ @READLINE_LIBS@ @SSL_LIBS@ @LIBINTL@ ++INCLUDES=@LIBRCC_INCLUDES@ @GLIB_CFLAGS@ -I../../intl ++LDADD = ../../lib/libgftp.a ../../lib/fsplib/libfsp.a ../uicommon/libgftpui.a @GLIB_LIBS@ @EXTRA_LIBS@ @READLINE_LIBS@ @SSL_LIBS@ @LIBINTL@ @LIBRCC_LIBS@ + noinst_HEADERS=gftp-text.h + localedir=$(datadir)/locale +diff -dPNur gftp-2.0.18-orig/lib/protocols.c gftp-2.0.18-new/lib/protocols.c +--- gftp-2.0.18-orig/lib/protocols.c 2005-07-23 15:30:59.000000000 +0200 ++++ gftp-2.0.18-new/lib/protocols.c 2005-07-24 00:56:12.000000000 +0200 +@@ -18,6 +18,8 @@ + /*****************************************************************************/ + + #include "gftp.h" ++#include "rcc.h" ++ + static const char cvsid[] = "$Id: protocols.c,v 1.125 2005/01/25 02:34:18 masneyb Exp $"; + + gftp_request * +@@ -26,6 +28,8 @@ + gftp_request *request; + + request = g_malloc0 (sizeof (*request)); ++ request->language = 0; ++ request->charset = 0; + request->datafd = -1; + request->cachefd = -1; + request->server_type = GFTP_DIRTYPE_OTHER; +@@ -460,6 +469,9 @@ + gftp_lookup_request_option (request, "remote_charsets", &tempstr); + if (*tempstr == '\0') + { ++ ret = rccPatchTo(request, str); ++ if (ret) return ret; ++ + error = NULL; + if ((ret = g_locale_to_utf8 (str, -1, &bread, &bwrite, &error)) != NULL) + return (ret); +@@ -531,6 +544,9 @@ + gftp_lookup_request_option (request, "remote_charsets", &tempstr); + if (*tempstr == '\0') + { ++ ret = rccPatchFrom(request, str); ++ if (ret) return ret; ++ + error = NULL; + if ((ret = g_locale_from_utf8 (str, -1, &bread, &bwrite, &error)) != NULL) + return (ret); +@@ -919,6 +935,18 @@ + } + + ++void ++gftp_set_language (gftp_request * request, int language) { ++ g_return_if_fail (request != NULL); ++ request->language = language; ++} ++ ++void ++gftp_set_charset (gftp_request * request, int charset) { ++ g_return_if_fail (request != NULL); ++ request->charset = charset; ++} ++ + void + gftp_set_hostname (gftp_request * request, const char *hostname) + { +@@ -1056,6 +1084,7 @@ + const char *newname) + { + char *utf8; ++ char *oldutf8; + int ret; + + g_return_val_if_fail (request != NULL, GFTP_EFATAL); +@@ -1064,13 +1093,13 @@ + return (GFTP_EFATAL); + + utf8 = gftp_string_from_utf8 (request, newname); ++ oldutf8 = gftp_string_from_utf8 (request, oldname); ++ ret = request->rename (request, oldutf8?oldutf8:oldname, utf8?utf8:newname); ++ + if (utf8 != NULL) +- { +- ret = request->rename (request, oldname, utf8); + g_free (utf8); +- } +- else +- ret = request->rename (request, oldname, newname); ++ if (oldutf8 != NULL) ++ g_free (oldutf8); + + return (ret); + } +@@ -1948,11 +1977,14 @@ + (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL) + fle->startsize = *newsize; + +- if (transfer->toreq && fle->destfile == NULL) ++ if (transfer->toreq && fle->destfile == NULL) { ++ newname = rccPatch(transfer->fromreq, transfer->toreq, fle->file); + fle->destfile = gftp_build_path (transfer->toreq, + transfer->toreq->directory, +- fle->file, NULL); +- ++ newname?newname:fle->file, NULL); ++ if (newname) free(newname); ++ } ++ + if (transfer->fromreq->directory != NULL && + *transfer->fromreq->directory != '\0' && + *fle->file != '/') +@@ -2026,11 +2058,15 @@ + return (curfle->size); + } + +- if (transfer->toreq && curfle->destfile == NULL) ++ if (transfer->toreq && curfle->destfile == NULL) { ++ newname = rccPatch(transfer->fromreq, transfer->toreq, curfle->file); + curfle->destfile = gftp_build_path (transfer->toreq, + transfer->toreq->directory, +- curfle->file, NULL); ++ newname?newname:curfle->file, NULL); ++ if (newname) free(newname); ++ } + ++ + if (transfer->fromreq->directory != NULL && + *transfer->fromreq->directory != '\0' && *curfle->file != '/') + { +diff -dPNur gftp-2.0.18-orig/src/gtk/gftp-gtk.c gftp-2.0.18-new/src/gtk/gftp-gtk.c +--- gftp-2.0.18-orig/src/gtk/gftp-gtk.c 2005-01-25 03:34:19.000000000 +0100 ++++ gftp-2.0.18-new/src/gtk/gftp-gtk.c 2005-07-23 22:22:42.000000000 +0200 +@@ -18,6 +18,7 @@ + /*****************************************************************************/ + + #include "gftp-gtk.h" ++#include "../../lib/rcc.h" + static const char cvsid[] = "$Id: gftp-gtk.c,v 1.66 2005/01/25 02:34:19 masneyb Exp $"; + + static GtkItemFactory *log_factory, *dl_factory; +@@ -28,6 +29,7 @@ + GtkWidget * stop_btn, * hostedit, * useredit, * passedit, * portedit, * logwdw, + * dlwdw, * protocol_menu, * optionmenu, * gftpui_command_widget, + * download_left_arrow, * upload_right_arrow, * openurl_btn; ++GtkWidget * language_menu, * charset_menu; + GtkTooltips * openurl_tooltip; + GtkAdjustment * logwdw_vadj; + #if GTK_MAJOR_VERSION > 1 +@@ -420,6 +422,42 @@ + return (factory->widget); + } + ++#ifdef HAVE_LIBRCC ++static int rcc_current_language = 0; ++static int rcc_current_charset = 0; ++ ++static void rccCharsetCB(GtkWidget * w, gpointer item) { ++ rcc_current_charset = g_list_index(GTK_MENU_SHELL(charset_menu)->children, gtk_menu_get_active(GTK_MENU(charset_menu))); ++} ++ ++static void rccLanguageCB(GtkWidget * w, gpointer item) { ++ GtkWidget *tempwid, *optionmenu; ++ unsigned int i; ++ char **langs; ++ gint cur; ++ ++ cur = g_list_index(GTK_MENU_SHELL(language_menu)->children, gtk_menu_get_active(GTK_MENU(language_menu))); ++ optionmenu = gtk_menu_get_attach_widget(GTK_MENU(charset_menu)); ++ ++ rcc_current_language = cur; ++ rcc_current_charset = 0; ++ ++ langs = rccPatchGetCharsetList(cur); ++ if (langs) { ++ charset_menu = gtk_menu_new (); ++ for (i=0;langs[i];i++) { ++ tempwid = gtk_menu_item_new_with_label (langs[i]); ++ gtk_object_set_user_data (GTK_OBJECT (tempwid), GINT_TO_POINTER(i)); ++ gtk_menu_append (GTK_MENU (charset_menu), tempwid); ++ gtk_widget_show (tempwid); ++ } ++ ++ gtk_option_menu_remove_menu (GTK_OPTION_MENU (optionmenu)); ++ gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), charset_menu); ++ gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 0); ++ } ++} ++#endif /* HAVE_LIBRCC */ + + static GtkWidget * + CreateConnectToolbar (GtkWidget * parent) +@@ -430,14 +468,19 @@ + {"application/x-rootwin-drop", 0, 1} + }; + GtkWidget *toolbar, *box, *tempwid; ++ GtkWidget *vbox; ++ GtkWidget *tmpoptionmenu; + gftp_config_list_vars * tmplistvar; + char *default_protocol, *tempstr; ++ char **langs; + int i, num; + + toolbar = gtk_handle_box_new (); + ++ vbox = gtk_vbox_new (FALSE, 0); + box = gtk_hbox_new (FALSE, 4); +- gtk_container_add (GTK_CONTAINER (toolbar), box); ++ gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0); ++ gtk_container_add (GTK_CONTAINER (toolbar), vbox); + gtk_container_border_width (GTK_CONTAINER (box), 5); + + openurl_tooltip = gtk_tooltips_new (); +@@ -548,6 +591,7 @@ + optionmenu = gtk_option_menu_new (); + gtk_box_pack_start (GTK_BOX (tempwid), optionmenu, TRUE, FALSE, 0); + ++ + num = 0; + gftp_lookup_global_option ("default_protocol", &default_protocol); + protocol_menu = gtk_menu_new (); +@@ -584,6 +628,61 @@ + gtk_container_border_width (GTK_CONTAINER (stop_btn), 1); + gtk_box_pack_start (GTK_BOX (box), stop_btn, FALSE, FALSE, 0); + ++#ifdef HAVE_LIBRCC ++ box = gtk_hbox_new (FALSE, 4); ++ gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0); ++ gtk_container_border_width (GTK_CONTAINER (box), 5); ++ ++ langs = rccPatchGetCharsetList(0); ++ if (langs) { ++ tempwid = gtk_vbox_new (FALSE, 0); ++ gtk_box_pack_end (GTK_BOX (box), tempwid, FALSE, FALSE, 0); ++ ++ tmpoptionmenu = gtk_option_menu_new (); ++ gtk_box_pack_start (GTK_BOX (tempwid), tmpoptionmenu, TRUE, FALSE, 0); ++ ++ charset_menu = gtk_menu_new (); ++ for (i=0;langs[i];i++) { ++ tempwid = gtk_menu_item_new_with_label (langs[i]); ++ gtk_signal_connect(GTK_OBJECT(tempwid), "activate", GTK_SIGNAL_FUNC(rccCharsetCB), NULL); ++ gtk_object_set_user_data (GTK_OBJECT (tempwid), GINT_TO_POINTER(i)); ++ gtk_menu_append (GTK_MENU (charset_menu), tempwid); ++ gtk_widget_show (tempwid); ++ } ++ ++ gtk_option_menu_set_menu (GTK_OPTION_MENU (tmpoptionmenu), charset_menu); ++ gtk_option_menu_set_history (GTK_OPTION_MENU (tmpoptionmenu), rcc_current_charset); ++ ++ tempwid = gtk_label_new (_("Charset: ")); ++ gtk_box_pack_end (GTK_BOX (box), tempwid, FALSE, FALSE, 0); ++ } ++ ++ langs = rccPatchGetLanguageList(); ++ if (langs) { ++ tempwid = gtk_vbox_new (FALSE, 0); ++ gtk_box_pack_end (GTK_BOX (box), tempwid, FALSE, FALSE, 0); ++ ++ tmpoptionmenu = gtk_option_menu_new (); ++ gtk_box_pack_start (GTK_BOX (tempwid), tmpoptionmenu, TRUE, FALSE, 0); ++ ++ language_menu = gtk_menu_new (); ++ for (i=0;langs[i];i++) { ++ tempwid = gtk_menu_item_new_with_label (langs[i]); ++ gtk_signal_connect(GTK_OBJECT(tempwid), "activate", GTK_SIGNAL_FUNC(rccLanguageCB), NULL); ++ gtk_object_set_user_data (GTK_OBJECT (tempwid), GINT_TO_POINTER(i)); ++ gtk_menu_append (GTK_MENU (language_menu), tempwid); ++ gtk_widget_show (tempwid); ++ } ++ ++ gtk_option_menu_set_menu (GTK_OPTION_MENU (tmpoptionmenu), language_menu); ++ gtk_option_menu_set_history (GTK_OPTION_MENU (tmpoptionmenu), rcc_current_language); ++ ++ tempwid = gtk_label_new (_("Language: ")); ++ gtk_box_pack_end (GTK_BOX (box), tempwid, FALSE, FALSE, 0); ++ } ++#endif /* HAVE_LIBRCC */ ++ ++ + gtk_widget_grab_focus (GTK_COMBO (hostedit)->entry); + + return (toolbar); +@@ -1132,6 +1231,16 @@ + add_history (current_wdata->combo, current_wdata->history, + current_wdata->histlen, current_wdata->request->directory); + ++#ifdef HAVE_LIBRCC ++ tempwid = gtk_menu_get_active (GTK_MENU (language_menu)); ++ num = GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (tempwid))); ++ gftp_set_language(current_wdata->request, num); ++ ++ tempwid = gtk_menu_get_active (GTK_MENU (charset_menu)); ++ num = GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (tempwid))); ++ gftp_set_charset(current_wdata->request, num); ++#endif /* HAVE_LIBRCC */ ++ + ftp_connect (current_wdata, current_wdata->request, 1); + } + +@@ -1270,6 +1379,8 @@ + { + GtkWidget *window, *ui; + ++ rccPatchInit(); ++ + /* We override the read color functions because we are using a GdkColor + structures to store the color. If I put this in lib/config_file.c, then + the core library would be dependant on Gtk+ being present */ +@@ -1336,6 +1447,8 @@ + GDK_THREADS_ENTER (); + gtk_main (); + GDK_THREADS_LEAVE (); ++ ++ rccPatchFree(); + + return (0); + } diff --git a/patches/gstreamer/gst-plugins-good-0.10.16-rusxmms.diff b/patches/gstreamer/gst-plugins-good-0.10.16-rusxmms.diff new file mode 100644 index 0000000..95aea19 --- /dev/null +++ b/patches/gstreamer/gst-plugins-good-0.10.16-rusxmms.diff @@ -0,0 +1,224 @@ +diff -dPNur gst-plugins-good-0.10.16/configure.ac gst-plugins-good-0.10.16-ds/configure.ac +--- gst-plugins-good-0.10.16/configure.ac 2009-08-29 00:05:24.000000000 +0400 ++++ gst-plugins-good-0.10.16-ds/configure.ac 2009-10-29 06:20:29.000000000 +0300 +@@ -939,6 +939,13 @@ + AC_SUBST(BZ2_LIBS) + ]) + ++dnl *** id3demux to use LibRCC ++translit(dnm, m, l) AM_CONDITIONAL(USE_LIBRCC, true) ++AG_GST_CHECK_FEATURE(LIBRCC, [librcc support for id3demux],, [ ++ AG_GST_CHECK_LIBHEADER(LIBRCC, rcc, rccInit, ,librcc.h, LIBRCC_LIBS="-lrcc") ++ AC_SUBST(LIBRCC_LIBS) ++]) ++ + else + + dnl not building plugins with external dependencies, +@@ -974,6 +981,7 @@ + AM_CONDITIONAL(USE_XSHM, false) + AM_CONDITIONAL(USE_XVIDEO, false) + AM_CONDITIONAL(USE_ZLIB, false) ++AM_CONDITIONAL(USE_LIBRCC, false) + + fi dnl of EXT plugins + +diff -dPNur gst-plugins-good-0.10.16/gst/id3demux/gstid3demux.c gst-plugins-good-0.10.16-ds/gst/id3demux/gstid3demux.c +--- gst-plugins-good-0.10.16/gst/id3demux/gstid3demux.c 2009-08-11 02:15:55.000000000 +0400 ++++ gst-plugins-good-0.10.16-ds/gst/id3demux/gstid3demux.c 2009-10-29 06:44:25.000000000 +0300 +@@ -56,6 +56,7 @@ + + #include "gstid3demux.h" + #include "id3tags.h" ++#include "rccpatch.h" + + static const GstElementDetails gst_id3demux_details = + GST_ELEMENT_DETAILS ("ID3 tag demuxer", +@@ -107,11 +108,22 @@ + } + + static void ++gst_id3demux_finalize (GObject * object) ++{ ++ GstID3Demux *demux = GST_ID3DEMUX (object); ++ ++ rcc_patch_unref(); ++ ++ G_OBJECT_CLASS (parent_class)->finalize (object); ++} ++ ++static void + gst_id3demux_class_init (GstID3DemuxClass * klass) + { + GstTagDemuxClass *tagdemux_class = (GstTagDemuxClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; + ++ gobject_class->finalize = gst_id3demux_finalize; + gobject_class->set_property = gst_id3demux_set_property; + gobject_class->get_property = gst_id3demux_get_property; + +@@ -133,6 +145,7 @@ + gst_id3demux_init (GstID3Demux * id3demux, GstID3DemuxClass * klass) + { + id3demux->prefer_v1 = DEFAULT_PREFER_V1; ++ rcc_patch_ref(); + } + + static gboolean +diff -dPNur gst-plugins-good-0.10.16/gst/id3demux/id3v2frames.c gst-plugins-good-0.10.16-ds/gst/id3demux/id3v2frames.c +--- gst-plugins-good-0.10.16/gst/id3demux/id3v2frames.c 2009-08-11 02:15:55.000000000 +0400 ++++ gst-plugins-good-0.10.16-ds/gst/id3demux/id3v2frames.c 2009-10-29 06:40:17.000000000 +0300 +@@ -33,6 +33,7 @@ + #endif + + #include "id3tags.h" ++#include "rccpatch.h" + + GST_DEBUG_CATEGORY_EXTERN (id3demux_debug); + #define GST_CAT_DEFAULT (id3demux_debug) +@@ -986,7 +987,12 @@ + utf8 = NULL; + } + } +- } ++ } ++ ++ /* Try LibRCC library to detect encoding */ ++ utf8 = rcc_patch_to_utf8(start, size); ++ if (utf8) goto beach; ++ + /* Try current locale (if not UTF-8) */ + if (!g_get_charset (&env)) { + if ((utf8 = g_locale_to_utf8 (start, size, &bytes_read, NULL, NULL))) { +diff -dPNur gst-plugins-good-0.10.16/gst/id3demux/Makefile.am gst-plugins-good-0.10.16-ds/gst/id3demux/Makefile.am +--- gst-plugins-good-0.10.16/gst/id3demux/Makefile.am 2009-08-11 02:15:55.000000000 +0400 ++++ gst-plugins-good-0.10.16-ds/gst/id3demux/Makefile.am 2009-10-29 06:20:06.000000000 +0300 +@@ -1,10 +1,15 @@ + plugin_LTLIBRARIES = libgstid3demux.la + +-libgstid3demux_la_SOURCES = gstid3demux.c id3tags.c id3v2frames.c ++libgstid3demux_la_SOURCES = gstid3demux.c id3tags.c id3v2frames.c rccpatch.c + libgstid3demux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) + libgstid3demux_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_MAJORMINOR@ \ + -lgstpbutils-@GST_MAJORMINOR@ $(GST_BASE_LIBS) $(ZLIB_LIBS) + libgstid3demux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + libgstid3demux_la_LIBTOOLFLAGS = --tag=disable-static + +-noinst_HEADERS = gstid3demux.h id3tags.h ++if USE_LIBRCC ++ libgstid3demux_la_LIBADD += @LIBRCC_LIBS@ ++endif ++ ++ ++noinst_HEADERS = gstid3demux.h id3tags.h rccpatch.h +diff -dPNur gst-plugins-good-0.10.16/gst/id3demux/rccpatch.c gst-plugins-good-0.10.16-ds/gst/id3demux/rccpatch.c +--- gst-plugins-good-0.10.16/gst/id3demux/rccpatch.c 1970-01-01 03:00:00.000000000 +0300 ++++ gst-plugins-good-0.10.16-ds/gst/id3demux/rccpatch.c 2009-10-29 07:05:20.000000000 +0300 +@@ -0,0 +1,91 @@ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include <stdlib.h> ++#include "rccpatch.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 */ ++ ++ ++static void rcc_patch_free() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ puts("clean"); ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rcc_patch_init() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ puts("init"); ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++static int registered = 0; ++static int ref_count = 0; ++static GStaticMutex lock = G_STATIC_MUTEX_INIT; ++ ++void rcc_patch_ref() { ++ puts("ref"); ++ g_static_mutex_lock(&lock); ++ if (!registered) { ++ g_atexit(rcc_patch_free); ++ registered = 1; ++ } ++ if (++ref_count==1) rcc_patch_init(); ++ g_static_mutex_unlock(&lock); ++} ++ ++void rcc_patch_unref() { ++ puts("unref"); ++ g_static_mutex_lock(&lock); ++ if (--ref_count==0) rcc_patch_free(); ++ g_static_mutex_unlock(&lock); ++} ++ ++gchar *rcc_patch_to_utf8(const gchar *str, const guint size) { ++#ifdef HAVE_LIBRCC ++ gchar *res; ++ ++ if (rcc_initialized) { ++ g_static_mutex_lock(&lock); ++ res = rccSizedRecode(ctx, ID3_CLASS, UTF_CLASS, str, size, NULL); ++ g_static_mutex_unlock(&lock); ++ ++ return res; ++ } ++#endif /* HAVE_LIBRCC */ ++ ++ return NULL; ++} ++ +diff -dPNur gst-plugins-good-0.10.16/gst/id3demux/rccpatch.h gst-plugins-good-0.10.16-ds/gst/id3demux/rccpatch.h +--- gst-plugins-good-0.10.16/gst/id3demux/rccpatch.h 1970-01-01 03:00:00.000000000 +0300 ++++ gst-plugins-good-0.10.16-ds/gst/id3demux/rccpatch.h 2009-10-29 06:23:58.000000000 +0300 +@@ -0,0 +1,12 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <gst/gst.h> ++ ++void rcc_patch_ref(); ++void rcc_patch_unref(); ++ ++gchar *rcc_patch_to_utf8(const gchar *str, const guint size); ++ ++ ++#endif /* _RCC_PATCH_H */ diff --git a/patches/gstreamer/gstreamer b/patches/gstreamer/gstreamer new file mode 100644 index 0000000..86a0b5f --- /dev/null +++ b/patches/gstreamer/gstreamer @@ -0,0 +1,14 @@ +totem -> gstreamer -> + mp3 playback [mad,ffmpeg,flump3dec] + id3 id3demux (plugins-good) + it uses tag functions (from plugins-base/gst-libs/gst/tag) to + access id3 v.1 and maintains id3 v.2 itself. + +tag contains 'gst_tag_freeform_string_to_utf8' which should be rcc'ized and +used from id3demux (and probably other places) instead of current patch. + +The question is initialization... + + +GST_TAG_ENCODING=CP1251 totem 01_-_vpotmah_192_lame_cbr.mp3 + diff --git a/patches/gstreamer/libid3_problems b/patches/gstreamer/libid3_problems new file mode 100644 index 0000000..4d74a7f --- /dev/null +++ b/patches/gstreamer/libid3_problems @@ -0,0 +1,3 @@ +problems with building of libid3 complaining due to id3_frametype_* undefined are due to + - missing gperf and as a result empty frametype.c and compat.c generated + - gperf should be installed and empty frametype.c, compat.c deleted diff --git a/patches/id3lib/id3lib-ds-rcc.patch b/patches/id3lib/id3lib-ds-rcc.patch new file mode 100644 index 0000000..22c7aa9 --- /dev/null +++ b/patches/id3lib/id3lib-ds-rcc.patch @@ -0,0 +1,169 @@ +diff -dPNur id3lib-3.8.3-orig/configure.in id3lib-3.8.3-new/configure.in +--- id3lib-3.8.3-orig/configure.in 2003-03-02 01:23:00.000000000 +0100 ++++ id3lib-3.8.3-new/configure.in 2005-07-19 22:03:12.000000000 +0200 +@@ -217,6 +217,20 @@ + LIBS="$LIBS $ICONV_LIB" + fi + ++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 Check for c++ features + AC_LANG_SAVE + AC_LANG_CPLUSPLUS +@@ -315,5 +329,5 @@ + src/Makefile \ + examples/Makefile \ + prj/Makefile \ +- libprj/Makefile ++ libprj/Makefile + ) +diff -dPNur id3lib-3.8.3-orig/src/field_string_ascii.cpp id3lib-3.8.3-new/src/field_string_ascii.cpp +--- id3lib-3.8.3-orig/src/field_string_ascii.cpp 2003-03-02 01:23:00.000000000 +0100 ++++ id3lib-3.8.3-new/src/field_string_ascii.cpp 2005-07-19 21:34:12.000000000 +0200 +@@ -27,6 +27,7 @@ + #include "field_impl.h" + #include "id3/utils.h" // has <config.h> "id3/id3lib_streams.h" "id3/globals.h" "id3/id3lib_strings.h" + #include "io_helpers.h" ++#include "rccpatch.h" + + using namespace dami; + +@@ -92,8 +93,15 @@ + buffer != NULL && maxLength > 0) + { + String data = this->GetText(); ++ char *recoded = rccPatchRecode(data.data(), (size_t)data.size(), (size_t*)&size); ++ if (recoded) { ++ size = dami::min(maxLength, size); ++ ::memcpy(buffer, recoded, size); ++ free(recoded); ++ } else { + size = dami::min(maxLength, data.size()); + ::memcpy(buffer, data.data(), size); ++ } + if (size < maxLength) + { + buffer[size] = '\0'; +diff -dPNur id3lib-3.8.3-orig/src/Makefile.am id3lib-3.8.3-new/src/Makefile.am +--- id3lib-3.8.3-orig/src/Makefile.am 2003-03-02 01:23:00.000000000 +0100 ++++ id3lib-3.8.3-new/src/Makefile.am 2005-07-19 21:38:31.000000000 +0200 +@@ -17,7 +17,7 @@ + zlib_include = + endif + +-INCLUDES = \ ++INCLUDES = @LIBRCC_INCLUDES@ \ + @ID3LIB_DEBUG_FLAGS@ -I$(top_srcdir)/include/id3 -I$(top_srcdir)/include $(zlib_include) + + noinst_HEADERS = \ +@@ -31,7 +31,8 @@ + header_tag.h \ + mp3_header.h \ + tag_impl.h \ +- spec.h ++ spec.h \ ++ rccpatch.h + + id3lib_sources = \ + c_wrapper.cpp \ +@@ -66,7 +67,8 @@ + tag_parse_v1.cpp \ + tag_render.cpp \ + utils.cpp \ +- writers.cpp ++ writers.cpp \ ++ rccpatch.cpp + + lib_LTLIBRARIES = libid3.la + +@@ -77,6 +79,7 @@ + endif + + libid3_la_LDFLAGS = \ ++ @LIBRCC_LIBS@ \ + -version-info $(LT_VERSION) \ + -release $(LT_RELEASE) \ + -export-dynamic +diff -dPNur id3lib-3.8.3-orig/src/rccpatch.cpp id3lib-3.8.3-new/src/rccpatch.cpp +--- id3lib-3.8.3-orig/src/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ id3lib-3.8.3-new/src/rccpatch.cpp 2005-07-19 22:10:47.000000000 +0200 +@@ -0,0 +1,60 @@ ++#include <stdlib.h> ++ ++#include "../config.h" ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define OUT_CLASS 1 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, NULL, NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++#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 */ ++} ++ ++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 ++ char *res; ++ rccPatchTryInit(); ++ return rccSizedRecode(NULL, ID3_CLASS, OUT_CLASS, str, len, rlen); ++#else ++ return NULL; ++#endif /* HAVE_LIBRCC */ ++} +diff -dPNur id3lib-3.8.3-orig/src/rccpatch.h id3lib-3.8.3-new/src/rccpatch.h +--- id3lib-3.8.3-orig/src/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ id3lib-3.8.3-new/src/rccpatch.h 2005-07-19 21:34:51.000000000 +0200 +@@ -0,0 +1,3 @@ ++void rccPatchFree(); ++void rccPatchInit(); ++char *rccPatchRecode(const char *str, size_t len, size_t *rlen); diff --git a/patches/libid3tag/README b/patches/libid3tag/README new file mode 100644 index 0000000..f927e0d --- /dev/null +++ b/patches/libid3tag/README @@ -0,0 +1,2 @@ +Read-only patch. The configuration in 'xmms' config. Both ID3 ID3 v.2 Latin1 +encoding is taken out of 'id3' class. diff --git a/patches/libid3tag/libid3tag-0.15.1b-ds-rcc.patch b/patches/libid3tag/libid3tag-0.15.1b-ds-rcc.patch new file mode 100644 index 0000000..4641f3d --- /dev/null +++ b/patches/libid3tag/libid3tag-0.15.1b-ds-rcc.patch @@ -0,0 +1,300 @@ +diff -dPNur libid3tag-0.15.1b/configure.ac libid3tag-0.15.1b-ds/configure.ac +--- libid3tag-0.15.1b/configure.ac 2004-01-24 00:22:46.000000000 +0100 ++++ libid3tag-0.15.1b-ds/configure.ac 2008-04-12 21:36:35.000000000 +0200 +@@ -145,6 +145,22 @@ + *** environment variable to specify its installed location, e.g. -L<dir>.]) + ]) + ++ ++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 handle --enable and --disable options + + AC_CACHE_SAVE +diff -dPNur libid3tag-0.15.1b/latin1.c libid3tag-0.15.1b-ds/latin1.c +--- libid3tag-0.15.1b/latin1.c 2004-01-23 10:41:32.000000000 +0100 ++++ libid3tag-0.15.1b-ds/latin1.c 2008-04-12 21:36:35.000000000 +0200 +@@ -31,6 +31,9 @@ + # include "latin1.h" + # include "ucs4.h" + ++# include "utf8.h" ++# include "rccpatch.h" ++ + /* + * NAME: latin1->length() + * DESCRIPTION: return the number of ucs4 chars represented by a latin1 string +@@ -172,6 +175,11 @@ + id3_length_t size = 0; + id3_latin1_t latin1[1], *out; + ++/* ++ Theoretically, we should add here a code for converting ucs4 to ++ recoded latin1 string. However, using non-standard latin1 tags ++ in ID3v.2 tags is completely idiotic. So, I'll not do that. ++*/ + while (*ucs4) { + switch (id3_latin1_encodechar(out = latin1, *ucs4++)) { + case 1: size += id3_latin1_put(ptr, *out++); +@@ -193,6 +201,7 @@ + { + id3_byte_t const *end; + id3_latin1_t *latin1ptr, *latin1; ++ id3_utf8_t *utf8; + id3_ucs4_t *ucs4; + + end = *ptr + length; +@@ -207,6 +216,19 @@ + + *latin1ptr = 0; + ++ ++ utf8 = rccPatchLatin2UTF(latin1); ++ if (utf8) { ++ ucs4 = malloc((id3_utf8_length(utf8) + 1) * sizeof(*ucs4)); ++ if (ucs4) ++ id3_utf8_decode(utf8, ucs4); ++ free(utf8); ++ free(latin1); ++ ++ ++ return ucs4; ++ } ++ + ucs4 = malloc((id3_latin1_length(latin1) + 1) * sizeof(*ucs4)); + if (ucs4) + id3_latin1_decode(latin1, ucs4); +diff -dPNur libid3tag-0.15.1b/Makefile.am libid3tag-0.15.1b-ds/Makefile.am +--- libid3tag-0.15.1b/Makefile.am 2004-02-17 03:11:28.000000000 +0100 ++++ libid3tag-0.15.1b-ds/Makefile.am 2008-04-12 21:36:35.000000000 +0200 +@@ -81,6 +81,7 @@ + libid3tag_la_SOURCES = version.c ucs4.c latin1.c utf16.c utf8.c \ + parse.c render.c field.c frametype.c compat.c \ + genre.c frame.c crc.c util.c tag.c file.c \ ++ rccpatch.c rccpatch.h \ + version.h ucs4.h latin1.h utf16.h utf8.h \ + parse.h render.h field.h frametype.h compat.h \ + genre.h frame.h crc.h util.h tag.h file.h \ +@@ -90,7 +91,8 @@ + frametype.gperf compat.gperf genre.dat.in \ + debug.c debug.h + +-libid3tag_la_LDFLAGS = -version-info $(version_info) ++INCLUDES = @LIBRCC_INCLUDES@ ++libid3tag_la_LDFLAGS = -version-info $(version_info) @LIBRCC_LIBS@ + + BUILT_SOURCES = frametype.c compat.c genre.dat + +diff -dPNur libid3tag-0.15.1b/rccpatch.c libid3tag-0.15.1b-ds/rccpatch.c +--- libid3tag-0.15.1b/rccpatch.c 1970-01-01 01:00:00.000000000 +0100 ++++ libid3tag-0.15.1b-ds/rccpatch.c 2008-04-12 21:36:35.000000000 +0200 +@@ -0,0 +1,96 @@ ++#include <stdlib.h> ++#include "rccpatch.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 */ ++} ++ ++ ++id3_utf8_t *rccPatchLatin2UTF(id3_latin1_t *str) { ++#ifdef HAVE_LIBRCC ++ rccPatchTryInit(); ++ ++ return rccRecode(ctx, ID3_CLASS, UTF_CLASS, str); ++#else ++ return NULL; ++#endif /* HAVE_LIBRCC */ ++} ++ ++id3_latin1_t *rccPatchUTF2Latin(id3_utf8_t *str) { ++#ifdef HAVE_LIBRCC ++ rccPatchTryInit(); ++ ++ return rccRecode(ctx, UTF_CLASS, ID3_CLASS, str); ++#else ++ return NULL; ++#endif /* HAVE_LIBRCC */ ++} ++ ++id3_latin1_t *rccPatchUTF2Out(id3_utf8_t *str) { ++#ifdef HAVE_LIBRCC ++ rccPatchTryInit(); ++ ++ return rccRecode(ctx, UTF_CLASS, OUT_CLASS, str); ++#else ++ return NULL; ++#endif /* HAVE_LIBRCC */ ++} ++ +diff -dPNur libid3tag-0.15.1b/rccpatch.h libid3tag-0.15.1b-ds/rccpatch.h +--- libid3tag-0.15.1b/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ libid3tag-0.15.1b-ds/rccpatch.h 2008-04-12 21:36:35.000000000 +0200 +@@ -0,0 +1,15 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include "id3tag.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++id3_utf8_t *rccPatchLatin2UTF(id3_latin1_t *str); ++id3_latin1_t *rccPatchUTF2Latin(id3_utf8_t *str); ++id3_latin1_t *rccPatchUTF2Out(id3_utf8_t *str); ++ ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur libid3tag-0.15.1b/tag.c libid3tag-0.15.1b-ds/tag.c +--- libid3tag-0.15.1b/tag.c 2004-02-17 03:04:10.000000000 +0100 ++++ libid3tag-0.15.1b-ds/tag.c 2008-04-12 21:37:12.000000000 +0200 +@@ -45,6 +45,9 @@ + # include "field.h" + # include "util.h" + ++# include "utf8.h" ++# include "rccpatch.h" ++ + /* + * NAME: tag->new() + * DESCRIPTION: allocate and return a new, empty tag +@@ -335,6 +338,8 @@ + { + struct id3_frame *frame; + id3_ucs4_t ucs4[31]; ++ ++ id3_utf8_t *utf8; + + if (text) { + trim(text); +@@ -350,9 +355,15 @@ + ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1) + goto fail; + +- if (text) ++ if (text) { ++ utf8 = rccPatchLatin2UTF(text); ++ if (utf8) { ++ if (strlen(utf8) > 30) utf8[30] = 0; ++ id3_utf8_decode(utf8, ucs4); ++ free(utf8); ++ } else + id3_latin1_decode(text, ucs4); +- else ++ } else + id3_ucs4_putnumber(ucs4, number); + + if (strcmp(id, ID3_FRAME_COMMENT) == 0) { +diff -dPNur libid3tag-0.15.1b/ucs4.c libid3tag-0.15.1b-ds/ucs4.c +--- libid3tag-0.15.1b/ucs4.c 2004-01-23 10:41:32.000000000 +0100 ++++ libid3tag-0.15.1b-ds/ucs4.c 2008-04-12 21:36:35.000000000 +0200 +@@ -33,6 +33,9 @@ + # include "utf16.h" + # include "utf8.h" + ++# include <string.h> ++# include "rccpatch.h" ++ + id3_ucs4_t const id3_ucs4_empty[] = { 0 }; + + /* +@@ -125,6 +128,27 @@ + { + id3_latin1_t *latin1; + ++ ++ id3_latin1_t *ltmp; ++ id3_utf8_t *utf8; ++ ++ utf8 = malloc(id3_ucs4_utf8size(ucs4) * sizeof(*utf8)); ++ if (utf8) { ++ id3_utf8_encode(utf8, ucs4); ++ ltmp = rccPatchUTF2Out(utf8); ++ free(utf8); ++ ++ if (ltmp) { ++ latin1 = malloc((1+strlen(ltmp))*sizeof(char)); ++ if (latin1) { ++ memcpy(latin1, ltmp, (1+strlen(ltmp))); ++ free(ltmp); ++ return release(latin1); ++ } ++ free(ltmp); ++ } ++ } ++ + latin1 = malloc(id3_ucs4_latin1size(ucs4) * sizeof(*latin1)); + if (latin1) + id3_latin1_encode(latin1, ucs4); diff --git a/patches/libtranslate/README.txt b/patches/libtranslate/README.txt new file mode 100644 index 0000000..e152812 --- /dev/null +++ b/patches/libtranslate/README.txt @@ -0,0 +1,5 @@ +Apply the patches in the order they listed. Use patches from 'soup22' directory +to build against libsoup versions before 2.4, otherwise use patches from +'soup24' (tested up to 2.8). + +Replace data/services.xml.in by provided services.xml with updated services. diff --git a/patches/libtranslate/libtranslate-ds2-memory.patch b/patches/libtranslate/libtranslate-ds2-memory.patch new file mode 100644 index 0000000..e05c7b4 --- /dev/null +++ b/patches/libtranslate/libtranslate-ds2-memory.patch @@ -0,0 +1,12 @@ +diff -dPNur libtranslate-0.99/src/translate-util.c libtranslate-0.99-new/src/translate-util.c +--- libtranslate-0.99/src/translate-util.c 2005-01-17 16:45:45.000000000 +0000 ++++ libtranslate-0.99-new/src/translate-util.c 2005-12-29 18:35:04.000000000 +0000 +@@ -136,7 +136,7 @@ + g_return_val_if_fail(big != NULL, NULL); + g_return_val_if_fail(little != NULL, NULL); + +- lower_big = g_ascii_strdown(big, big_len); ++ lower_big = g_ascii_strdown(big, (int)big_len); + lower_little = g_ascii_strdown(little, -1); + + s = strstr(lower_big, lower_little); diff --git a/patches/libtranslate/libtranslate-ds3-charsetparse.patch b/patches/libtranslate/libtranslate-ds3-charsetparse.patch new file mode 100644 index 0000000..2f578e9 --- /dev/null +++ b/patches/libtranslate/libtranslate-ds3-charsetparse.patch @@ -0,0 +1,47 @@ +--- libtranslate-0.99/src/modules/translate-generic-service.c.orig Mon Apr 11 23:08:47 2005 ++++ libtranslate-0.99/src/modules/translate-generic-service.c Mon Apr 11 23:15:54 2005 +@@ -484,7 +484,7 @@ + + if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + { +- const char *charset = NULL; ++ char *charset = NULL; + + if (flags & TRANSFER_CONVERT) + { +@@ -493,14 +493,31 @@ + content_type = translate_generic_service_get_header(message, &info, "Content-Type"); + if (content_type) + { +- charset = translate_ascii_strcasestr(content_type, "charset="); +- if (charset) +- charset += 8; ++ const char *tmp; ++ ++ tmp = translate_ascii_strcasestr(content_type, "charset="); ++ if (tmp) ++ { ++ int len; ++ ++ tmp += 8; ++ if (*tmp == '\'' || *tmp == '"') ++ tmp++; ++ ++ len = strlen(tmp); ++ if (len > 0 && (tmp[len - 1] == '\'' || tmp[len - 1] == '"')) ++ len--; ++ ++ charset = g_strndup(tmp, len); ++ } + } + } + + if (charset) +- response = g_convert(message->response.body, message->response.length, "UTF-8", charset, NULL, NULL, err); ++ { ++ response = g_convert(message->response.body, message->response.length, "UTF-8", charset, NULL, NULL, err); ++ g_free(charset); ++ } + else + { + if ((flags & TRANSFER_CONVERT) && ! g_utf8_validate(message->response.body, message->response.length, NULL)) diff --git a/patches/libtranslate/libtranslate-ds4-condfix.patch b/patches/libtranslate/libtranslate-ds4-condfix.patch new file mode 100644 index 0000000..9915a80 --- /dev/null +++ b/patches/libtranslate/libtranslate-ds4-condfix.patch @@ -0,0 +1,38 @@ +--- libtranslate-0.99/src/translate-session.c.orig Mon Apr 11 22:44:53 2005 ++++ libtranslate-0.99/src/translate-session.c Mon Apr 11 22:51:48 2005 +@@ -703,7 +703,14 @@ + GError *tmp_err = NULL; + + g_mutex_lock(info->mutex); +- ret = info->err != NULL; ++ if (info->err) ++ { ++ ret = TRUE; ++ if (info->progress_cond) ++ g_cond_signal(info->progress_cond); ++ } ++ else ++ ret = FALSE; + g_mutex_unlock(info->mutex); + + if (ret) +@@ -728,6 +735,9 @@ + else + g_propagate_error(&info->err, tmp_err); + ++ if (info->progress_cond) ++ g_cond_signal(info->progress_cond); ++ + g_mutex_unlock(info->mutex); + + return; +@@ -759,6 +769,9 @@ + info->err = g_error_new(TRANSLATE_SESSION_ERROR, + TRANSLATE_SESSION_ERROR_NO_SERVICE, + _("no service could translate chunk")); ++ ++ if (info->progress_cond) ++ g_cond_signal(info->progress_cond); + } + + g_mutex_unlock(info->mutex); diff --git a/patches/libtranslate/libtranslate-ds5-empty.patch b/patches/libtranslate/libtranslate-ds5-empty.patch new file mode 100644 index 0000000..eb2e0ce --- /dev/null +++ b/patches/libtranslate/libtranslate-ds5-empty.patch @@ -0,0 +1,17 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2007-06-27 17:26:10.000000000 +0200 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2007-06-27 17:23:55.000000000 +0200 +@@ -1042,6 +1042,13 @@ + + g_free(response); + } ++ ++ if ((!answer)&&(!*err)) { ++ g_set_error(err, ++ TRANSLATE_GENERIC_SERVICE_ERROR, ++ TRANSLATE_GENERIC_SERVICE_ERROR_PARSE, ++ _("empty server response")); ++ } + + return answer ? g_string_free(answer, FALSE) : NULL; + } diff --git a/patches/libtranslate/libtranslate-ds6-promt.patch b/patches/libtranslate/libtranslate-ds6-promt.patch new file mode 100644 index 0000000..6b30145 --- /dev/null +++ b/patches/libtranslate/libtranslate-ds6-promt.patch @@ -0,0 +1,27 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2007-06-27 17:26:10.000000000 +0200 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2007-06-27 17:23:55.000000000 +0200 +@@ -1238,7 +1245,22 @@ + { + if (modifier_value) + g_warning(_("%s: value specified for \"escape\" modifier"), warning_prefix); +- modified = soup_uri_encode(value, NULL); ++ modified = soup_uri_encode(value, "&"); ++ } ++ else if (! strcmp(modifier_name, "entities")) ++ { ++ int i; ++ char *ptr; ++ ++ modified = g_malloc(strlen(value)*6 + 1); ++ for (i=0,ptr=modified;value[i];i++) { ++ if ((unsigned char)(value[i])<160) *(ptr++)=value[i]; ++ else { ++ sprintf(ptr, "&#%u;", (unsigned char)(value[i])); ++ ptr+=6; ++ } ++ } ++ *ptr = 0; + } + else if (! strcmp(modifier_name, "charset")) + { diff --git a/patches/libtranslate/libtranslate-ds7-fixcharset.patch b/patches/libtranslate/libtranslate-ds7-fixcharset.patch new file mode 100644 index 0000000..0665d2f --- /dev/null +++ b/patches/libtranslate/libtranslate-ds7-fixcharset.patch @@ -0,0 +1,93 @@ +diff -dPNur libtranslate-0.99-new/src/modules/translate-generic-parser.c libtranslate-0.99-new-uk/src/modules/translate-generic-parser.c +--- libtranslate-0.99-new/src/modules/translate-generic-parser.c 2005-01-17 17:46:24.000000000 +0100 ++++ libtranslate-0.99-new-uk/src/modules/translate-generic-parser.c 2007-06-27 22:40:04.000000000 +0200 +@@ -726,6 +726,7 @@ + { + const char *url; + const char *post; ++ const char *charset; + const char *content_type; + + g_return_if_fail(info != NULL); +@@ -740,6 +741,7 @@ + "url", REQUIRED, &url, + "post", OPTIONAL, &post, + "content-type", OPTIONAL, &content_type, ++ "response-charset", OPTIONAL, &charset, + NULL); + + if (! *err) +@@ -748,6 +750,7 @@ + (*location)->url = g_strdup(url); + (*location)->post = g_strdup(post); + (*location)->content_type = g_strdup(content_type ? content_type : "application/x-www-form-urlencoded"); ++ (*location)->response_charset = g_strdup(charset); + } + } + +@@ -759,6 +762,7 @@ + g_free(location->url); + g_free(location->post); + g_free(location->content_type); ++ g_free(location->response_charset); + g_slist_foreach(location->http_headers, (GFunc) translate_generic_http_header_free, NULL); + g_slist_free(location->http_headers); + g_free(location); +diff -dPNur libtranslate-0.99-new/src/modules/translate-generic-parser.h libtranslate-0.99-new-uk/src/modules/translate-generic-parser.h +--- libtranslate-0.99-new/src/modules/translate-generic-parser.h 2005-01-17 17:46:30.000000000 +0100 ++++ libtranslate-0.99-new-uk/src/modules/translate-generic-parser.h 2007-06-27 22:34:13.000000000 +0200 +@@ -51,6 +51,7 @@ + char *url; + char *post; + char *content_type; ++ char *response_charset; + GSList *http_headers; + } TranslateGenericLocation; + +diff -dPNur libtranslate-0.99-new/src/modules/translate-generic-service.c libtranslate-0.99-new-uk/src/modules/translate-generic-service.c +--- libtranslate-0.99-new/src/modules/translate-generic-service.c 2007-06-27 17:23:55.000000000 +0200 ++++ libtranslate-0.99-new-uk/src/modules/translate-generic-service.c 2007-06-27 22:40:29.000000000 +0200 +@@ -129,6 +129,7 @@ + static char *translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, ++ const char *response_charset, + const GSList *headers, + TransferFlags flags, + GTimeVal *deadline, +@@ -407,6 +408,7 @@ + translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, ++ const char *response_charset, + const GSList *headers, + TransferFlags flags, + GTimeVal *deadline, +@@ -550,9 +552,9 @@ + } + } + +- if (charset) ++ if ((charset)||(response_charset)) + { +- response = g_convert(message->response.body, message->response.length, "UTF-8", charset, NULL, NULL, err); ++ response = g_convert(message->response.body, message->response.length, "UTF-8", response_charset?response_charset:charset, NULL, NULL, err); + g_free(charset); + } + else +@@ -941,6 +943,7 @@ + response = translate_generic_service_get(url, + post, + group->text_location->content_type, ++ group->text_location->response_charset, + headers, + TRANSFER_FOLLOW_REFRESH | TRANSFER_CONVERT, + deadline, +@@ -1339,6 +1342,7 @@ + response = translate_generic_service_get(translation_url, + post, + group->web_page_location->content_type, ++ group->web_page_location->response_charset, + headers, + 0, + NULL, diff --git a/patches/libtranslate/services.xml b/patches/libtranslate/services.xml new file mode 100644 index 0000000..14d0548 --- /dev/null +++ b/patches/libtranslate/services.xml @@ -0,0 +1,258 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE services SYSTEM "services.dtd"> +<services> + <custom-language tag="zh-TW" name="Chinese (Taiwan)"/> + + <service nick="Google" name="google"> + <group> + <language to="*" tag="en"/> + <language to="en,de" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en" tag="it"/> + <language to="en" tag="pt"/> + <language to="en" tag="es"/> + <language to="en" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en" tag="ar"/> + <text-translation url="http://www.google.com/translate_t?text=${text:escape}&langpair=${from}|${to}&ie=utf8&oe=utf8"> + <pre-marker text="id=result_box"/> + <pre-marker text="mouseover"/> + <pre-marker text=">"/> + <post-marker text="<br>"/> + </text-translation> + <web-page-translation url="http://www.google.com/translate_c?u=${url:escape}&langpair=${from}|${to}"/> + </group> + </service> + + <service nick="FreeTranslation" name="freetranslation" max-chunk-len="600"> + <group> + <language to="en" tag="nl" service-tag="dutch"/> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="fr" service-tag="french"/> + <language to="en" tag="de" service-tag="german"/> + <language to="en" tag="it" service-tag="italian"/> + <language tag="no" service-tag="norwegian"/> + <language to="en" tag="pt" service-tag="portuguese"/> + <language to="en" tag="es" service-tag="spanish"/> + <text-translation url="http://ets.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + <web-page-translation url="http://fets5.freetranslation.com/?sequence=core&url=${url:escape}&language=${from}/${to}"/> + </group> + <group> + <language tag="zh" service-tag="simplifiedchinese"/> + <language tag="zh-TW" service-tag="traditionalchinese"/> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="ru" service-tag="russian"/> + <text-translation url="http://ets6.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + </group> + <group> + <language to="*" tag="en" service-tag="english"/> + <language to="en" tag="ja" service-tag="japanese"/> + <text-translation url="http://tets9.freetranslation.com/?sequence=core&srctext=${text:escape}&language=${from}/${to}&charset=utf-8"/> + </group> + </service> + + <service nick="Pereklad" name="pereklad"> + <group> + <language to="*" tag="ru" service-tag="Rus"/> + <language to="*" tag="uk" service-tag="Ukr"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="*" tag="en" service-tag="Eng"/> + <language to="*" tag="de" service-tag="Ger"/> + <language to="*" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="en,de,fr" tag="ru" service-tag="Rus"/> + <language to="en,de,fr" tag="uk" service-tag="Ukr"/> + <language to="" tag="en" service-tag="Eng"/> + <language to="" tag="de" service-tag="Ger"/> + <language to="" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="ru" service-tag="Rus"/> + <language to="" tag="uk" service-tag="Ukr"/> + <language to="ru,uk" tag="en" service-tag="Eng"/> + <language to="ru,uk" tag="de" service-tag="Ger"/> + <language to="ru,uk" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="ru" service-tag="Rus"/> + <language to="" tag="uk" service-tag="Ukr"/> + <language to="ru,uk" tag="lv" service-tag="Lat"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="*" tag="lv" service-tag="Lat"/> + <language to="" tag="en" service-tag="Eng"/> + <language to="" tag="de" service-tag="Ger"/> + <language to="" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-1"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="lv" service-tag="Lat"/> + <language to="lv" tag="ru" service-tag="Rus"/> + <language to="lv" tag="uk" service-tag="Ukr"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-4"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + <group> + <language to="" tag="lv" service-tag="Lat"/> + <language to="lv" tag="en" service-tag="Eng"/> + <language to="lv" tag="de" service-tag="Ger"/> + <language to="lv" tag="fr" service-tag="Fra"/> + <text-translation + url="http://pereklad.online.ua/" + post="TranFrom=${from}&TranTo=${to}&SrcTxt=${text:escape}" + response-charset="ISO-8859-4"> + <pre-marker text="id="DstTxt""/> + <pre-marker text=">"/> + <post-marker text="</textarea>"/> + </text-translation> + </group> + </service> + + <service nick="Promt" name="promt"> + <group> + <language to="*" tag="ru" service-tag="r"/> + <language to="ru,de,fr,es" tag="en" service-tag="e"/> + <language to="ru,en,fr,es" tag="de" service-tag="g"/> + <language to="ru,en,de,es" tag="fr" service-tag="f"/> + <language to="ru,en" tag="it" service-tag="i"/> + <language to="ru,en,de,fr" tag="es" service-tag="s"/> + <language to="en" tag="pt" service-tag="p"/> + <text-translation + url="http://www.translate.ru/Default.aspx/Text" + post="__EVENTTARGET=&__EVENTTARGUMENT=&ctl00$SiteContent$MA_trasnlform$bTranslate=Translate&ctl00$SiteContent$MA_trasnlform$DropDownList2=&ctl00$SiteContent$trasnlform$sLang=${from}&ctl00$SiteContent$MA_trasnlform$rLang=${to}&ctl00$SiteContent$MA_trasnlform$sourceText=${text:escape}&ctl00$SiteContent$MA_trasnlform$rblTemplates=General"> + <pre-marker text="ctl00$SiteContent$MA_trasnlform$tbPismo"/> + <pre-marker text=">"/> + <post-marker text="</textarea"/> + + </text-translation> + </group> + </service> + + <service nick="SYSTRAN" name="systran"> + <group> + <language to="en" tag="ar"/> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW" service-tag="zt"/> + <language to="en,fr" tag="nl"/> + <language to="*" tag="en"/> + <language to="nl,en,de,it,pt,es" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en,fr" tag="it"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en,fr" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en,fr" tag="es"/> + <language to="en" tag="sv"/> + <http-header value="http://www.systransoft.com/" name="Referer"/> + <text-translation + url="http://www.systranet.com/tt?lp=${from}_${to}&service=translate" + post=". ${text}."> + <pre-marker text=". "/> + <post-marker text="."/> + </text-translation> + </group> + </service> + + <service nick="Babel Fish" name="babelfish"> + <group> + <language to="en" tag="zh"/> + <language to="en" tag="zh-TW" service-tag="zt"/> + <language to="*" tag="en"/> + <language to="en,fr" tag="nl"/> + <language to="en,de,el,it,pt,nl,es" tag="fr"/> + <language to="en,fr" tag="de"/> + <language to="en,fr" tag="el"/> + <language to="en,fr" tag="it"/> + <language to="en" tag="ja"/> + <language to="en" tag="ko"/> + <language to="en,fr" tag="pt"/> + <language to="en" tag="ru"/> + <language to="en,fr" tag="es"/> + <text-translation + url="http://babelfish.yahoo.com/translate_txt" + post="trtext=${text:escape}&lp=${from}_${to}&ei=UTF-8"> + <pre-marker text="id="result""/> + <pre-marker text="<div"/> + <pre-marker text=">"/> + <post-marker text="</div"/> + </text-translation> +<!-- + <web-page-translation url="http://babelfish.altavista.com/babelfish/trurl_load?url=${url:escape}&lp=${from}_${to}&enc=utf8"/> +!--> + </group> + </service> + +<!-- + <service nick="Kataku" name="kataku"> + <group> + <language to="*" tag="en"/> + <language to="*" tag="id" service-tag="in"/> + <text-translation url="http://www.toggletext.com/kataku_trial.php" post="input_text=${text:charset=ISO8859-1,escape}&langset_text=${from}_${to}"> + <pre-marker text="Translation:"/> + <pre-marker text="<pre"/> + <pre-marker text=">"/> + <post-marker text=" </pre>"/> + </text-translation> + <web-page-translation url="http://www.toggletext.com/kataku_webpage_translate.php?input=${url:escape}&langset=${from}_${to}"/> + </group> + </service> +--> + +</services>
\ No newline at end of file diff --git a/patches/libtranslate/soup22/libtranslate-ds1-timed.patch b/patches/libtranslate/soup22/libtranslate-ds1-timed.patch new file mode 100644 index 0000000..c98868a --- /dev/null +++ b/patches/libtranslate/soup22/libtranslate-ds1-timed.patch @@ -0,0 +1,352 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2005-01-17 17:46:38.000000000 +0100 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2005-07-27 22:13:33.000000000 +0200 +@@ -131,6 +131,7 @@ + const char *post_content_type, + const GSList *headers, + TransferFlags flags, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); +@@ -181,6 +182,15 @@ + gpointer user_data, + GError **err); + ++static char *translate_generic_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); ++ + char *translate_generic_service_expand (const char *warning_prefix, + const char *str, + ...); +@@ -248,6 +258,7 @@ + + service_class->get_pairs = translate_generic_service_get_pairs; + service_class->translate_text = translate_generic_service_translate_text; ++ service_class->timed_translate_text = translate_generic_service_timed_translate_text; + service_class->translate_web_page = translate_generic_service_translate_web_page; + + g_object_class_install_property(object_class, +@@ -387,12 +398,18 @@ + return TRUE; /* continue */ + } + ++static void send_message_cb(SoupMessage *req, gpointer user_data) { ++ g_object_ref(req); ++ *(gboolean*)user_data = TRUE; ++} ++ + static char * + translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, + const GSList *headers, + TransferFlags flags, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -400,6 +417,8 @@ + TransferInfo info; + SoupMessage *message; + const GSList *l; ++ GTimeVal tv; ++ gboolean completed = 0, canceled = 0; + char *response = NULL; + + g_return_val_if_fail(uri != NULL, FALSE); +@@ -479,9 +498,27 @@ + if (translate_generic_debug_flags & TRANSLATE_GENERIC_DEBUG_LOG_TRANSFERS) + translate_generic_service_log_connect(message); + ++ if (deadline) { ++ soup_session_queue_message(info.session, message, send_message_cb, &completed); ++ ++ do { ++ g_main_iteration (FALSE); ++ if (completed) break; ++ ++ g_get_current_time(&tv); ++ } while ((tv.tv_sec < deadline->tv_sec)||((tv.tv_sec == deadline->tv_sec)&&(tv.tv_usec < deadline->tv_usec))); ++ ++ if (!completed) { ++ soup_session_cancel_message(info.session, message); ++ canceled = 1; ++ } ++ } else + soup_session_send_message(info.session, message); + g_object_unref(info.session); + ++ if (canceled) ++ g_set_error(err, TRANSLATE_ERROR, TRANSLATE_ERROR_CANCELLED, _("Timeout")); ++ else + if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + { + const char *charset = NULL; +@@ -833,10 +870,11 @@ + } + + static char * +-translate_generic_service_translate_text (TranslateService *service, ++translate_generic_service_timed_translate_text (TranslateService *service, + const char *text, + const char *from, + const char *to, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -882,16 +920,16 @@ + + headers = g_slist_copy(group->http_headers); + headers = g_slist_concat(headers, g_slist_copy(group->text_location->http_headers)); +- ++ + response = translate_generic_service_get(url, + post, + group->text_location->content_type, + headers, + TRANSFER_FOLLOW_REFRESH | TRANSFER_CONVERT, ++ deadline, + progress_func, + user_data, + err); +- + g_free(url); + g_free(post); + g_slist_free(headers); +@@ -991,6 +1029,18 @@ + return answer ? g_string_free(answer, FALSE) : NULL; + } + ++static char * ++translate_generic_service_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ return translate_generic_service_timed_translate_text(service, text, from, to, NULL, progress_func, user_data, err); ++} ++ + char * + translate_generic_service_expand (const char *warning_prefix, + const char *str, +@@ -1252,6 +1302,7 @@ + group->web_page_location->content_type, + headers, + 0, ++ NULL, + progress_func, + user_data, + err); +@@ -1311,7 +1362,7 @@ + g_free(proxy_text_uri); + } + +- session = soup_session_sync_new_with_options(SOUP_SESSION_PROXY_URI, proxy_uri, NULL); ++ session = soup_session_async_new_with_options(SOUP_SESSION_PROXY_URI, proxy_uri, NULL); + + if (proxy_uri) + soup_uri_free(proxy_uri); +diff -dPNur libtranslate-0.99/src/translate-service.c libtranslate-0.99-new/src/translate-service.c +--- libtranslate-0.99/src/translate-service.c 2005-01-17 17:45:23.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service.c 2005-07-27 17:18:07.000000000 +0200 +@@ -372,6 +372,28 @@ + } + + char * ++translate_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ g_return_val_if_fail(TRANSLATE_IS_SERVICE(service), NULL); ++ g_return_val_if_fail(TRANSLATE_SERVICE_GET_CLASS(service)->translate_text != NULL, NULL); ++ g_return_val_if_fail(text != NULL, NULL); ++ g_return_val_if_fail(from != NULL, NULL); ++ g_return_val_if_fail(to != NULL, NULL); ++ ++ if (TRANSLATE_SERVICE_GET_CLASS(service)->timed_translate_text) ++ return TRANSLATE_SERVICE_GET_CLASS(service)->timed_translate_text(service, text, from, to, deadline, progress_func, user_data, err); ++ ++ return TRANSLATE_SERVICE_GET_CLASS(service)->translate_text(service, text, from, to, progress_func, user_data, err); ++} ++ ++char * + translate_service_translate_web_page (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-service.h libtranslate-0.99-new/src/translate-service.h +--- libtranslate-0.99/src/translate-service.h 2005-01-17 17:45:29.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service.h 2005-07-27 16:54:46.000000000 +0200 +@@ -73,6 +73,14 @@ + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); ++ char *(*timed_translate_text)(TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *(*translate_web_page) (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-service-private.h libtranslate-0.99-new/src/translate-service-private.h +--- libtranslate-0.99/src/translate-service-private.h 2005-01-17 17:45:17.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service-private.h 2005-07-27 17:30:00.000000000 +0200 +@@ -41,6 +41,14 @@ + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); ++char *translate_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *translate_service_translate_web_page (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-session.c libtranslate-0.99-new/src/translate-session.c +--- libtranslate-0.99/src/translate-session.c 2005-01-17 17:45:35.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-session.c 2005-07-27 16:52:46.000000000 +0200 +@@ -62,6 +62,8 @@ + { + GMutex *mutex; + GCond *progress_cond; ++ ++ GTimeVal *deadline; + + TranslateSession *session; + GSList *services; +@@ -487,6 +489,7 @@ + * @text: a nul-terminated string. + * @from: a RFC 3066 language tag. + * @to: a RFC 3066 language tag. ++ * @timeout: timeout in microseconds. + * @progress_func: a function to call when progressing, or %NULL. + * @user_data: data to pass to @progress_func, or %NULL. + * @err: a location to report errors, or %NULL. Any of the errors in +@@ -505,10 +508,11 @@ + * when no longer needed. + **/ + char * +-translate_session_translate_text (TranslateSession *session, ++translate_session_timed_translate_text (TranslateSession *session, + const char *text, + const char *from, + const char *to, ++ gulong timeout, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -519,6 +523,7 @@ + unsigned int max_threads; + GThreadPool *pool; + GSList *l; ++ GTimeVal deadline; + unsigned int max_chunk_len = 0; + char *translated = NULL; + +@@ -527,6 +532,11 @@ + g_return_val_if_fail(from != NULL, NULL); + g_return_val_if_fail(to != NULL, NULL); + ++ if (timeout) { ++ g_get_current_time(&deadline); ++ g_time_val_add(&deadline, timeout); ++ } ++ + LOCK(session); + info.services = translate_session_get_services_for_translation(session, + TRANSLATE_PAIR_TEXT, +@@ -560,7 +570,8 @@ + chunks = translate_session_split(text, max_chunk_len); + + info.mutex = g_mutex_new(); +- info.progress_cond = progress_func ? g_cond_new() : NULL; ++ info.progress_cond = (progress_func||timeout) ? g_cond_new() : NULL; ++ info.deadline = timeout ? &deadline : NULL; + info.session = session; + info.chunks = NULL; + info.from = from; +@@ -614,6 +625,11 @@ + GSList *l; + int n_chunks; + ++ if (timeout) { ++ if (!g_cond_timed_wait(info.progress_cond, info.mutex, info.deadline)) ++ info.err = g_error_new(TRANSLATE_ERROR,TRANSLATE_ERROR_CANCELLED,_("timeout")); ++ break; ++ } else + g_cond_wait(info.progress_cond, info.mutex); + + if (info.err) +@@ -680,6 +696,18 @@ + return translated; + } + ++char * ++translate_session_translate_text (TranslateSession *session, ++ const char *text, ++ const char *from, ++ const char *to, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ return translate_session_timed_translate_text(session, text, from, to, 0, progress_func, user_data, err); ++} ++ + static void + translate_session_translate_thread (gpointer data, gpointer user_data) + { +@@ -709,10 +737,11 @@ + if (ret) + return; + +- chunk_info->translated = translate_service_translate_text(service, ++ chunk_info->translated = translate_service_timed_translate_text(service, + chunk_info->chunk, + info->from, + info->to, ++ info->deadline, + info->progress_cond ? translate_session_translate_progress_cb : NULL, + info->progress_cond ? chunk_info : NULL, + &tmp_err); +diff -dPNur libtranslate-0.99/src/translate-session.h libtranslate-0.99-new/src/translate-session.h +--- libtranslate-0.99/src/translate-session.h 2005-01-17 17:45:40.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-session.h 2005-07-27 14:41:05.000000000 +0200 +@@ -93,6 +93,14 @@ + unsigned int translate_session_get_max_threads (TranslateSession *session); + int translate_session_get_max_retries (TranslateSession *session); + ++char *translate_session_timed_translate_text (TranslateSession *session, ++ const char *text, ++ const char *from, ++ const char *to, ++ gulong timeout, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *translate_session_translate_text (TranslateSession *session, + const char *text, + const char *from, diff --git a/patches/libtranslate/soup24/libtranslate-ds1-timed24.patch b/patches/libtranslate/soup24/libtranslate-ds1-timed24.patch new file mode 100644 index 0000000..daf3811 --- /dev/null +++ b/patches/libtranslate/soup24/libtranslate-ds1-timed24.patch @@ -0,0 +1,360 @@ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-new/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2005-01-17 17:46:38.000000000 +0100 ++++ libtranslate-0.99-new/src/modules/translate-generic-service.c 2005-07-27 22:13:33.000000000 +0200 +@@ -131,6 +131,7 @@ + const char *post_content_type, + const GSList *headers, + TransferFlags flags, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); +@@ -181,6 +182,15 @@ + gpointer user_data, + GError **err); + ++static char *translate_generic_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); ++ + char *translate_generic_service_expand (const char *warning_prefix, + const char *str, + ...); +@@ -248,6 +258,7 @@ + + service_class->get_pairs = translate_generic_service_get_pairs; + service_class->translate_text = translate_generic_service_translate_text; ++ service_class->timed_translate_text = translate_generic_service_timed_translate_text; + service_class->translate_web_page = translate_generic_service_translate_web_page; + + g_object_class_install_property(object_class, +@@ -387,12 +398,22 @@ + return TRUE; /* continue */ + } + ++#ifdef HAVE_LIBSOUP22 ++static void send_message_cb(SoupMessage *req, gpointer user_data) { ++#else ++static void send_message_cb(SoupSession *session, SoupMessage *req, gpointer user_data) { ++#endif ++ g_object_ref(req); ++ *(gboolean*)user_data = TRUE; ++} ++ + static char * + translate_generic_service_get (const char *uri, + const char *post, + const char *post_content_type, + const GSList *headers, + TransferFlags flags, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -400,6 +417,8 @@ + TransferInfo info; + SoupMessage *message; + const GSList *l; ++ GTimeVal tv; ++ gboolean completed = 0, canceled = 0; + char *response = NULL; + + g_return_val_if_fail(uri != NULL, FALSE); +@@ -479,9 +498,31 @@ + if (translate_generic_debug_flags & TRANSLATE_GENERIC_DEBUG_LOG_TRANSFERS) + translate_generic_service_log_connect(message); + ++ if (deadline) { ++ soup_session_queue_message(info.session, message, send_message_cb, &completed); ++ ++ do { ++ g_main_iteration (FALSE); ++ if (completed) break; ++ ++ g_get_current_time(&tv); ++ } while ((tv.tv_sec < deadline->tv_sec)||((tv.tv_sec == deadline->tv_sec)&&(tv.tv_usec < deadline->tv_usec))); ++ ++ if (!completed) { ++#ifdef HAVE_LIBSOUP22 ++ soup_session_cancel_message(info.session, message); ++#else ++ soup_session_cancel_message(info.session, message, SOUP_STATUS_CANCELLED); ++#endif ++ canceled = 1; ++ } ++ } else + soup_session_send_message(info.session, message); + g_object_unref(info.session); + ++ if (canceled) ++ g_set_error(err, TRANSLATE_ERROR, TRANSLATE_ERROR_CANCELLED, _("Timeout")); ++ else + if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + { + const char *charset = NULL; +@@ -833,10 +870,11 @@ + } + + static char * +-translate_generic_service_translate_text (TranslateService *service, ++translate_generic_service_timed_translate_text (TranslateService *service, + const char *text, + const char *from, + const char *to, ++ GTimeVal *deadline, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -882,16 +920,16 @@ + + headers = g_slist_copy(group->http_headers); + headers = g_slist_concat(headers, g_slist_copy(group->text_location->http_headers)); +- ++ + response = translate_generic_service_get(url, + post, + group->text_location->content_type, + headers, + TRANSFER_FOLLOW_REFRESH | TRANSFER_CONVERT, ++ deadline, + progress_func, + user_data, + err); +- + g_free(url); + g_free(post); + g_slist_free(headers); +@@ -991,6 +1029,18 @@ + return answer ? g_string_free(answer, FALSE) : NULL; + } + ++static char * ++translate_generic_service_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ return translate_generic_service_timed_translate_text(service, text, from, to, NULL, progress_func, user_data, err); ++} ++ + char * + translate_generic_service_expand (const char *warning_prefix, + const char *str, +@@ -1252,6 +1302,7 @@ + group->web_page_location->content_type, + headers, + 0, ++ NULL, + progress_func, + user_data, + err); +@@ -1311,7 +1362,7 @@ + g_free(proxy_text_uri); + } + +- session = soup_session_sync_new_with_options(SOUP_SESSION_PROXY_URI, proxy_uri, NULL); ++ session = soup_session_async_new_with_options(SOUP_SESSION_PROXY_URI, proxy_uri, NULL); + + if (proxy_uri) + soup_uri_free(proxy_uri); +diff -dPNur libtranslate-0.99/src/translate-service.c libtranslate-0.99-new/src/translate-service.c +--- libtranslate-0.99/src/translate-service.c 2005-01-17 17:45:23.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service.c 2005-07-27 17:18:07.000000000 +0200 +@@ -372,6 +372,28 @@ + } + + char * ++translate_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ g_return_val_if_fail(TRANSLATE_IS_SERVICE(service), NULL); ++ g_return_val_if_fail(TRANSLATE_SERVICE_GET_CLASS(service)->translate_text != NULL, NULL); ++ g_return_val_if_fail(text != NULL, NULL); ++ g_return_val_if_fail(from != NULL, NULL); ++ g_return_val_if_fail(to != NULL, NULL); ++ ++ if (TRANSLATE_SERVICE_GET_CLASS(service)->timed_translate_text) ++ return TRANSLATE_SERVICE_GET_CLASS(service)->timed_translate_text(service, text, from, to, deadline, progress_func, user_data, err); ++ ++ return TRANSLATE_SERVICE_GET_CLASS(service)->translate_text(service, text, from, to, progress_func, user_data, err); ++} ++ ++char * + translate_service_translate_web_page (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-service.h libtranslate-0.99-new/src/translate-service.h +--- libtranslate-0.99/src/translate-service.h 2005-01-17 17:45:29.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service.h 2005-07-27 16:54:46.000000000 +0200 +@@ -73,6 +73,14 @@ + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); ++ char *(*timed_translate_text)(TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *(*translate_web_page) (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-service-private.h libtranslate-0.99-new/src/translate-service-private.h +--- libtranslate-0.99/src/translate-service-private.h 2005-01-17 17:45:17.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-service-private.h 2005-07-27 17:30:00.000000000 +0200 +@@ -41,6 +41,14 @@ + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err); ++char *translate_service_timed_translate_text (TranslateService *service, ++ const char *text, ++ const char *from, ++ const char *to, ++ GTimeVal *deadline, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *translate_service_translate_web_page (TranslateService *service, + const char *url, + const char *from, +diff -dPNur libtranslate-0.99/src/translate-session.c libtranslate-0.99-new/src/translate-session.c +--- libtranslate-0.99/src/translate-session.c 2005-01-17 17:45:35.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-session.c 2005-07-27 16:52:46.000000000 +0200 +@@ -62,6 +62,8 @@ + { + GMutex *mutex; + GCond *progress_cond; ++ ++ GTimeVal *deadline; + + TranslateSession *session; + GSList *services; +@@ -487,6 +489,7 @@ + * @text: a nul-terminated string. + * @from: a RFC 3066 language tag. + * @to: a RFC 3066 language tag. ++ * @timeout: timeout in microseconds. + * @progress_func: a function to call when progressing, or %NULL. + * @user_data: data to pass to @progress_func, or %NULL. + * @err: a location to report errors, or %NULL. Any of the errors in +@@ -505,10 +508,11 @@ + * when no longer needed. + **/ + char * +-translate_session_translate_text (TranslateSession *session, ++translate_session_timed_translate_text (TranslateSession *session, + const char *text, + const char *from, + const char *to, ++ gulong timeout, + TranslateProgressFunc progress_func, + gpointer user_data, + GError **err) +@@ -519,6 +523,7 @@ + unsigned int max_threads; + GThreadPool *pool; + GSList *l; ++ GTimeVal deadline; + unsigned int max_chunk_len = 0; + char *translated = NULL; + +@@ -527,6 +532,11 @@ + g_return_val_if_fail(from != NULL, NULL); + g_return_val_if_fail(to != NULL, NULL); + ++ if (timeout) { ++ g_get_current_time(&deadline); ++ g_time_val_add(&deadline, timeout); ++ } ++ + LOCK(session); + info.services = translate_session_get_services_for_translation(session, + TRANSLATE_PAIR_TEXT, +@@ -560,7 +570,8 @@ + chunks = translate_session_split(text, max_chunk_len); + + info.mutex = g_mutex_new(); +- info.progress_cond = progress_func ? g_cond_new() : NULL; ++ info.progress_cond = (progress_func||timeout) ? g_cond_new() : NULL; ++ info.deadline = timeout ? &deadline : NULL; + info.session = session; + info.chunks = NULL; + info.from = from; +@@ -614,6 +625,11 @@ + GSList *l; + int n_chunks; + ++ if (timeout) { ++ if (!g_cond_timed_wait(info.progress_cond, info.mutex, info.deadline)) ++ info.err = g_error_new(TRANSLATE_ERROR,TRANSLATE_ERROR_CANCELLED,_("timeout")); ++ break; ++ } else + g_cond_wait(info.progress_cond, info.mutex); + + if (info.err) +@@ -680,6 +696,18 @@ + return translated; + } + ++char * ++translate_session_translate_text (TranslateSession *session, ++ const char *text, ++ const char *from, ++ const char *to, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err) ++{ ++ return translate_session_timed_translate_text(session, text, from, to, 0, progress_func, user_data, err); ++} ++ + static void + translate_session_translate_thread (gpointer data, gpointer user_data) + { +@@ -709,10 +737,11 @@ + if (ret) + return; + +- chunk_info->translated = translate_service_translate_text(service, ++ chunk_info->translated = translate_service_timed_translate_text(service, + chunk_info->chunk, + info->from, + info->to, ++ info->deadline, + info->progress_cond ? translate_session_translate_progress_cb : NULL, + info->progress_cond ? chunk_info : NULL, + &tmp_err); +diff -dPNur libtranslate-0.99/src/translate-session.h libtranslate-0.99-new/src/translate-session.h +--- libtranslate-0.99/src/translate-session.h 2005-01-17 17:45:40.000000000 +0100 ++++ libtranslate-0.99-new/src/translate-session.h 2005-07-27 14:41:05.000000000 +0200 +@@ -93,6 +93,14 @@ + unsigned int translate_session_get_max_threads (TranslateSession *session); + int translate_session_get_max_retries (TranslateSession *session); + ++char *translate_session_timed_translate_text (TranslateSession *session, ++ const char *text, ++ const char *from, ++ const char *to, ++ gulong timeout, ++ TranslateProgressFunc progress_func, ++ gpointer user_data, ++ GError **err); + char *translate_session_translate_text (TranslateSession *session, + const char *text, + const char *from, diff --git a/patches/libtranslate/soup24/libtranslate-ds8-soup24inc.patch b/patches/libtranslate/soup24/libtranslate-ds8-soup24inc.patch new file mode 100644 index 0000000..8de7c07 --- /dev/null +++ b/patches/libtranslate/soup24/libtranslate-ds8-soup24inc.patch @@ -0,0 +1,533 @@ +diff -dPNur libtranslate-0.99/config.h.in libtranslate-0.99-1/config.h.in +--- libtranslate-0.99/config.h.in 2005-01-17 18:06:58.000000000 +0100 ++++ libtranslate-0.99-1/config.h.in 2010-02-14 03:55:56.000000000 +0100 +@@ -24,6 +24,12 @@ + /* Define if your <locale.h> file defines LC_MESSAGES. */ + #undef HAVE_LC_MESSAGES + ++/* Building with libsoup 2.2 */ ++#undef HAVE_LIBSOUP22 ++ ++/* Building with libsoup 2.4 */ ++#undef HAVE_LIBSOUP24 ++ + /* Define to 1 if you have the <locale.h> header file. */ + #undef HAVE_LOCALE_H + +diff -dPNur libtranslate-0.99/configure.ac libtranslate-0.99-1/configure.ac +--- libtranslate-0.99/configure.ac 2005-01-15 17:24:12.000000000 +0100 ++++ libtranslate-0.99-1/configure.ac 2010-02-14 03:55:56.000000000 +0100 +@@ -50,7 +50,11 @@ + ### optional libraries + + if TRANSLATE_FEATURE_ENABLED(generic); then +- PKG_CHECK_MODULES(SOUP, [libsoup-2.2],, [TRANSLATE_FEATURE_DISABLE(generic, [libsoup not found])]) ++ PKG_CHECK_MODULES(SOUP, [libsoup-2.4], ++ [AC_DEFINE(HAVE_LIBSOUP24, 1, [Building with libsoup 2.4])], ++ [PKG_CHECK_MODULES(SOUP, [libsoup-2.2], ++ [AC_DEFINE(HAVE_LIBSOUP22, 1, [Building with libsoup 2.2])], ++ [TRANSLATE_FEATURE_DISABLE(generic, [libsoup not found])])]) + fi + if TRANSLATE_FEATURE_ENABLED(generic); then + PKG_CHECK_MODULES(LIBXML, [libxml-2.0],, [TRANSLATE_FEATURE_DISABLE(generic, [libxml not found])]) +diff -dPNur libtranslate-0.99/src/modules/translate-generic-service.c libtranslate-0.99-1/src/modules/translate-generic-service.c +--- libtranslate-0.99/src/modules/translate-generic-service.c 2010-02-14 03:55:34.000000000 +0100 ++++ libtranslate-0.99-1/src/modules/translate-generic-service.c 2010-02-14 04:04:56.000000000 +0100 +@@ -35,7 +35,9 @@ + #include <stdlib.h> + #include <glib/gi18n-lib.h> + #include <libsoup/soup.h> ++#ifdef HAVE_LIBSOUP22 + #include <libsoup/soup-message-filter.h> ++#endif + #include <libxml/HTMLparser.h> + #include "translate.h" + #include "translate-generic-service.h" +@@ -43,6 +45,17 @@ + #include "translate-generic-parser.h" + #include "translate-generic-soup-cookie-jar.h" + ++#ifdef HAVE_LIBSOUP22 ++#define soup_message_headers_get soup_message_get_header ++#define soup_message_headers_append soup_message_add_header ++#define SoupURI SoupUri ++#define SOUP_MESSAGE_RESPONSE_BODY(msg) ((msg)->response.body) ++#define SOUP_MESSAGE_RESPONSE_LENGTH(msg) ((msg)->response.length) ++#else ++#define SOUP_MESSAGE_RESPONSE_BODY(msg) ((msg)->response_body->data) ++#define SOUP_MESSAGE_RESPONSE_LENGTH(msg) ((msg)->response_body->length) ++#endif ++ + #define MAKE_WARNING_PREFIX(service, group_pos, attribute, element) \ + g_strdup_printf(_("in %s, group %i, \"%s\" attribute of \"%s\" element"), \ + translate_service_get_name((service)), \ +@@ -142,6 +155,7 @@ + const char *name); + + static void translate_generic_service_log_connect (SoupMessage *message); ++#ifdef HAVE_LIBSOUP22 + static void translate_generic_service_log_wrote_headers_h (SoupMessage *message, + gpointer user_data); + static void translate_generic_service_log_wrote_body_h (SoupMessage *message, +@@ -153,10 +167,20 @@ + static void translate_generic_service_log_headers_cb (const char *key, + const char *value, + gpointer user_data); ++#else ++static void translate_generic_service_log_printer (SoupLogger *logger, ++ SoupLoggerLogLevel level, ++ char direction, ++ const char *data, ++ gpointer user_data); ++#endif + + static void translate_generic_service_progress_got_headers_h (SoupMessage *message, + gpointer user_data); + static void translate_generic_service_progress_got_chunk_h (SoupMessage *message, ++#ifdef HAVE_LIBSOUP24 ++ SoupBuffer *chunk, ++#endif + gpointer user_data); + + static void translate_generic_service_html_got_headers_h (SoupMessage *message, +@@ -172,8 +196,10 @@ + static void translate_generic_service_refresh_got_body_h (SoupMessage *message, + gpointer user_data); + ++#ifdef HAVE_LIBSOUP22 + static void translate_generic_service_redirect_handler (SoupMessage *message, + gpointer user_data); ++#endif + + static char *translate_generic_service_translate_text (TranslateService *service, + const char *text, +@@ -440,7 +466,11 @@ + g_return_val_if_fail(post_content_type != NULL, NULL); + soup_message_set_request(message, + post_content_type, ++#ifdef HAVE_LIBSOUP22 + SOUP_BUFFER_USER_OWNED, ++#else ++ SOUP_MEMORY_TEMPORARY, ++#endif + (char *) post, + strlen(post)); + } +@@ -448,7 +478,7 @@ + for (l = headers; l != NULL; l = l->next) + { + TranslateGenericHttpHeader *header = l->data; +- soup_message_add_header(message->request_headers, header->name, header->value); ++ soup_message_headers_append(message->request_headers, header->name, header->value); + } + + info.session = translate_generic_service_soup_session_sync_new(); +@@ -456,12 +486,21 @@ + info.html_http_equiv = NULL; + + if (translate_generic_debug_flags & TRANSLATE_GENERIC_DEBUG_LOG_TRANSFERS) +- g_object_connect(message, +- "signal::wrote-headers", translate_generic_service_log_wrote_headers_h, &info, +- "signal::wrote-body", translate_generic_service_log_wrote_body_h, &info, +- "signal::got-headers", translate_generic_service_log_got_headers_h, &info, +- "signal::got-body", translate_generic_service_log_got_body_h, &info, +- NULL); ++ { ++#ifdef HAVE_LIBSOUP22 ++ g_object_connect(message, ++ "signal::wrote-headers", translate_generic_service_log_wrote_headers_h, &info, ++ "signal::wrote-body", translate_generic_service_log_wrote_body_h, &info, ++ "signal::got-headers", translate_generic_service_log_got_headers_h, &info, ++ "signal::got-body", translate_generic_service_log_got_body_h, &info, ++ NULL); ++#else ++ SoupLogger *logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1); ++ soup_logger_set_printer (logger, translate_generic_service_log_printer, NULL, NULL); ++ soup_logger_attach (logger, info.session); ++ g_object_unref (logger); ++#endif ++ } + + if (progress_func) + { +@@ -489,6 +528,7 @@ + if (flags & TRANSFER_FOLLOW_REFRESH) + g_signal_connect(message, "got-body", G_CALLBACK(translate_generic_service_refresh_got_body_h), &info); + ++#ifdef HAVE_LIBSOUP22 + /* http://bugzilla.ximian.com/show_bug.cgi?id=70688 */ + soup_message_set_flags(message, SOUP_MESSAGE_NO_REDIRECT); + soup_message_add_status_class_handler(message, +@@ -496,6 +536,7 @@ + SOUP_HANDLER_POST_BODY, + translate_generic_service_redirect_handler, + info.session); ++#endif + + if (translate_generic_debug_flags & TRANSLATE_GENERIC_DEBUG_LOG_TRANSFERS) + translate_generic_service_log_connect(message); +@@ -554,18 +595,18 @@ + + if ((charset)||(response_charset)) + { +- response = g_convert(message->response.body, message->response.length, "UTF-8", response_charset?response_charset:charset, NULL, NULL, err); ++ response = g_convert(SOUP_MESSAGE_RESPONSE_BODY (message), SOUP_MESSAGE_RESPONSE_LENGTH (message), "UTF-8", charset, NULL, NULL, err); + g_free(charset); + } + else + { +- if ((flags & TRANSFER_CONVERT) && ! g_utf8_validate(message->response.body, message->response.length, NULL)) ++ if ((flags & TRANSFER_CONVERT) && ! g_utf8_validate(SOUP_MESSAGE_RESPONSE_BODY (message), SOUP_MESSAGE_RESPONSE_LENGTH (message), NULL)) + g_set_error(err, + TRANSLATE_GENERIC_SERVICE_ERROR, + TRANSLATE_GENERIC_SERVICE_ERROR_TRANSFER, + _("invalid UTF-8")); + else +- response = g_strndup(message->response.body, message->response.length); ++ response = g_strndup(SOUP_MESSAGE_RESPONSE_BODY (message), SOUP_MESSAGE_RESPONSE_LENGTH (message)); + } + } + else +@@ -606,7 +647,7 @@ + : NULL; + + if (! value) +- value = soup_message_get_header(message->response_headers, name); ++ value = soup_message_headers_get(message->response_headers, name); + + return value; + } +@@ -614,12 +655,14 @@ + static void + translate_generic_service_log_connect (SoupMessage *message) + { +- const SoupUri *uri; ++ const SoupURI *uri; + + uri = soup_message_get_uri(message); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, _("connecting to %s:%i"), uri->host, uri->port); + } + ++#ifdef HAVE_LIBSOUP22 ++ + static void + translate_generic_service_log_wrote_headers_h (SoupMessage *message, + gpointer user_data) +@@ -674,6 +717,20 @@ + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s %s: %s", prefix, key, value); + } + ++#else /* !HAVE_LIBSOUP22 */ ++ ++static void ++translate_generic_service_log_printer (SoupLogger *logger, ++ SoupLoggerLogLevel level, ++ char direction, ++ const char *data, ++ gpointer user_data) ++{ ++ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%c %s", direction, data); ++} ++ ++#endif /* HAVE_LIBSOUP22 */ ++ + static void + translate_generic_service_progress_got_headers_h (SoupMessage *message, + gpointer user_data) +@@ -681,7 +738,7 @@ + TransferInfo *info = user_data; + const char *content_length; + +- content_length = soup_message_get_header(message->response_headers, "Content-Length"); ++ content_length = soup_message_headers_get(message->response_headers, "Content-Length"); + info->length = (content_length + && *content_length + && strspn(content_length, "0123456789") == strlen(content_length)) +@@ -691,6 +748,9 @@ + + static void + translate_generic_service_progress_got_chunk_h (SoupMessage *message, ++#ifdef HAVE_LIBSOUP24 ++ SoupBuffer *chunk, ++#endif + gpointer user_data) + { + TransferInfo *info = user_data; +@@ -700,7 +760,11 @@ + progress = -1; + else + { ++#ifdef HAVE_LIBSOUP22 + info->received += message->response.length; ++#else ++ info->received += chunk->length; ++#endif + progress = (double) info->received / info->length; + progress = CLAMP(progress, 0.0, 1.0); + } +@@ -716,7 +780,7 @@ + TransferInfo *info = user_data; + const char *content_type; + +- content_type = soup_message_get_header(message->response_headers, "Content-Type"); ++ content_type = soup_message_headers_get(message->response_headers, "Content-Type"); + info->parse_html = content_type + && (g_str_has_prefix(content_type, "text/html") + || g_str_has_prefix(content_type, "application/xhtml+xml") +@@ -736,7 +800,7 @@ + info->html_http_equiv = NULL; + } + +- if (info->parse_html && message->response.length > 0) ++ if (info->parse_html && SOUP_MESSAGE_RESPONSE_LENGTH (message) > 0) + { + char *body; + xmlSAXHandler sax_handler = { NULL }; +@@ -750,7 +814,7 @@ + sax_handler.startElement = translate_generic_service_html_start_element_cb; + sax_handler.endElement = translate_generic_service_html_end_element_cb; + +- body = g_strndup(message->response.body, message->response.length); ++ body = g_strndup(SOUP_MESSAGE_RESPONSE_BODY (message), SOUP_MESSAGE_RESPONSE_LENGTH (message)); + htmlSAXParseDoc(body, NULL, &sax_handler, user_data); + g_free(body); + } +@@ -817,7 +881,7 @@ + { + TransferInfo *info = user_data; + const char *refresh_uri; +- SoupUri *new_uri = NULL; ++ SoupURI *new_uri = NULL; + + refresh_uri = translate_generic_service_get_header(message, info, "Refresh"); + if (refresh_uri) +@@ -832,9 +896,9 @@ + new_uri = soup_uri_new(refresh_uri); + if (! new_uri) + { +- const SoupUri *base_uri; ++ SoupURI *base_uri; + +- base_uri = soup_message_get_uri(message); ++ base_uri = (SoupURI *)soup_message_get_uri(message); + new_uri = soup_uri_new_with_base(base_uri, refresh_uri); + } + } +@@ -851,6 +915,7 @@ + } + } + ++#ifdef HAVE_LIBSOUP22 + static void + translate_generic_service_redirect_handler (SoupMessage *message, + gpointer user_data) +@@ -887,6 +952,7 @@ + soup_session_requeue_message(session, message); + } + } ++#endif + + static char * + translate_generic_service_timed_translate_text (TranslateService *service, +@@ -1391,7 +1457,7 @@ + translate_generic_service_soup_session_sync_new (void) + { + char *proxy_text_uri; +- SoupUri *proxy_uri = NULL; ++ SoupURI *proxy_uri = NULL; + SoupSession *session; + TranslateGenericSoupCookieJar *cookie_jar; + +@@ -1411,7 +1477,7 @@ + soup_uri_free(proxy_uri); + + cookie_jar = translate_generic_soup_cookie_jar_new(); +- soup_session_add_filter(session, SOUP_MESSAGE_FILTER(cookie_jar)); ++ translate_generic_soup_cookie_jar_attach(cookie_jar, session); + g_object_unref(cookie_jar); + + return session; +diff -dPNur libtranslate-0.99/src/modules/translate-generic-soup-cookie-jar.c libtranslate-0.99-1/src/modules/translate-generic-soup-cookie-jar.c +--- libtranslate-0.99/src/modules/translate-generic-soup-cookie-jar.c 2005-01-17 17:46:53.000000000 +0100 ++++ libtranslate-0.99-1/src/modules/translate-generic-soup-cookie-jar.c 2010-02-14 03:55:56.000000000 +0100 +@@ -29,9 +29,12 @@ + * POSSIBILITY OF SUCH DAMAGE. + */ + ++#include "config.h" + #include <string.h> + #include <libsoup/soup.h> ++#ifdef HAVE_LIBSOUP22 + #include <libsoup/soup-message-filter.h> ++#endif + #include "translate-generic-soup-cookie-jar.h" + + struct _TranslateGenericSoupCookieJarPrivate +@@ -44,9 +47,12 @@ + static void translate_generic_soup_cookie_jar_register_type (GType *type); + static void translate_generic_soup_cookie_jar_class_init (TranslateGenericSoupCookieJarClass *class); + static void translate_generic_soup_cookie_jar_init (TranslateGenericSoupCookieJar *jar); ++#ifdef HAVE_LIBSOUP22 + static void translate_generic_soup_cookie_jar_filter_init (SoupMessageFilterClass *iface); ++#else ++#define SoupMessageFilter TranslateGenericSoupCookieJar ++#endif + static void translate_generic_soup_cookie_jar_finalize (GObject *object); +- + static void translate_generic_soup_cookie_jar_setup_message (SoupMessageFilter *filter, + SoupMessage *message); + +@@ -75,17 +81,21 @@ + 0, + (GInstanceInitFunc) translate_generic_soup_cookie_jar_init + }; ++#ifdef HAVE_LIBSOUP22 + static const GInterfaceInfo filter_info = { + (GInterfaceInitFunc) translate_generic_soup_cookie_jar_filter_init, + NULL, + NULL + }; ++#endif + + *type = g_type_register_static(G_TYPE_OBJECT, + "TranslateGenericSoupCookieJar", + &info, + 0); ++#ifdef HAVE_LIBSOUP22 + g_type_add_interface_static(*type, SOUP_TYPE_MESSAGE_FILTER, &filter_info); ++#endif + } + + static void +@@ -107,11 +117,13 @@ + TranslateGenericSoupCookieJarPrivate); + } + ++#ifdef HAVE_LIBSOUP22 + static void + translate_generic_soup_cookie_jar_filter_init (SoupMessageFilterClass *iface) + { + iface->setup_message = translate_generic_soup_cookie_jar_setup_message; + } ++#endif + + static void + translate_generic_soup_cookie_jar_finalize (GObject *object) +@@ -125,26 +137,46 @@ + } + + static void ++add_cookie_to_jar (TranslateGenericSoupCookieJar *jar, const char *cookie) ++{ ++ char *s; ++ ++ s = strchr(cookie, ';'); ++ if (s) ++ jar->priv->cookies = g_slist_append(jar->priv->cookies, g_strndup(cookie, s - cookie)); ++} ++ ++#ifdef HAVE_LIBSOUP24 ++static void ++maybe_add_cookie_to_jar (const char *header, const char *value, gpointer jar) ++{ ++ if (!g_ascii_strcasecmp (header, "Set-Cookie")) ++ add_cookie_to_jar (jar, value); ++} ++#endif ++ ++static void + translate_generic_soup_cookie_jar_setup_message (SoupMessageFilter *filter, +- SoupMessage *message) ++ SoupMessage *message) + { + TranslateGenericSoupCookieJar *jar = TRANSLATE_GENERIC_SOUP_COOKIE_JAR(filter); +- const GSList *cookies; + const GSList *l; + + /* FIXME: add full RFC 2965 support */ + ++#ifdef HAVE_LIBSOUP22 ++ const GSList *cookies; ++ + cookies = soup_message_get_header_list(message->response_headers, "Set-Cookie"); + for (l = cookies; l != NULL; l = l->next) + { + const char *cookie = l->data; +- char *s; +- +- s = strchr(cookie, ';'); +- if (s) +- jar->priv->cookies = g_slist_append(jar->priv->cookies, g_strndup(cookie, s - cookie)); ++ add_cookie_to_jar(jar, cookie); + } +- ++#else ++ soup_message_headers_foreach(message->response_headers, maybe_add_cookie_to_jar, jar); ++#endif ++ + if (jar->priv->cookies) + { + GString *string; +@@ -159,13 +191,44 @@ + g_string_append(string, "; "); + } + ++#ifdef HAVE_LIBSOUP22 + soup_message_add_header(message->request_headers, "Cookie", string->str); ++#else ++ soup_message_headers_append(message->request_headers, "Cookie", string->str); ++#endif + g_string_free(string, TRUE); + } + } + ++#ifdef HAVE_LIBSOUP24 ++static void ++translate_generic_soup_cookie_jar_request_started (SoupSession *session, ++ SoupMessage *message, ++ SoupSocket *socket, ++ gpointer cookie_jar) ++{ ++ translate_generic_soup_cookie_jar_setup_message (cookie_jar, message); ++} ++#endif ++ + TranslateGenericSoupCookieJar * + translate_generic_soup_cookie_jar_new (void) + { + return g_object_new(TRANSLATE_GENERIC_TYPE_SOUP_COOKIE_JAR, NULL); + } ++ ++void ++translate_generic_soup_cookie_jar_attach (TranslateGenericSoupCookieJar *cookie_jar, ++ SoupSession *session) ++{ ++#ifdef HAVE_LIBSOUP22 ++ soup_session_add_filter (session, SOUP_MESSAGE_FILTER(cookie_jar)); ++#else ++ g_signal_connect (session, "request_started", ++ G_CALLBACK (translate_generic_soup_cookie_jar_request_started), ++ cookie_jar); ++ g_object_set_data_full (G_OBJECT (session), "TranslateGenericSoupCookieJar", ++ g_object_ref (cookie_jar), g_object_unref); ++#endif ++} ++ +diff -dPNur libtranslate-0.99/src/modules/translate-generic-soup-cookie-jar.h libtranslate-0.99-1/src/modules/translate-generic-soup-cookie-jar.h +--- libtranslate-0.99/src/modules/translate-generic-soup-cookie-jar.h 2005-01-17 17:47:00.000000000 +0100 ++++ libtranslate-0.99-1/src/modules/translate-generic-soup-cookie-jar.h 2010-02-14 03:55:56.000000000 +0100 +@@ -33,6 +33,7 @@ + #define _TRANSLATE_GENERIC_SOUP_COOKIE_JAR_H + + #include <glib-object.h> ++#include <libsoup/soup-session.h> + + #define TRANSLATE_GENERIC_TYPE_SOUP_COOKIE_JAR (translate_generic_soup_cookie_jar_get_type()) + #define TRANSLATE_GENERIC_SOUP_COOKIE_JAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TRANSLATE_GENERIC_TYPE_SOUP_COOKIE_JAR, TranslateGenericSoupCookieJar)) +@@ -59,5 +60,6 @@ + + GType translate_generic_soup_cookie_jar_get_type (void); + TranslateGenericSoupCookieJar *translate_generic_soup_cookie_jar_new (void); ++void translate_generic_soup_cookie_jar_attach (TranslateGenericSoupCookieJar *cookie_jar, SoupSession *session); + + #endif /* _TRANSLATE_GENERIC_SOUP_COOKIE_JAR_H */ diff --git a/patches/mpg123/mpg123-ds-rcc.patch b/patches/mpg123/mpg123-ds-rcc.patch new file mode 100644 index 0000000..bbfd104 --- /dev/null +++ b/patches/mpg123/mpg123-ds-rcc.patch @@ -0,0 +1,151 @@ +diff -dPNur mpg123-0.59r/common.c mpg123-0.59r-new/common.c +--- mpg123-0.59r/common.c 1999-06-15 23:24:19.000000000 +0200 ++++ mpg123-0.59r-new/common.c 2005-09-16 02:48:11.000000000 +0200 +@@ -15,6 +15,7 @@ + #endif + #endif + ++#include "rccpatch.h" + #include "mpg123.h" + #include "genre.h" + #include "common.h" +@@ -484,6 +485,8 @@ + char comment[31]={0,}; + char genre[31]={0,}; + ++ char *ctitle, *cartist, *calbum, *ccomment; ++ + if(param.quiet) + return; + +@@ -492,16 +495,26 @@ + strncpy(album,tag->album,30); + strncpy(year,tag->year,4); + strncpy(comment,tag->comment,30); ++ ++ ctitle = rccPatchRecode(title); ++ cartist = rccPatchRecode(artist); ++ calbum = rccPatchRecode(album); ++ ccomment = rccPatchRecode(comment); + +- if ( tag->genre <= sizeof(genre_table)/sizeof(*genre_table) ) { ++ if ( tag->genre < sizeof(genre_table)/sizeof(*genre_table) ) { + strncpy(genre, genre_table[tag->genre], 30); + } else { + strncpy(genre,"Unknown",30); + } + +- fprintf(stderr,"Title : %-30s Artist: %s\n",title,artist); +- fprintf(stderr,"Album : %-30s Year : %4s\n",album,year); +- fprintf(stderr,"Comment: %-30s Genre : %s\n",comment,genre); ++ fprintf(stderr,"Title : %-30s Artist: %s\n",ctitle?ctitle:title,cartist?cartist:artist); ++ fprintf(stderr,"Album : %-30s Year : %4s\n",calbum?calbum:album,year); ++ fprintf(stderr,"Comment: %-30s Genre : %s\n",ccomment?ccomment:comment,genre); ++ ++ if (ctitle) free(ctitle); ++ if (cartist) free(cartist); ++ if (calbum) free(calbum); ++ if (ccomment) free(ccomment); + } + + #if 0 +diff -dPNur mpg123-0.59r/Makefile mpg123-0.59r-new/Makefile +--- mpg123-0.59r/Makefile 1999-06-18 14:18:58.000000000 +0200 ++++ mpg123-0.59r-new/Makefile 2005-09-16 02:47:47.000000000 +0200 +@@ -554,12 +554,12 @@ + mpg123-make: + @ $(MAKE) CFLAGS='$(CFLAGS)' BINNAME=mpg123 mpg123 + +-mpg123: mpg123.o common.o $(OBJECTS) decode_2to1.o decode_4to1.o \ ++mpg123: mpg123.o rccpatch.o common.o $(OBJECTS) decode_2to1.o decode_4to1.o \ + tabinit.o audio.o layer1.o layer2.o layer3.o buffer.o \ + getlopt.o httpget.o xfermem.o equalizer.o \ + decode_ntom.o Makefile wav.o readers.o getbits.o \ + control_generic.o +- $(CC) $(CFLAGS) $(LDFLAGS) mpg123.o tabinit.o common.o layer1.o \ ++ $(CC) $(CFLAGS) $(LDFLAGS) -lrcc mpg123.o tabinit.o rccpatch.o common.o layer1.o \ + layer2.o layer3.o audio.o buffer.o decode_2to1.o equalizer.o \ + decode_4to1.o getlopt.o httpget.o xfermem.o decode_ntom.o \ + wav.o readers.o getbits.o control_generic.o \ +diff -dPNur mpg123-0.59r/mpg123.c mpg123-0.59r-new/mpg123.c +--- mpg123-0.59r/mpg123.c 1999-06-18 14:18:11.000000000 +0200 ++++ mpg123-0.59r-new/mpg123.c 2005-09-16 02:47:47.000000000 +0200 +@@ -32,6 +32,8 @@ + #include "buffer.h" + #include "term.h" + ++#include "rccpatch.h" ++ + #include "version.h" + + static void usage(char *dummy); +@@ -903,6 +905,8 @@ + exit(0); + } + #endif ++ ++ rccPatchInit(); + + while ((fname = get_next_file(argc, argv))) { + char *dirname, *filename; +@@ -1068,6 +1072,8 @@ + intflag = FALSE; + } + } ++ rccPatchFree(); ++ + #ifndef NOXFERMEM + if (param.usebuffer) { + buffer_end(); +diff -dPNur mpg123-0.59r/rccpatch.c mpg123-0.59r-new/rccpatch.c +--- mpg123-0.59r/rccpatch.c 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-0.59r-new/rccpatch.c 2005-09-16 02:47:47.000000000 +0200 +@@ -0,0 +1,40 @@ ++#include <librcc.h> ++ ++#define ID3_CLASS 0 ++#define OUT_CLASS 1 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, NULL, NULL, "Output Encoding", 0 }, ++ { NULL } ++}; ++ ++static int rcc_initialized = 0; ++ ++void rccPatchFree() { ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++} ++ ++void rccPatchInit() { ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++} ++ ++static void rccPatchTryInit() { ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++} ++ ++char *rccPatchRecode(const char *str) { ++ char *res; ++ rccPatchTryInit(); ++ return rccRecode(NULL, ID3_CLASS, OUT_CLASS, str); ++} +diff -dPNur mpg123-0.59r/rccpatch.h mpg123-0.59r-new/rccpatch.h +--- mpg123-0.59r/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-0.59r-new/rccpatch.h 2005-09-16 02:47:47.000000000 +0200 +@@ -0,0 +1,4 @@ ++void rccPatchFree(); ++void rccPatchInit(); ++char *rccPatchRecode(const char *str); ++ diff --git a/patches/mpg123/mpg123-ds-rcc1121.patch b/patches/mpg123/mpg123-ds-rcc1121.patch new file mode 100644 index 0000000..1335795 --- /dev/null +++ b/patches/mpg123/mpg123-ds-rcc1121.patch @@ -0,0 +1,247 @@ +diff -dPNur mpg123-1.12.1/configure.ac mpg123-1.12.1-new/configure.ac +--- mpg123-1.12.1/configure.ac 2010-03-31 10:27:37.000000000 +0200 ++++ mpg123-1.12.1-new/configure.ac 2010-07-07 23:44:57.000000000 +0200 +@@ -998,6 +998,21 @@ + AC_CHECK_LIB([m], [sqrt]) + AC_CHECK_LIB([mx], [powf]) + ++# LibRCC ++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) ++ + # attempt to make the signal stuff work... also with GENERIC - later + #if test x"$ac_cv_header_sys_signal_h" = xyes; then + # AC_CHECK_FUNCS( sigemptyset sigaddset sigprocmask sigaction ) +diff -dPNur mpg123-1.12.1/src/libmpg123/id3.c mpg123-1.12.1-new/src/libmpg123/id3.c +--- mpg123-1.12.1/src/libmpg123/id3.c 2010-03-31 10:27:35.000000000 +0200 ++++ mpg123-1.12.1-new/src/libmpg123/id3.c 2010-07-07 23:51:50.000000000 +0200 +@@ -9,6 +9,8 @@ + #include "mpg123lib_intern.h" + #include "id3.h" + #include "debug.h" ++#include "rccpatch.h" ++ + + #ifndef NO_ID3V2 /* Only the main parsing routine will always be there. */ + +@@ -829,6 +831,15 @@ + size_t length = l; + size_t i; + unsigned char *p; ++ char *ctitle; ++ ++ ctitle = mpg123_rcc_recode(s, l, &i); ++ if (ctitle) { ++ convert_utf8(sb, ctitle, i, 0); ++ free(ctitle); ++ return; ++ } ++ + /* determine real length, a latin1 character can at most take 2 in UTF8 */ + for(i=0; i<l; ++i) + if(s[i] >= 0x80) ++length; +diff -dPNur mpg123-1.12.1/src/libmpg123/Makefile.am mpg123-1.12.1-new/src/libmpg123/Makefile.am +--- mpg123-1.12.1/src/libmpg123/Makefile.am 2010-03-31 10:27:35.000000000 +0200 ++++ mpg123-1.12.1-new/src/libmpg123/Makefile.am 2010-07-07 23:44:57.000000000 +0200 +@@ -29,6 +29,8 @@ + libmpg123_la_DEPENDENCIES = @DECODER_LOBJ@ @LFS_LOBJ@ + + libmpg123_la_SOURCES = \ ++ rccpatch.c \ ++ rccpatch.h \ + compat.c \ + compat.h \ + parse.c \ +diff -dPNur mpg123-1.12.1/src/libmpg123/rccpatch.c mpg123-1.12.1-new/src/libmpg123/rccpatch.c +--- mpg123-1.12.1/src/libmpg123/rccpatch.c 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-1.12.1-new/src/libmpg123/rccpatch.c 2010-07-07 23:55:59.000000000 +0200 +@@ -0,0 +1,76 @@ ++#include <string.h> ++#include <librcc.h> ++#include "mpg123.h" ++ ++#define ID3_CLASS 0 ++#define UTF_CLASS 1 ++#define OUT_CLASS 2 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, NULL, NULL, "Output Encoding", 0 }, ++ { NULL } ++}; ++ ++static int rcc_initialized = 0; ++ ++void mpg123_rcc_free() { ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++} ++ ++void mpg123_rcc_init() { ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++} ++ ++static void mpg123_rcc_try_init() { ++ if (!rcc_initialized) { ++ mpg123_rcc_init(); ++ if (rcc_initialized) atexit(mpg123_rcc_free); ++ } ++} ++ ++ ++char *mpg123_rcc_recode(const char *str, size_t len, size_t *rlen) { ++ char *res; ++ mpg123_rcc_try_init(); ++ return rccSizedRecode(NULL, ID3_CLASS, UTF_CLASS, str, len, rlen); ++} ++ ++static void mpg123_rcc_recode_string(mpg123_string *str, rcc_class_id from, rcc_class_id to) { ++ size_t size; ++ char *res; ++ ++ if ((!str)||(str->fill<2)) return; ++ ++ mpg123_rcc_try_init(); ++ ++ res = rccSizedRecode(NULL, from, to, str->p, str->fill - 1, &size); ++ if (res) { ++ if (size+1>str->size) { ++ if (!mpg123_resize_string(str, size + 1)) { ++ // allocation failed ++ free(res); ++ return; ++ } ++ } ++ strncpy(str->p, res, size + 1); ++ str->fill = size + 1; ++ free(res); ++ } ++} ++ ++void mpg123_rcc_recode_utf_string(mpg123_string *str) { ++ mpg123_rcc_recode_string(str, UTF_CLASS, OUT_CLASS); ++} ++ ++void mpg123_rcc_recode_latin_string(mpg123_string *str) { ++ mpg123_rcc_recode_string(str, ID3_CLASS, OUT_CLASS); ++} +diff -dPNur mpg123-1.12.1/src/libmpg123/rccpatch.h mpg123-1.12.1-new/src/libmpg123/rccpatch.h +--- mpg123-1.12.1/src/libmpg123/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-1.12.1-new/src/libmpg123/rccpatch.h 2010-07-07 23:44:57.000000000 +0200 +@@ -0,0 +1,5 @@ ++void mpg123_rcc_free(); ++void mpg123_rcc_init(); ++char *mpg123_rcc_recode(const char *str, size_t len, size_t *rlen); ++void mpg123_rcc_recode_utf_string(mpg123_string *str); ++void mpg123_rcc_recode_latin_string(mpg123_string *str); +diff -dPNur mpg123-1.12.1/src/Makefile.am mpg123-1.12.1-new/src/Makefile.am +--- mpg123-1.12.1/src/Makefile.am 2010-03-31 10:27:36.000000000 +0200 ++++ mpg123-1.12.1-new/src/Makefile.am 2010-07-07 23:46:10.000000000 +0200 +@@ -5,10 +5,10 @@ + ## initially written by Nicholas J. Humfrey + + AM_CPPFLAGS = -DPKGLIBDIR="\"$(pkglibdir)\"" +-mpg123_LDADD = $(LIBLTDL) libmpg123/libmpg123.la @MODULE_OBJ@ @OUTPUT_OBJ@ @OUTPUT_LIBS@ ++mpg123_LDADD = $(LIBLTDL) libmpg123/libmpg123.la @MODULE_OBJ@ @OUTPUT_OBJ@ @OUTPUT_LIBS@ @LIBRCC_LIBS@ + mpg123_LDFLAGS = @EXEC_LT_LDFLAGS@ @OUTPUT_LDFLAGS@ + # Just mpg123_INCLUDES has no effect on build! Trying that before reverting to AM_CPPFLAGS. +-INCLUDES = $(LTDLINCL) -I$(top_builddir)/src/libmpg123 -I$(top_srcdir)/src/libmpg123 ++INCLUDES = $(LTDLINCL) -I$(top_builddir)/src/libmpg123 -I$(top_srcdir)/src/libmpg123 @LIBRCC_INCLUDES@ + # libltdl is not mentioned here... it's not that trivial + mpg123_DEPENDENCIES = @OUTPUT_OBJ@ @MODULE_OBJ@ libmpg123/libmpg123.la + +diff -dPNur mpg123-1.12.1/src/metaprint.c mpg123-1.12.1-new/src/metaprint.c +--- mpg123-1.12.1/src/metaprint.c 2010-03-31 10:27:36.000000000 +0200 ++++ mpg123-1.12.1-new/src/metaprint.c 2010-07-07 23:54:21.000000000 +0200 +@@ -17,7 +17,11 @@ + if(source == NULL) return; + + if(utf8env) mpg123_copy_string(source, dest); +- else utf8_ascii(dest, source); ++ else { ++ mpg123_copy_string(source, dest); ++ mpg123_rcc_recode_utf_string(dest); ++// utf8_ascii(dest, source); ++ } + } + + /* print tags... limiting the UTF-8 to ASCII */ +@@ -53,6 +57,7 @@ + strncpy(tag[TITLE].p,v1->title,30); + tag[TITLE].p[30] = 0; + tag[TITLE].fill = strlen(tag[TITLE].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[TITLE]); + } + } + if(!tag[ARTIST].fill) +@@ -62,6 +67,7 @@ + strncpy(tag[ARTIST].p,v1->artist,30); + tag[ARTIST].p[30] = 0; + tag[ARTIST].fill = strlen(tag[ARTIST].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[ARTIST]); + } + } + if(!tag[ALBUM].fill) +@@ -71,6 +77,7 @@ + strncpy(tag[ALBUM].p,v1->album,30); + tag[ALBUM].p[30] = 0; + tag[ALBUM].fill = strlen(tag[ALBUM].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[ALBUM]); + } + } + if(!tag[COMMENT].fill) +@@ -80,6 +87,7 @@ + strncpy(tag[COMMENT].p,v1->comment,30); + tag[COMMENT].p[30] = 0; + tag[COMMENT].fill = strlen(tag[COMMENT].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[COMMENT]); + } + } + if(!tag[YEAR].fill) +diff -dPNur mpg123-1.12.1/src/mpg123.c mpg123-1.12.1-new/src/mpg123.c +--- mpg123-1.12.1/src/mpg123.c 2010-03-31 10:27:36.000000000 +0200 ++++ mpg123-1.12.1-new/src/mpg123.c 2010-07-07 23:52:58.000000000 +0200 +@@ -10,6 +10,7 @@ + #include "mpg123app.h" + #include "mpg123.h" + #include "local.h" ++#include "rccpatch.h" + + #ifdef HAVE_SYS_WAIT_H + #include <sys/wait.h> +@@ -973,6 +974,8 @@ + if(param.term_ctrl) + term_init(); + #endif ++ ++ mpg123_rcc_init(); + while ((fname = get_next_file())) + { + char *dirname, *filename; +@@ -1132,6 +1135,8 @@ + #endif + } + } /* end of loop over input files */ ++ mpg123_rcc_free(); ++ + /* Ensure we played everything. */ + if(param.smooth && param.usebuffer) + { diff --git a/patches/mpg123/mpg123-ds-rcc173.patch b/patches/mpg123/mpg123-ds-rcc173.patch new file mode 100644 index 0000000..ae814ff --- /dev/null +++ b/patches/mpg123/mpg123-ds-rcc173.patch @@ -0,0 +1,271 @@ +diff -dPNur mpg123-1.7.3/configure.ac mpg123-1.7.3-rusxmms/configure.ac +--- mpg123-1.7.3/configure.ac 2009-04-27 09:02:40.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/configure.ac 2009-06-13 23:22:17.000000000 +0200 +@@ -759,6 +759,21 @@ + AC_CHECK_LIB([m], [sqrt]) + AC_CHECK_LIB([mx], [powf]) + ++# LibRCC ++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) ++ + # attempt to make the signal stuff work... also with GENERIC - later + #if test x"$ac_cv_header_sys_signal_h" = xyes; then + # AC_CHECK_FUNCS( sigemptyset sigaddset sigprocmask sigaction ) +diff -dPNur mpg123-1.7.3/src/libmpg123/id3.c mpg123-1.7.3-rusxmms/src/libmpg123/id3.c +--- mpg123-1.7.3/src/libmpg123/id3.c 2009-04-27 09:02:12.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/libmpg123/id3.c 2009-06-14 00:34:23.000000000 +0200 +@@ -9,6 +9,8 @@ + #include "mpg123lib_intern.h" + #include "id3.h" + #include "debug.h" ++#include "rccpatch.h" ++ + + #ifndef NO_ID3V2 /* Only the main parsing routine will always be there. */ + +@@ -774,6 +776,15 @@ + size_t length = l; + size_t i; + unsigned char *p; ++ char *ctitle; ++ ++ ctitle = mpg123_rcc_recode(s, l, &i); ++ if (ctitle) { ++ convert_utf8(sb, ctitle, i); ++ free(ctitle); ++ return; ++ } ++ + /* determine real length, a latin1 character can at most take 2 in UTF8 */ + for(i=0; i<l; ++i) + if(s[i] >= 0x80) ++length; +diff -dPNur mpg123-1.7.3/src/libmpg123/libmpg123.sym mpg123-1.7.3-rusxmms/src/libmpg123/libmpg123.sym +--- mpg123-1.7.3/src/libmpg123/libmpg123.sym 2009-04-27 09:07:20.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/libmpg123/libmpg123.sym 2009-06-14 01:53:25.000000000 +0200 +@@ -74,3 +74,8 @@ + mpg123_position + mpg123_length + mpg123_set_filesize ++mpg123_rcc_free ++mpg123_rcc_init ++mpg123_rcc_recode ++mpg123_rcc_recode_utf_string ++mpg123_rcc_recode_latin_string +diff -dPNur mpg123-1.7.3/src/libmpg123/libmpg123.sym.in mpg123-1.7.3-rusxmms/src/libmpg123/libmpg123.sym.in +--- mpg123-1.7.3/src/libmpg123/libmpg123.sym.in 2009-04-27 09:02:12.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/libmpg123/libmpg123.sym.in 2009-06-14 01:51:45.000000000 +0200 +@@ -74,3 +74,8 @@ + mpg123_position@LARGEFILE_SUFFIX@ + mpg123_length@LARGEFILE_SUFFIX@ + mpg123_set_filesize@LARGEFILE_SUFFIX@ ++mpg123_rcc_free ++mpg123_rcc_init ++mpg123_rcc_recode ++mpg123_rcc_recode_utf_string ++mpg123_rcc_recode_latin_string +diff -dPNur mpg123-1.7.3/src/libmpg123/Makefile.am mpg123-1.7.3-rusxmms/src/libmpg123/Makefile.am +--- mpg123-1.7.3/src/libmpg123/Makefile.am 2009-04-27 09:02:12.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/libmpg123/Makefile.am 2009-06-14 00:10:34.000000000 +0200 +@@ -31,6 +31,8 @@ + libmpg123_la_DEPENDENCIES = @DECODER_LOBJ@ libmpg123.sym + + libmpg123_la_SOURCES = \ ++ rccpatch.c \ ++ rccpatch.h \ + compat.c \ + compat.h \ + parse.c \ +diff -dPNur mpg123-1.7.3/src/libmpg123/rccpatch.c mpg123-1.7.3-rusxmms/src/libmpg123/rccpatch.c +--- mpg123-1.7.3/src/libmpg123/rccpatch.c 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-1.7.3-rusxmms/src/libmpg123/rccpatch.c 2009-06-14 01:54:37.000000000 +0200 +@@ -0,0 +1,76 @@ ++#include <string.h> ++#include <librcc.h> ++#include "mpg123.h" ++ ++#define ID3_CLASS 0 ++#define UTF_CLASS 1 ++#define OUT_CLASS 2 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, NULL, NULL, "Output Encoding", 0 }, ++ { NULL } ++}; ++ ++static int rcc_initialized = 0; ++ ++void mpg123_rcc_free() { ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++} ++ ++void mpg123_rcc_init() { ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++} ++ ++static void mpg123_rcc_try_init() { ++ if (!rcc_initialized) { ++ mpg123_rcc_init(); ++ if (rcc_initialized) atexit(mpg123_rcc_free); ++ } ++} ++ ++ ++char *mpg123_rcc_recode(const char *str, size_t len, size_t *rlen) { ++ char *res; ++ mpg123_rcc_try_init(); ++ return rccSizedRecode(NULL, ID3_CLASS, UTF_CLASS, str, len, rlen); ++} ++ ++static void mpg123_rcc_recode_string(mpg123_string *str, rcc_class_id from, rcc_class_id to) { ++ size_t size; ++ char *res; ++ ++ if ((!str)||(str->fill<2)) return; ++ ++ mpg123_rcc_try_init(); ++ ++ res = rccSizedRecode(NULL, from, to, str->p, str->fill - 1, &size); ++ if (res) { ++ if (size+1>str->size) { ++ if (!mpg123_resize_string(str, size + 1)) { ++ // allocation failed ++ free(res); ++ return; ++ } ++ } ++ strncpy(str->p, res, size + 1); ++ str->fill = size + 1; ++ free(res); ++ } ++} ++ ++void mpg123_rcc_recode_utf_string(mpg123_string *str) { ++ mpg123_rcc_recode_string(str, UTF_CLASS, OUT_CLASS); ++} ++ ++void mpg123_rcc_recode_latin_string(mpg123_string *str) { ++ mpg123_rcc_recode_string(str, ID3_CLASS, OUT_CLASS); ++} +diff -dPNur mpg123-1.7.3/src/libmpg123/rccpatch.h mpg123-1.7.3-rusxmms/src/libmpg123/rccpatch.h +--- mpg123-1.7.3/src/libmpg123/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-1.7.3-rusxmms/src/libmpg123/rccpatch.h 2009-06-14 01:51:21.000000000 +0200 +@@ -0,0 +1,5 @@ ++void mpg123_rcc_free(); ++void mpg123_rcc_init(); ++char *mpg123_rcc_recode(const char *str, size_t len, size_t *rlen); ++void mpg123_rcc_recode_utf_string(mpg123_string *str); ++void mpg123_rcc_recode_latin_string(mpg123_string *str); +diff -dPNur mpg123-1.7.3/src/Makefile.am mpg123-1.7.3-rusxmms/src/Makefile.am +--- mpg123-1.7.3/src/Makefile.am 2009-04-27 09:02:12.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/Makefile.am 2009-06-14 00:10:22.000000000 +0200 +@@ -5,10 +5,10 @@ + ## initially written by Nicholas J. Humfrey + + AM_CPPFLAGS = -DPKGLIBDIR="\"$(pkglibdir)\"" +-mpg123_LDADD = $(LIBLTDL) libmpg123/libmpg123.la @MODULE_OBJ@ @OUTPUT_OBJ@ @OUTPUT_LIBS@ ++mpg123_LDADD = $(LIBLTDL) libmpg123/libmpg123.la @MODULE_OBJ@ @OUTPUT_OBJ@ @OUTPUT_LIBS@ @LIBRCC_LIBS@ + mpg123_LDFLAGS = @LT_LDFLAGS@ @OUTPUT_LDFLAGS@ + # Just mpg123_INCLUDES has no effect on build! Trying that before reverting to AM_CPPFLAGS. +-INCLUDES = $(LTDLINCL) -I$(top_builddir)/src/libmpg123 -I$(top_srcdir)/src/libmpg123 ++INCLUDES = $(LTDLINCL) -I$(top_builddir)/src/libmpg123 -I$(top_srcdir)/src/libmpg123 @LIBRCC_INCLUDES@ + # libltdl is not mentioned here... it's not that trivial + mpg123_DEPENDENCIES = @OUTPUT_OBJ@ @MODULE_OBJ@ libmpg123/libmpg123.la + +diff -dPNur mpg123-1.7.3/src/metaprint.c mpg123-1.7.3-rusxmms/src/metaprint.c +--- mpg123-1.7.3/src/metaprint.c 2009-04-27 09:02:12.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/metaprint.c 2009-06-14 01:59:09.000000000 +0200 +@@ -17,7 +17,11 @@ + if(source == NULL) return; + + if(utf8env) mpg123_copy_string(source, dest); +- else utf8_ascii(dest, source); ++ else { ++ mpg123_copy_string(source, dest); ++ mpg123_rcc_recode_utf_string(dest); ++// utf8_ascii(dest, source); ++ } + } + + /* print tags... limiting the UTF-8 to ASCII */ +@@ -53,6 +57,7 @@ + strncpy(tag[TITLE].p,v1->title,30); + tag[TITLE].p[30] = 0; + tag[TITLE].fill = strlen(tag[TITLE].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[TITLE]); + } + } + if(!tag[ARTIST].fill) +@@ -62,6 +67,7 @@ + strncpy(tag[ARTIST].p,v1->artist,30); + tag[ARTIST].p[30] = 0; + tag[ARTIST].fill = strlen(tag[ARTIST].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[ARTIST]); + } + } + if(!tag[ALBUM].fill) +@@ -71,6 +77,7 @@ + strncpy(tag[ALBUM].p,v1->album,30); + tag[ALBUM].p[30] = 0; + tag[ALBUM].fill = strlen(tag[ALBUM].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[ALBUM]); + } + } + if(!tag[COMMENT].fill) +@@ -80,6 +87,7 @@ + strncpy(tag[COMMENT].p,v1->comment,30); + tag[COMMENT].p[30] = 0; + tag[COMMENT].fill = strlen(tag[COMMENT].p) + 1; ++ mpg123_rcc_recode_latin_string(&tag[COMMENT]); + } + } + if(!tag[YEAR].fill) +diff -dPNur mpg123-1.7.3/src/mpg123.c mpg123-1.7.3-rusxmms/src/mpg123.c +--- mpg123-1.7.3/src/mpg123.c 2009-04-27 09:02:12.000000000 +0200 ++++ mpg123-1.7.3-rusxmms/src/mpg123.c 2009-06-14 00:35:14.000000000 +0200 +@@ -10,6 +10,7 @@ + #include "mpg123app.h" + #include "mpg123.h" + #include "local.h" ++#include "rccpatch.h" + + #ifdef HAVE_SYS_WAIT_H + #include <sys/wait.h> +@@ -893,6 +894,8 @@ + if(param.term_ctrl) + term_init(); + #endif ++ ++ mpg123_rcc_init(); + while ((fname = get_next_file())) + { + char *dirname, *filename; +@@ -1038,6 +1041,8 @@ + #endif + } + } /* end of loop over input files */ ++ mpg123_rcc_free(); ++ + /* Ensure we played everything. */ + if(param.smooth && param.usebuffer) + { diff --git a/patches/mpg123/mpg123-ds-rcc65.patch b/patches/mpg123/mpg123-ds-rcc65.patch new file mode 100644 index 0000000..41a4d33 --- /dev/null +++ b/patches/mpg123/mpg123-ds-rcc65.patch @@ -0,0 +1,240 @@ +diff -dPNur mpg123-0.65/configure.ac mpg123-0.65-new/configure.ac +--- mpg123-0.65/configure.ac 2007-02-07 10:24:33.000000000 +0100 ++++ mpg123-0.65-new/configure.ac 2007-04-15 13:36:52.000000000 +0200 +@@ -137,6 +137,21 @@ + AC_CHECK_LIB([m], [sqrt]) + AC_CHECK_LIB([mx], [powf]) + ++# LibRCC ++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) ++ + # Check for JACK + PKG_CHECK_MODULES(JACK, jack, HAVE_JACK=yes, HAVE_JACK=no) + +diff -dPNur mpg123-0.65/src/id3.c mpg123-0.65-new/src/id3.c +--- mpg123-0.65/src/id3.c 2007-02-07 10:24:33.000000000 +0100 ++++ mpg123-0.65-new/src/id3.c 2007-04-15 13:26:06.000000000 +0200 +@@ -6,6 +6,7 @@ + #include "stringbuf.h" + #include "genre.h" + #include "id3.h" ++#include "rccpatch.h" + + struct taginfo + { +@@ -499,6 +500,8 @@ + void print_id3_tag(unsigned char *id3v1buf) + { + char genre_from_v1 = 0; ++ char *ctitle, *cartist, *calbum, *ccomment; ++ + if(!(id3.version || id3v1buf)) return; + if(id3v1buf != NULL) + { +@@ -688,17 +691,26 @@ + free_stringbuf(&tmp); + } + ++ if (id3.title.fill) ctitle = rccPatchRecode(id3.title.p); ++ else ctitle = NULL; ++ if (id3.artist.fill) cartist = rccPatchRecode(id3.artist.p); ++ else cartist = NULL; ++ if (id3.album.fill) calbum = rccPatchRecode(id3.album.p); ++ else calbum = NULL; ++ if (id3.comment.fill) ccomment = rccPatchRecode(id3.comment.p); ++ else ccomment = NULL; ++ + if(param.long_id3) + { + fprintf(stderr,"\n"); + /* print id3v2 */ + /* dammed, I use pointers as bool again! It's so convenient... */ +- fprintf(stderr,"\tTitle: %s\n", id3.title.fill ? id3.title.p : ""); +- fprintf(stderr,"\tArtist: %s\n", id3.artist.fill ? id3.artist.p : ""); +- fprintf(stderr,"\tAlbum: %s\n", id3.album.fill ? id3.album.p : ""); ++ fprintf(stderr,"\tTitle: %s\n", ctitle?ctitle:(id3.title.fill ? id3.title.p : "")); ++ fprintf(stderr,"\tArtist: %s\n", cartist?cartist:(id3.artist.fill ? id3.artist.p : "")); ++ fprintf(stderr,"\tAlbum: %s\n", calbum?calbum:(id3.album.fill ? id3.album.p : "")); + fprintf(stderr,"\tYear: %s\n", id3.year.fill ? id3.year.p : ""); + fprintf(stderr,"\tGenre: %s\n", id3.genre.fill ? id3.genre.p : ""); +- fprintf(stderr,"\tComment: %s\n", id3.comment.fill ? id3.comment.p : ""); ++ fprintf(stderr,"\tComment: %s\n", ccomment?ccomment:(id3.comment.fill ? id3.comment.p : "")); + fprintf(stderr,"\n"); + } + else +@@ -708,23 +720,23 @@ + /* one _could_ circumvent the strlen calls... */ + if(id3.title.fill && id3.artist.fill && strlen(id3.title.p) <= 30 && strlen(id3.title.p) <= 30) + { +- fprintf(stderr,"Title: %-30s Artist: %s\n",id3.title.p,id3.artist.p); ++ fprintf(stderr,"Title: %-30s Artist: %s\n",ctitle?ctitle:id3.title.p,cartist?cartist:id3.artist.p); + } + else + { +- if(id3.title.fill) fprintf(stderr,"Title: %s\n", id3.title.p); +- if(id3.artist.fill) fprintf(stderr,"Artist: %s\n", id3.artist.p); ++ if(id3.title.fill) fprintf(stderr,"Title: %s\n", ctitle?ctitle:id3.title.p); ++ if(id3.artist.fill) fprintf(stderr,"Artist: %s\n", cartist?cartist:id3.artist.p); + } + if (id3.comment.fill && id3.album.fill && strlen(id3.comment.p) <= 30 && strlen(id3.album.p) <= 30) + { +- fprintf(stderr,"Comment: %-30s Album: %s\n",id3.comment.p,id3.album.p); ++ fprintf(stderr,"Comment: %-30s Album: %s\n",ccomment?ccomment:id3.comment.p,calbum?calbum:id3.album.p); + } + else + { + if (id3.comment.fill) +- fprintf(stderr,"Comment: %s\n", id3.comment.p); ++ fprintf(stderr,"Comment: %s\n", ccomment?ccomment:id3.comment.p); + if (id3.album.fill) +- fprintf(stderr,"Album: %s\n", id3.album.p); ++ fprintf(stderr,"Album: %s\n", calbum?calbum:id3.album.p); + } + if (id3.year.fill && id3.genre.fill && strlen(id3.year.p) <= 30 && strlen(id3.genre.p) <= 30) + { +@@ -738,6 +750,11 @@ + fprintf(stderr,"Genre: %s\n", id3.genre.p); + } + } ++ ++ if (ctitle) free(ctitle); ++ if (cartist) free(cartist); ++ if (calbum) free(calbum); ++ if (ccomment) free(ccomment); + } + + /* +diff -dPNur mpg123-0.65/src/Makefile.am mpg123-0.65-new/src/Makefile.am +--- mpg123-0.65/src/Makefile.am 2007-02-07 10:24:33.000000000 +0100 ++++ mpg123-0.65-new/src/Makefile.am 2007-04-15 13:38:44.000000000 +0200 +@@ -4,8 +4,8 @@ + ## see COPYING and AUTHORS files in distribution or http://mpg123.de + ## initially written by Nicholas J. Humfrey + +-AM_CFLAGS = @AUDIO_CFLAGS@ +-AM_LDFLAGS = @AUDIO_LIBS@ ++AM_CFLAGS = @AUDIO_CFLAGS@ @LIBRCC_INCLUDES@ ++AM_LDFLAGS = @AUDIO_LIBS@ @LIBRCC_LIBS@ + mpg123_LDADD = @AUDIO_OBJ@ @CPU_TYPE_LIB@ + mpg123_DEPENDENCIES = @AUDIO_OBJ@ @CPU_TYPE_LIB@ + +@@ -14,6 +14,8 @@ + + bin_PROGRAMS = mpg123 + mpg123_SOURCES = \ ++ rccpatch.c \ ++ rccpatch.h \ + audio.c \ + audio.h \ + buffer.c \ +diff -dPNur mpg123-0.65/src/mpg123.c mpg123-0.65-new/src/mpg123.c +--- mpg123-0.65/src/mpg123.c 2007-02-07 10:24:33.000000000 +0100 ++++ mpg123-0.65-new/src/mpg123.c 2007-04-15 13:30:42.000000000 +0200 +@@ -35,6 +35,7 @@ + #include "layer3.h" + #endif + #include "playlist.h" ++#include "rccpatch.h" + #include "id3.h" + #include "icy.h" + +@@ -814,15 +815,18 @@ + + if(param.remote) { + int ret; ++ rccPatchInit(); + init_id3(); + init_icy(); + ret = control_generic(&fr); + clear_icy(); + exit_id3(); ++ rccPatchFree(); + safe_exit(ret); + } + #endif + ++ rccPatchInit(); + init_icy(); + init_id3(); /* prepare id3 memory */ + while ((fname = get_next_file())) { +@@ -851,7 +855,7 @@ + } + } + #endif +- ++ + } + + #if !defined(WIN32) && !defined(GENERIC) +@@ -1031,6 +1035,7 @@ + } /* end of loop over input files */ + clear_icy(); + exit_id3(); /* free id3 memory */ ++ rccPatchFree(); + #ifndef NOXFERMEM + if (param.usebuffer) { + buffer_end(); +diff -dPNur mpg123-0.65/src/rccpatch.c mpg123-0.65-new/src/rccpatch.c +--- mpg123-0.65/src/rccpatch.c 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-0.65-new/src/rccpatch.c 2007-04-15 13:13:09.000000000 +0200 +@@ -0,0 +1,40 @@ ++#include <librcc.h> ++ ++#define ID3_CLASS 0 ++#define OUT_CLASS 1 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, NULL, NULL, "Output Encoding", 0 }, ++ { NULL } ++}; ++ ++static int rcc_initialized = 0; ++ ++void rccPatchFree() { ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++} ++ ++void rccPatchInit() { ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++} ++ ++static void rccPatchTryInit() { ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++} ++ ++char *rccPatchRecode(const char *str) { ++ char *res; ++ rccPatchTryInit(); ++ return rccRecode(NULL, ID3_CLASS, OUT_CLASS, str); ++} +diff -dPNur mpg123-0.65/src/rccpatch.h mpg123-0.65-new/src/rccpatch.h +--- mpg123-0.65/src/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ mpg123-0.65-new/src/rccpatch.h 2007-04-15 13:13:09.000000000 +0200 +@@ -0,0 +1,4 @@ ++void rccPatchFree(); ++void rccPatchInit(); ++char *rccPatchRecode(const char *str); ++ diff --git a/patches/p7zip/README b/patches/p7zip/README new file mode 100644 index 0000000..fe8ae08 --- /dev/null +++ b/patches/p7zip/README @@ -0,0 +1,13 @@ +Difference between 'rusxmms' and 'rusxmms-full' patches is following. The full patche besides makefile.machine fixes all +other architecure-oss specific make files. The 'rusxmms' patch does not. However, you could execute following commands +to have all makefiles adjusted. + +find . -maxdepth 1 -name "makefile.linux*" -print0 | xargs -0 sed -i -e "s/LOCAL_LIBS=-lpthread/LOCAL_LIBS=-lpthread -lrcc/" +find . -maxdepth 1 -name "makefile.machine" -print0 | xargs -0 sed -i -e "s/LOCAL_LIBS=-lpthread/LOCAL_LIBS=-lpthread -lrcc/" + + +Configuration +============= + - The patch uses "zip" configuration of RCC. This means settings could be + altered using "rcc-gtk2-config zip". + - ZIP OEM / Output - encodings are important for patch. diff --git a/patches/p7zip/p7zip_4.44-ds-rusxmms-full.patch b/patches/p7zip/p7zip_4.44-ds-rusxmms-full.patch new file mode 100644 index 0000000..98e7855 --- /dev/null +++ b/patches/p7zip/p7zip_4.44-ds-rusxmms-full.patch @@ -0,0 +1,314 @@ +diff -dPNur p7zip_4.44-old/C/rccrecode.c p7zip_4.44/C/rccrecode.c +--- p7zip_4.44-old/C/rccrecode.c 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.44/C/rccrecode.c 2007-04-14 19:47:03.000000000 +0200 +@@ -0,0 +1,69 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip_4.44-old/C/rccrecode.h p7zip_4.44/C/rccrecode.h +--- p7zip_4.44-old/C/rccrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.44/C/rccrecode.h 2007-04-14 19:34:20.000000000 +0200 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip_4.44-old/CPP/7zip/Archive/Zip/makefile p7zip_4.44/CPP/7zip/Archive/Zip/makefile +--- p7zip_4.44-old/CPP/7zip/Archive/Zip/makefile 2007-01-23 21:29:41.000000000 +0100 ++++ p7zip_4.44/CPP/7zip/Archive/Zip/makefile 2007-04-14 18:36:44.000000000 +0200 +@@ -13,6 +13,7 @@ + LIBS=$(LOCAL_LIBS_DLL) + + OBJS = \ ++../../../../C/rccrecode.o \ + ../../../Common/MyWindows.o \ + ../../../Common/Vector.o\ + ../../../Common/Alloc.o\ +diff -dPNur p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip_4.44/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipIn.cpp 2007-01-20 18:06:58.000000000 +0100 ++++ p7zip_4.44/CPP/7zip/Archive/Zip/ZipIn.cpp 2007-04-14 19:34:59.000000000 +0200 +@@ -9,11 +9,22 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { ++ ++CInArchive::CInArchive() { ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() { ++ rcc_free(rccctx); ++} ++ + + // static const char kEndOfString = '\0'; +- ++ + bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit) + { + m_Stream = inStream; +@@ -179,10 +190,18 @@ + + AString CInArchive::ReadFileName(UInt32 nameSize) + { ++ char *rccrec; + if (nameSize == 0) + return AString(); + SafeReadBytes(m_NameBuffer.GetBuffer(nameSize), nameSize); + m_NameBuffer.ReleaseBuffer(nameSize); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)m_NameBuffer, 0); ++ if (rccrec) { ++ m_NameBuffer = rccrec; ++ free(rccrec); ++ } ++ + return m_NameBuffer; + } + +diff -dPNur p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipIn.h p7zip_4.44/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipIn.h 2007-01-20 18:06:28.000000000 +0100 ++++ p7zip_4.44/CPP/7zip/Archive/Zip/ZipIn.h 2007-04-14 19:05:31.000000000 +0200 +@@ -104,6 +104,10 @@ + bool SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); ++ ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); + }; + + }} +diff -dPNur p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip_4.44/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipOut.cpp 2007-01-20 18:06:57.000000000 +0100 ++++ p7zip_4.44/CPP/7zip/Archive/Zip/ZipOut.cpp 2007-04-14 19:44:44.000000000 +0200 +@@ -8,9 +8,19 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + m_Stream = outStream; +@@ -104,6 +114,8 @@ + + HRESULT COutArchive::WriteLocalHeader(const CLocalItem &item) + { ++ char *rccrec; ++ + m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); + + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; +@@ -124,6 +136,12 @@ + return E_FAIL; + } + WriteUInt16((UInt16)m_ExtraSize); // test it; ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("%u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; +@@ -147,6 +165,8 @@ + + void COutArchive::WriteCentralHeader(const CItem &item) + { ++ char *rccrec; ++ + m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); + + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; +@@ -175,6 +195,13 @@ + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); ++ ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("C: %u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { +diff -dPNur p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipOut.h p7zip_4.44/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip_4.44-old/CPP/7zip/Archive/Zip/ZipOut.h 2007-01-20 18:06:29.000000000 +0100 ++++ p7zip_4.44/CPP/7zip/Archive/Zip/ZipOut.h 2007-04-14 19:10:12.000000000 +0200 +@@ -44,6 +44,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ + }; + + }} +diff -dPNur p7zip_4.44-old/CPP/7zip/Bundles/Alone/makefile p7zip_4.44/CPP/7zip/Bundles/Alone/makefile +--- p7zip_4.44-old/CPP/7zip/Bundles/Alone/makefile 2007-01-23 21:29:43.000000000 +0100 ++++ p7zip_4.44/CPP/7zip/Bundles/Alone/makefile 2007-04-14 18:52:31.000000000 +0200 +@@ -41,6 +41,7 @@ + $(MY_HOME)/mySplitCommandLine.o + + OBJS=\ ++../../../../C/rccrecode.o \ + ../../../Common/MyWindows.o \ + 7zAES.o \ + 7zCompressionMode.o \ +diff -dPNur p7zip_4.44-old/makefile.linux_amd64 p7zip_4.44/makefile.linux_amd64 +--- p7zip_4.44-old/makefile.linux_amd64 2007-04-14 15:37:39.000000000 +0200 ++++ p7zip_4.44/makefile.linux_amd64 2007-04-14 18:50:13.000000000 +0200 +@@ -11,6 +11,6 @@ + CC=x86_64-pc-linux-gnu-gcc $(ALLFLAGS) + LINK_SHARED=-shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + +diff -dPNur p7zip_4.44-old/makefile.linux_gcc_2.95_no_need_for_libstdc p7zip_4.44/makefile.linux_gcc_2.95_no_need_for_libstdc +--- p7zip_4.44-old/makefile.linux_gcc_2.95_no_need_for_libstdc 2007-04-14 15:37:39.000000000 +0200 ++++ p7zip_4.44/makefile.linux_gcc_2.95_no_need_for_libstdc 2007-04-14 18:51:02.000000000 +0200 +@@ -10,6 +10,6 @@ + CC=x86_64-pc-linux-gnu-gcc $(ALLFLAGS) + LINK_SHARED=-shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + +diff -dPNur p7zip_4.44-old/makefile.linux_x86_ppc_alpha p7zip_4.44/makefile.linux_x86_ppc_alpha +--- p7zip_4.44-old/makefile.linux_x86_ppc_alpha 2007-04-14 15:37:39.000000000 +0200 ++++ p7zip_4.44/makefile.linux_x86_ppc_alpha 2007-04-14 18:51:15.000000000 +0200 +@@ -14,6 +14,6 @@ + CC=x86_64-pc-linux-gnu-gcc $(ALLFLAGS) + LINK_SHARED=-shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + +diff -dPNur p7zip_4.44-old/makefile.linux_x86_ppc_alpha__gcc_4.X p7zip_4.44/makefile.linux_x86_ppc_alpha__gcc_4.X +--- p7zip_4.44-old/makefile.linux_x86_ppc_alpha__gcc_4.X 2007-04-14 15:37:39.000000000 +0200 ++++ p7zip_4.44/makefile.linux_x86_ppc_alpha__gcc_4.X 2007-04-14 18:51:19.000000000 +0200 +@@ -14,6 +14,6 @@ + CC=x86_64-pc-linux-gnu-gcc $(ALLFLAGS) + LINK_SHARED=-shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + +diff -dPNur p7zip_4.44-old/makefile.machine p7zip_4.44/makefile.machine +--- p7zip_4.44-old/makefile.machine 2007-04-14 15:37:39.000000000 +0200 ++++ p7zip_4.44/makefile.machine 2007-04-14 18:49:24.000000000 +0200 +@@ -11,6 +11,6 @@ + CC=x86_64-pc-linux-gnu-gcc $(ALLFLAGS) + LINK_SHARED=-shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + diff --git a/patches/p7zip/p7zip_4.57-ds-rusxmms-full.patch b/patches/p7zip/p7zip_4.57-ds-rusxmms-full.patch new file mode 100644 index 0000000..24fa504 --- /dev/null +++ b/patches/p7zip/p7zip_4.57-ds-rusxmms-full.patch @@ -0,0 +1,419 @@ +diff -dPNur p7zip_4.57/C/rccrecode.c p7zip_4.57-new/C/rccrecode.c +--- p7zip_4.57/C/rccrecode.c 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.57-new/C/rccrecode.c 2008-04-11 22:02:20.000000000 +0200 +@@ -0,0 +1,71 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "zip"); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ if (ctx) rccLoad(ctx, "zip"); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip_4.57/C/rccrecode.h p7zip_4.57-new/C/rccrecode.h +--- p7zip_4.57/C/rccrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.57-new/C/rccrecode.h 2008-04-11 22:02:20.000000000 +0200 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.cpp 2007-12-08 11:19:00.000000000 +0100 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.cpp 2008-04-11 22:02:20.000000000 +0200 +@@ -9,11 +9,22 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { ++ ++CInArchive::CInArchive() { ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() { ++ rcc_free(rccctx); ++} ++ + + // static const char kEndOfString = '\0'; +- ++ + bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit) + { + m_Stream = inStream; +@@ -196,10 +207,18 @@ + + AString CInArchive::ReadFileName(UInt32 nameSize) + { ++ char *rccrec; + if (nameSize == 0) + return AString(); + SafeReadBytes(m_NameBuffer.GetBuffer(nameSize), nameSize); + m_NameBuffer.ReleaseBuffer(nameSize); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)m_NameBuffer, 0); ++ if (rccrec) { ++ m_NameBuffer = rccrec; ++ free(rccrec); ++ } ++ + return m_NameBuffer; + } + +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.h p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.h 2007-12-08 11:19:00.000000000 +0100 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.h 2008-04-11 22:02:20.000000000 +0200 +@@ -106,6 +106,10 @@ + bool SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); ++ ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); + }; + + }} +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.cpp 2007-06-26 20:06:23.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.cpp 2008-04-11 22:02:20.000000000 +0200 +@@ -7,9 +7,19 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + if (!m_OutBuffer.Create(1 << 16)) +@@ -112,6 +122,7 @@ + { + SeekTo(m_BasePosition); + ++ char *rccrec; + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + + WriteUInt32(NSignature::kLocalFileHeader); +@@ -130,6 +141,12 @@ + throw CSystemException(E_FAIL); + } + WriteUInt16((UInt16)m_ExtraSize); // test it; ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("%u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; +@@ -154,6 +171,7 @@ + + void COutArchive::WriteCentralHeader(const CItem &item) + { ++ char *rccrec; + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; + bool isPack64 = item.PackSize >= 0xFFFFFFFF; + bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; +@@ -180,6 +198,13 @@ + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); ++ ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("C: %u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.h p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.h 2007-06-26 20:06:22.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.h 2008-04-11 22:02:20.000000000 +0200 +@@ -49,6 +49,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ + }; + + }} +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Alone/makefile p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile +--- p7zip_4.57/CPP/7zip/Bundles/Alone/makefile 2007-07-24 20:55:33.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile 2008-04-11 22:02:20.000000000 +0200 +@@ -15,6 +15,7 @@ + LIBS=$(LOCAL_LIBS) + + OBJS=\ ++rccrecode.o \ + myGetTickCount.o \ + wine_date_and_time.o \ + myAddExeFlag.o \ +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Alone/makefile.list p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile.list +--- p7zip_4.57/CPP/7zip/Bundles/Alone/makefile.list 2007-07-24 20:56:10.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile.list 2008-04-11 22:02:20.000000000 +0200 +@@ -196,6 +196,7 @@ + ../../../../C/Compress/Branch/BranchPPC.c \ + ../../../../C/Compress/Branch/BranchSPARC.c \ + ../../../../C/Compress/Branch/BranchX86.c \ ++ ../../../../C/rccrecode.c \ + ../../../../C/7zCrc.c \ + ../../../../C/Sort.c \ + ../../../../C/Threads.c \ +@@ -237,6 +238,8 @@ + $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp + ListFileUtils.o : ../../../Common/ListFileUtils.cpp + $(CXX) $(CFLAGS) ../../../Common/ListFileUtils.cpp ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CFLAGS) ../../../../C/rccrecode.c + MyWindows.o : ../../../Common/MyWindows.cpp + $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp + Random.o : ../../../Common/Random.cpp +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile +--- p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile 2007-08-03 20:16:04.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile 2008-04-11 22:02:20.000000000 +0200 +@@ -14,6 +14,7 @@ + LIBS=$(LOCAL_LIBS_DLL) + + OBJS = \ ++rccrecode.o \ + wine_date_and_time.o \ + myGetTickCount.o \ + CRC.o \ +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile.list p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile.list +--- p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile.list 2007-08-03 20:17:57.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile.list 2008-04-11 22:02:20.000000000 +0200 +@@ -218,6 +218,7 @@ + ../../../../C/Compress/Branch/BranchPPC.c \ + ../../../../C/Compress/Branch/BranchSPARC.c \ + ../../../../C/Compress/Branch/BranchX86.c \ ++ ../../../../C/rccrecode.c \ + ../../../../C/7zCrc.c \ + ../../../../C/Sort.c \ + ../../../../C/Threads.c \ +@@ -237,6 +238,8 @@ + $(CXX) $(CC_SHARED) $(CFLAGS) ../../../Common/ListFileUtils.cpp + MyWindows.o : ../../../Common/MyWindows.cpp + $(CXX) $(CC_SHARED) $(CFLAGS) ../../../Common/MyWindows.cpp ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CC_SHARED) $(CFLAGS) ../../../../C/rccrecode.c + Random.o : ../../../Common/Random.cpp + $(CXX) $(CC_SHARED) $(CFLAGS) ../../../Common/Random.cpp + StdInStream.o : ../../../Common/StdInStream.cpp +diff -dPNur p7zip_4.57/makefile.linux_amd64 p7zip_4.57-new/makefile.linux_amd64 +--- p7zip_4.57/makefile.linux_amd64 2007-06-28 09:32:20.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_amd64 2008-04-11 22:02:45.000000000 +0200 +@@ -12,7 +12,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.57/makefile.linux_amd64_asm p7zip_4.57-new/makefile.linux_amd64_asm +--- p7zip_4.57/makefile.linux_amd64_asm 2007-06-28 09:32:30.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_amd64_asm 2008-04-11 22:02:45.000000000 +0200 +@@ -13,7 +13,7 @@ + LINK_SHARED=-fPIC -shared + ASM=yasm -f elf -m amd64 + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x64 +diff -dPNur p7zip_4.57/makefile.linux_gcc_2.95_no_need_for_libstdc p7zip_4.57-new/makefile.linux_gcc_2.95_no_need_for_libstdc +--- p7zip_4.57/makefile.linux_gcc_2.95_no_need_for_libstdc 2007-06-24 20:49:31.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_gcc_2.95_no_need_for_libstdc 2008-04-11 22:02:45.000000000 +0200 +@@ -11,7 +11,7 @@ + LINK_SHARED=-shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.57/makefile.linux_s390x p7zip_4.57-new/makefile.linux_s390x +--- p7zip_4.57/makefile.linux_s390x 2007-08-07 18:36:01.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_s390x 2008-04-11 22:02:45.000000000 +0200 +@@ -15,7 +15,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.57/makefile.linux_x86_asm_gcc_4.X p7zip_4.57-new/makefile.linux_x86_asm_gcc_4.X +--- p7zip_4.57/makefile.linux_x86_asm_gcc_4.X 2007-08-08 11:15:07.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_x86_asm_gcc_4.X 2008-04-11 22:02:45.000000000 +0200 +@@ -15,7 +15,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.57/makefile.linux_x86_asm_gcc_4.X_fltk p7zip_4.57-new/makefile.linux_x86_asm_gcc_4.X_fltk +--- p7zip_4.57/makefile.linux_x86_asm_gcc_4.X_fltk 2007-08-08 11:15:10.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_x86_asm_gcc_4.X_fltk 2008-04-11 22:02:45.000000000 +0200 +@@ -15,7 +15,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread `fltk-config --ldflags` ++LOCAL_LIBS=-lpthread -lrcc `fltk-config --ldflags` + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.57/makefile.linux_x86_asm_icc p7zip_4.57-new/makefile.linux_x86_asm_icc +--- p7zip_4.57/makefile.linux_x86_asm_icc 2007-08-08 11:15:15.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_x86_asm_icc 2008-04-11 22:02:45.000000000 +0200 +@@ -16,7 +16,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.57/makefile.linux_x86_ppc_alpha p7zip_4.57-new/makefile.linux_x86_ppc_alpha +--- p7zip_4.57/makefile.linux_x86_ppc_alpha 2007-08-08 11:15:18.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_x86_ppc_alpha 2008-04-11 22:02:45.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.57/makefile.linux_x86_ppc_alpha_gcc_4.X p7zip_4.57-new/makefile.linux_x86_ppc_alpha_gcc_4.X +--- p7zip_4.57/makefile.linux_x86_ppc_alpha_gcc_4.X 2007-08-08 11:15:20.000000000 +0200 ++++ p7zip_4.57-new/makefile.linux_x86_ppc_alpha_gcc_4.X 2008-04-11 22:02:45.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.57/makefile.machine p7zip_4.57-new/makefile.machine +--- p7zip_4.57/makefile.machine 2007-12-15 18:19:48.000000000 +0100 ++++ p7zip_4.57-new/makefile.machine 2008-04-11 22:02:20.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) diff --git a/patches/p7zip/p7zip_4.57-ds-rusxmms.patch b/patches/p7zip/p7zip_4.57-ds-rusxmms.patch new file mode 100644 index 0000000..0913c13 --- /dev/null +++ b/patches/p7zip/p7zip_4.57-ds-rusxmms.patch @@ -0,0 +1,336 @@ +diff -dPNur p7zip_4.57/C/rccrecode.c p7zip_4.57-new/C/rccrecode.c +--- p7zip_4.57/C/rccrecode.c 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.57-new/C/rccrecode.c 2008-04-11 20:23:42.000000000 +0200 +@@ -0,0 +1,71 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "zip"); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ if (ctx) rccLoad(ctx, "zip"); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip_4.57/C/rccrecode.h p7zip_4.57-new/C/rccrecode.h +--- p7zip_4.57/C/rccrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.57-new/C/rccrecode.h 2008-04-11 20:23:42.000000000 +0200 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.cpp 2007-12-08 11:19:00.000000000 +0100 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.cpp 2008-04-11 20:23:42.000000000 +0200 +@@ -9,11 +9,22 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { ++ ++CInArchive::CInArchive() { ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() { ++ rcc_free(rccctx); ++} ++ + + // static const char kEndOfString = '\0'; +- ++ + bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit) + { + m_Stream = inStream; +@@ -196,10 +207,18 @@ + + AString CInArchive::ReadFileName(UInt32 nameSize) + { ++ char *rccrec; + if (nameSize == 0) + return AString(); + SafeReadBytes(m_NameBuffer.GetBuffer(nameSize), nameSize); + m_NameBuffer.ReleaseBuffer(nameSize); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)m_NameBuffer, 0); ++ if (rccrec) { ++ m_NameBuffer = rccrec; ++ free(rccrec); ++ } ++ + return m_NameBuffer; + } + +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.h p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipIn.h 2007-12-08 11:19:00.000000000 +0100 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipIn.h 2008-04-11 20:23:42.000000000 +0200 +@@ -106,6 +106,10 @@ + bool SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); ++ ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); + }; + + }} +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.cpp 2007-06-26 20:06:23.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.cpp 2008-04-11 20:23:42.000000000 +0200 +@@ -7,9 +7,19 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + if (!m_OutBuffer.Create(1 << 16)) +@@ -112,6 +122,7 @@ + { + SeekTo(m_BasePosition); + ++ char *rccrec; + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + + WriteUInt32(NSignature::kLocalFileHeader); +@@ -130,6 +141,12 @@ + throw CSystemException(E_FAIL); + } + WriteUInt16((UInt16)m_ExtraSize); // test it; ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("%u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; +@@ -154,6 +171,7 @@ + + void COutArchive::WriteCentralHeader(const CItem &item) + { ++ char *rccrec; + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; + bool isPack64 = item.PackSize >= 0xFFFFFFFF; + bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; +@@ -180,6 +198,13 @@ + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); ++ ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("C: %u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { +diff -dPNur p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.h p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip_4.57/CPP/7zip/Archive/Zip/ZipOut.h 2007-06-26 20:06:22.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Archive/Zip/ZipOut.h 2008-04-11 20:23:42.000000000 +0200 +@@ -49,6 +49,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ + }; + + }} +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Alone/makefile p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile +--- p7zip_4.57/CPP/7zip/Bundles/Alone/makefile 2007-07-24 20:55:33.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile 2008-04-11 20:23:42.000000000 +0200 +@@ -15,6 +15,7 @@ + LIBS=$(LOCAL_LIBS) + + OBJS=\ ++rccrecode.o \ + myGetTickCount.o \ + wine_date_and_time.o \ + myAddExeFlag.o \ +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Alone/makefile.list p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile.list +--- p7zip_4.57/CPP/7zip/Bundles/Alone/makefile.list 2007-07-24 20:56:10.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Alone/makefile.list 2008-04-11 20:23:42.000000000 +0200 +@@ -196,6 +196,7 @@ + ../../../../C/Compress/Branch/BranchPPC.c \ + ../../../../C/Compress/Branch/BranchSPARC.c \ + ../../../../C/Compress/Branch/BranchX86.c \ ++ ../../../../C/rccrecode.c \ + ../../../../C/7zCrc.c \ + ../../../../C/Sort.c \ + ../../../../C/Threads.c \ +@@ -237,6 +238,8 @@ + $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp + ListFileUtils.o : ../../../Common/ListFileUtils.cpp + $(CXX) $(CFLAGS) ../../../Common/ListFileUtils.cpp ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CFLAGS) ../../../../C/rccrecode.c + MyWindows.o : ../../../Common/MyWindows.cpp + $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp + Random.o : ../../../Common/Random.cpp +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile +--- p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile 2007-08-03 20:16:04.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile 2008-04-11 20:30:53.000000000 +0200 +@@ -14,6 +14,7 @@ + LIBS=$(LOCAL_LIBS_DLL) + + OBJS = \ ++rccrecode.o \ + wine_date_and_time.o \ + myGetTickCount.o \ + CRC.o \ +diff -dPNur p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile.list p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile.list +--- p7zip_4.57/CPP/7zip/Bundles/Format7zFree/makefile.list 2007-08-03 20:17:57.000000000 +0200 ++++ p7zip_4.57-new/CPP/7zip/Bundles/Format7zFree/makefile.list 2008-04-11 20:32:11.000000000 +0200 +@@ -218,6 +218,7 @@ + ../../../../C/Compress/Branch/BranchPPC.c \ + ../../../../C/Compress/Branch/BranchSPARC.c \ + ../../../../C/Compress/Branch/BranchX86.c \ ++ ../../../../C/rccrecode.c \ + ../../../../C/7zCrc.c \ + ../../../../C/Sort.c \ + ../../../../C/Threads.c \ +@@ -237,6 +238,8 @@ + $(CXX) $(CC_SHARED) $(CFLAGS) ../../../Common/ListFileUtils.cpp + MyWindows.o : ../../../Common/MyWindows.cpp + $(CXX) $(CC_SHARED) $(CFLAGS) ../../../Common/MyWindows.cpp ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CC_SHARED) $(CFLAGS) ../../../../C/rccrecode.c + Random.o : ../../../Common/Random.cpp + $(CXX) $(CC_SHARED) $(CFLAGS) ../../../Common/Random.cpp + StdInStream.o : ../../../Common/StdInStream.cpp +diff -dPNur p7zip_4.57/makefile.machine p7zip_4.57-new/makefile.machine +--- p7zip_4.57/makefile.machine 2007-12-15 18:19:48.000000000 +0100 ++++ p7zip_4.57-new/makefile.machine 2008-04-11 20:23:42.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.57/makefile.machine.orig p7zip_4.57-new/makefile.machine.orig +--- p7zip_4.57/makefile.machine.orig 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.57-new/makefile.machine.orig 2007-12-15 18:19:48.000000000 +0100 +@@ -0,0 +1,21 @@ ++# ++# makefile for Linux (x86, PPC, alpha ...) ++# ++ ++OPTFLAGS=-O ++ ++ALLFLAGS=${OPTFLAGS} -s \ ++ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ ++ -DNDEBUG -D_REENTRANT -DENV_UNIX \ ++ $(LOCAL_FLAGS) ++ ++CXX=g++ $(ALLFLAGS) ++CC=gcc $(ALLFLAGS) ++CC_SHARED=-fPIC ++LINK_SHARED=-fPIC -shared ++ ++LOCAL_LIBS=-lpthread ++LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl ++ ++OBJ_CRC32=$(OBJ_CRC32_C) ++ diff --git a/patches/p7zip/p7zip_4.65-ds-rusxmms-full.patch b/patches/p7zip/p7zip_4.65-ds-rusxmms-full.patch new file mode 100644 index 0000000..a7ab04e --- /dev/null +++ b/patches/p7zip/p7zip_4.65-ds-rusxmms-full.patch @@ -0,0 +1,425 @@ +diff -dPNur p7zip_4.65/C/rccrecode.c p7zip_4.65-new/C/rccrecode.c +--- p7zip_4.65/C/rccrecode.c 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.65-new/C/rccrecode.c 2009-06-14 02:44:19.000000000 +0200 +@@ -0,0 +1,71 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "zip"); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ if (ctx) rccLoad(ctx, "zip"); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip_4.65/C/rccrecode.h p7zip_4.65-new/C/rccrecode.h +--- p7zip_4.65/C/rccrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.65-new/C/rccrecode.h 2009-06-14 02:44:19.000000000 +0200 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.cpp 2008-11-28 23:03:44.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.cpp 2009-06-14 02:47:28.000000000 +0200 +@@ -9,6 +9,8 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + extern "C" + { + #include "../../../../C/CpuArch.h" +@@ -23,6 +25,14 @@ + + // static const char kEndOfString = '\0'; + ++CInArchive::CInArchive() { ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() { ++ rcc_free(rccctx); ++} ++ + HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) + { + Close(); +@@ -198,12 +208,21 @@ + + AString CInArchive::ReadFileName(UInt32 nameSize) + { ++ char *rccrec; ++ + if (nameSize == 0) + return AString(); + char *p = m_NameBuffer.GetBuffer(nameSize); + SafeReadBytes(p, nameSize); + p[nameSize] = 0; + m_NameBuffer.ReleaseBuffer(); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)m_NameBuffer, 0); ++ if (rccrec) { ++ m_NameBuffer = rccrec; ++ free(rccrec); ++ } ++ + return m_NameBuffer; + } + +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.h p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.h 2008-08-14 11:11:13.000000000 +0200 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.h 2009-06-14 02:48:32.000000000 +0200 +@@ -108,6 +108,10 @@ + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); + ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); ++ + bool IsOpen() const { return m_Stream != NULL; } + }; + +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.cpp 2008-08-14 11:11:26.000000000 +0200 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.cpp 2009-06-14 02:44:19.000000000 +0200 +@@ -7,9 +7,19 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + if (!m_OutBuffer.Create(1 << 16)) +@@ -112,6 +122,7 @@ + { + SeekTo(m_BasePosition); + ++ char *rccrec; + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + + WriteUInt32(NSignature::kLocalFileHeader); +@@ -130,6 +141,12 @@ + throw CSystemException(E_FAIL); + } + WriteUInt16((UInt16)m_ExtraSize); // test it; ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("%u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; +@@ -154,6 +171,7 @@ + + void COutArchive::WriteCentralHeader(const CItem &item) + { ++ char *rccrec; + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; + bool isPack64 = item.PackSize >= 0xFFFFFFFF; + bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; +@@ -181,6 +199,13 @@ + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); ++ ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("C: %u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.h p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.h 2008-08-14 11:11:13.000000000 +0200 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.h 2009-06-14 02:44:19.000000000 +0200 +@@ -49,6 +49,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ + }; + + }} +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Alone/makefile p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile +--- p7zip_4.65/CPP/7zip/Bundles/Alone/makefile 2009-02-07 19:39:04.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile 2009-06-14 02:44:19.000000000 +0200 +@@ -250,6 +250,7 @@ + Sha256.o + + OBJS=\ ++rccrecode.o \ + myGetTickCount.o \ + wine_date_and_time.o \ + myAddExeFlag.o \ +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Alone/makefile.list p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile.list +--- p7zip_4.65/CPP/7zip/Bundles/Alone/makefile.list 2009-02-09 21:04:57.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile.list 2009-06-14 02:51:45.000000000 +0200 +@@ -204,6 +204,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/Bra.c \ + ../../../../C/Bra86.c \ + ../../../../C/BraIA64.c \ +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile +--- p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile 2009-02-09 21:47:24.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile 2009-06-14 03:00:06.000000000 +0200 +@@ -296,6 +296,7 @@ + Sha256.o \ + + OBJS = \ ++ rccrecode.o \ + wine_date_and_time.o \ + myGetTickCount.o \ + $(COMMON_OBJS) \ +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile.list p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile.list +--- p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-02-09 21:04:32.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-06-14 03:00:39.000000000 +0200 +@@ -235,6 +235,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/Bra.c \ + ../../../../C/Bra86.c \ + ../../../../C/BraIA64.c \ +diff -dPNur p7zip_4.65/makefile.linux_amd64 p7zip_4.65-new/makefile.linux_amd64 +--- p7zip_4.65/makefile.linux_amd64 2007-06-28 09:32:20.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_amd64 2009-06-14 05:08:19.000000000 +0200 +@@ -12,7 +12,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.65/makefile.linux_amd64_asm p7zip_4.65-new/makefile.linux_amd64_asm +--- p7zip_4.65/makefile.linux_amd64_asm 2007-06-28 09:32:30.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_amd64_asm 2009-06-14 05:08:19.000000000 +0200 +@@ -13,7 +13,7 @@ + LINK_SHARED=-fPIC -shared + ASM=yasm -f elf -m amd64 + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x64 +diff -dPNur p7zip_4.65/makefile.linux_amd64_asm_icc p7zip_4.65-new/makefile.linux_amd64_asm_icc +--- p7zip_4.65/makefile.linux_amd64_asm_icc 2009-02-09 22:12:36.000000000 +0100 ++++ p7zip_4.65-new/makefile.linux_amd64_asm_icc 2009-06-14 05:08:19.000000000 +0200 +@@ -16,7 +16,7 @@ + LINK_SHARED=-fPIC -shared + ASM=yasm -f elf -m amd64 + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x64 +diff -dPNur p7zip_4.65/makefile.linux_gcc_2.95_no_need_for_libstdc p7zip_4.65-new/makefile.linux_gcc_2.95_no_need_for_libstdc +--- p7zip_4.65/makefile.linux_gcc_2.95_no_need_for_libstdc 2007-06-24 20:49:31.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_gcc_2.95_no_need_for_libstdc 2009-06-14 05:08:19.000000000 +0200 +@@ -11,7 +11,7 @@ + LINK_SHARED=-shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.65/makefile.linux_s390x p7zip_4.65-new/makefile.linux_s390x +--- p7zip_4.65/makefile.linux_s390x 2007-08-07 18:36:01.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_s390x 2009-06-14 05:08:19.000000000 +0200 +@@ -15,7 +15,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.65/makefile.linux_x86_asm_gcc_4.X p7zip_4.65-new/makefile.linux_x86_asm_gcc_4.X +--- p7zip_4.65/makefile.linux_x86_asm_gcc_4.X 2007-08-08 11:15:07.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_x86_asm_gcc_4.X 2009-06-14 05:08:19.000000000 +0200 +@@ -15,7 +15,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.65/makefile.linux_x86_asm_gcc_4.X_fltk p7zip_4.65-new/makefile.linux_x86_asm_gcc_4.X_fltk +--- p7zip_4.65/makefile.linux_x86_asm_gcc_4.X_fltk 2007-08-08 11:15:10.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_x86_asm_gcc_4.X_fltk 2009-06-14 05:08:19.000000000 +0200 +@@ -15,7 +15,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread `fltk-config --ldflags` ++LOCAL_LIBS=-lpthread -lrcc `fltk-config --ldflags` + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.65/makefile.linux_x86_asm_icc p7zip_4.65-new/makefile.linux_x86_asm_icc +--- p7zip_4.65/makefile.linux_x86_asm_icc 2007-08-08 11:15:15.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_x86_asm_icc 2009-06-14 05:08:19.000000000 +0200 +@@ -16,7 +16,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip_4.65/makefile.linux_x86_ppc_alpha p7zip_4.65-new/makefile.linux_x86_ppc_alpha +--- p7zip_4.65/makefile.linux_x86_ppc_alpha 2007-08-08 11:15:18.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_x86_ppc_alpha 2009-06-14 05:08:19.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.65/makefile.linux_x86_ppc_alpha_gcc_4.X p7zip_4.65-new/makefile.linux_x86_ppc_alpha_gcc_4.X +--- p7zip_4.65/makefile.linux_x86_ppc_alpha_gcc_4.X 2007-08-08 11:15:20.000000000 +0200 ++++ p7zip_4.65-new/makefile.linux_x86_ppc_alpha_gcc_4.X 2009-06-14 05:08:19.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.65/makefile.machine p7zip_4.65-new/makefile.machine +--- p7zip_4.65/makefile.machine 2009-02-14 18:19:09.000000000 +0100 ++++ p7zip_4.65-new/makefile.machine 2009-06-14 02:44:19.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.65/makefile.rules p7zip_4.65-new/makefile.rules +--- p7zip_4.65/makefile.rules 2009-02-09 21:03:16.000000000 +0100 ++++ p7zip_4.65-new/makefile.rules 2009-06-14 02:52:48.000000000 +0200 +@@ -558,3 +558,5 @@ + 7zCrcT8.o : ../../../../C/7zCrcT8.c + $(CC) $(CFLAGS) ../../../../C/7zCrcT8.c + ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CFLAGS) ../../../../C/rccrecode.c diff --git a/patches/p7zip/p7zip_4.65-ds-rusxmms.patch b/patches/p7zip/p7zip_4.65-ds-rusxmms.patch new file mode 100644 index 0000000..7072522 --- /dev/null +++ b/patches/p7zip/p7zip_4.65-ds-rusxmms.patch @@ -0,0 +1,305 @@ +diff -dPNur p7zip_4.65/C/rccrecode.c p7zip_4.65-new/C/rccrecode.c +--- p7zip_4.65/C/rccrecode.c 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.65-new/C/rccrecode.c 2009-06-14 02:44:19.000000000 +0200 +@@ -0,0 +1,71 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "zip"); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ if (ctx) rccLoad(ctx, "zip"); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip_4.65/C/rccrecode.h p7zip_4.65-new/C/rccrecode.h +--- p7zip_4.65/C/rccrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ p7zip_4.65-new/C/rccrecode.h 2009-06-14 02:44:19.000000000 +0200 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.cpp 2008-11-28 23:03:44.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.cpp 2009-06-14 02:47:28.000000000 +0200 +@@ -9,6 +9,8 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + extern "C" + { + #include "../../../../C/CpuArch.h" +@@ -23,6 +25,14 @@ + + // static const char kEndOfString = '\0'; + ++CInArchive::CInArchive() { ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() { ++ rcc_free(rccctx); ++} ++ + HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) + { + Close(); +@@ -198,12 +208,21 @@ + + AString CInArchive::ReadFileName(UInt32 nameSize) + { ++ char *rccrec; ++ + if (nameSize == 0) + return AString(); + char *p = m_NameBuffer.GetBuffer(nameSize); + SafeReadBytes(p, nameSize); + p[nameSize] = 0; + m_NameBuffer.ReleaseBuffer(); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)m_NameBuffer, 0); ++ if (rccrec) { ++ m_NameBuffer = rccrec; ++ free(rccrec); ++ } ++ + return m_NameBuffer; + } + +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.h p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipIn.h 2008-08-14 11:11:13.000000000 +0200 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipIn.h 2009-06-14 02:48:32.000000000 +0200 +@@ -108,6 +108,10 @@ + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); + ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); ++ + bool IsOpen() const { return m_Stream != NULL; } + }; + +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.cpp 2008-08-14 11:11:26.000000000 +0200 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.cpp 2009-06-14 02:44:19.000000000 +0200 +@@ -7,9 +7,19 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + if (!m_OutBuffer.Create(1 << 16)) +@@ -112,6 +122,7 @@ + { + SeekTo(m_BasePosition); + ++ char *rccrec; + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + + WriteUInt32(NSignature::kLocalFileHeader); +@@ -130,6 +141,12 @@ + throw CSystemException(E_FAIL); + } + WriteUInt16((UInt16)m_ExtraSize); // test it; ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("%u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; +@@ -154,6 +171,7 @@ + + void COutArchive::WriteCentralHeader(const CItem &item) + { ++ char *rccrec; + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; + bool isPack64 = item.PackSize >= 0xFFFFFFFF; + bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; +@@ -181,6 +199,13 @@ + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); ++ ++ rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) { ++ printf("C: %u, %s.\n", item.Name.Length(), rccrec); ++ WriteBytes(rccrec, strlen(rccrec)); ++ free(rccrec); ++ } else + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { +diff -dPNur p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.h p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip_4.65/CPP/7zip/Archive/Zip/ZipOut.h 2008-08-14 11:11:13.000000000 +0200 ++++ p7zip_4.65-new/CPP/7zip/Archive/Zip/ZipOut.h 2009-06-14 02:44:19.000000000 +0200 +@@ -49,6 +49,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ + }; + + }} +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Alone/makefile p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile +--- p7zip_4.65/CPP/7zip/Bundles/Alone/makefile 2009-02-07 19:39:04.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile 2009-06-14 02:44:19.000000000 +0200 +@@ -250,6 +250,7 @@ + Sha256.o + + OBJS=\ ++rccrecode.o \ + myGetTickCount.o \ + wine_date_and_time.o \ + myAddExeFlag.o \ +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Alone/makefile.list p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile.list +--- p7zip_4.65/CPP/7zip/Bundles/Alone/makefile.list 2009-02-09 21:04:57.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Alone/makefile.list 2009-06-14 02:51:45.000000000 +0200 +@@ -204,6 +204,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/Bra.c \ + ../../../../C/Bra86.c \ + ../../../../C/BraIA64.c \ +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile +--- p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile 2009-02-09 21:47:24.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile 2009-06-14 03:00:06.000000000 +0200 +@@ -296,6 +296,7 @@ + Sha256.o \ + + OBJS = \ ++ rccrecode.o \ + wine_date_and_time.o \ + myGetTickCount.o \ + $(COMMON_OBJS) \ +diff -dPNur p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile.list p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile.list +--- p7zip_4.65/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-02-09 21:04:32.000000000 +0100 ++++ p7zip_4.65-new/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-06-14 03:00:39.000000000 +0200 +@@ -235,6 +235,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/Bra.c \ + ../../../../C/Bra86.c \ + ../../../../C/BraIA64.c \ +diff -dPNur p7zip_4.65/makefile.machine p7zip_4.65-new/makefile.machine +--- p7zip_4.65/makefile.machine 2009-02-14 18:19:09.000000000 +0100 ++++ p7zip_4.65-new/makefile.machine 2009-06-14 02:44:19.000000000 +0200 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip_4.65/makefile.rules p7zip_4.65-new/makefile.rules +--- p7zip_4.65/makefile.rules 2009-02-09 21:03:16.000000000 +0100 ++++ p7zip_4.65-new/makefile.rules 2009-06-14 02:52:48.000000000 +0200 +@@ -558,3 +558,5 @@ + 7zCrcT8.o : ../../../../C/7zCrcT8.c + $(CC) $(CFLAGS) ../../../../C/7zCrcT8.c + ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CFLAGS) ../../../../C/rccrecode.c diff --git a/patches/p7zip/p7zip_9.04-ds-rusxmms-full.patch b/patches/p7zip/p7zip_9.04-ds-rusxmms-full.patch new file mode 100644 index 0000000..d44a16f --- /dev/null +++ b/patches/p7zip/p7zip_9.04-ds-rusxmms-full.patch @@ -0,0 +1,414 @@ +diff -dPNur p7zip-9.04~dfsg.1/C/rccrecode.c p7zip-9.04~dfsg.1-ds/C/rccrecode.c +--- p7zip-9.04~dfsg.1/C/rccrecode.c 1970-01-01 03:00:00.000000000 +0300 ++++ p7zip-9.04~dfsg.1-ds/C/rccrecode.c 2009-10-28 03:29:23.000000000 +0300 +@@ -0,0 +1,71 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "zip"); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ if (ctx) rccLoad(ctx, "zip"); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip-9.04~dfsg.1/C/rccrecode.h p7zip-9.04~dfsg.1-ds/C/rccrecode.h +--- p7zip-9.04~dfsg.1/C/rccrecode.h 1970-01-01 03:00:00.000000000 +0300 ++++ p7zip-9.04~dfsg.1-ds/C/rccrecode.h 2009-10-28 03:29:23.000000000 +0300 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.cpp 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.cpp 2009-10-28 03:49:06.000000000 +0300 +@@ -9,6 +9,8 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + #include "ZipIn.h" + + #define Get16(p) GetUi16(p) +@@ -17,7 +19,17 @@ + + namespace NArchive { + namespace NZip { +- ++ ++CInArchive::CInArchive() ++{ ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() ++{ ++ rcc_free(rccctx); ++} ++ + HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) + { + _inBufMode = false; +@@ -200,12 +212,20 @@ + + void CInArchive::ReadFileName(UInt32 nameSize, AString &dest) + { ++ char *rccrec; ++ + if (nameSize == 0) + dest.Empty(); + char *p = dest.GetBuffer((int)nameSize); + SafeReadBytes(p, nameSize); + p[nameSize] = 0; + dest.ReleaseBuffer(); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)dest, 0); ++ if (rccrec) { ++ dest = rccrec; ++ free(rccrec); ++ } + } + + void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.h p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.h 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.h 2009-10-28 03:29:23.000000000 +0300 +@@ -114,6 +114,10 @@ + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); + ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); ++ + bool IsOpen() const { return m_Stream != NULL; } + }; + +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.h p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.h 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.h 2009-10-28 05:49:05.000000000 +0300 +@@ -49,6 +49,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ void Recode(CItem &item); + }; + + }} +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipUpdate.cpp p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipUpdate.cpp +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipUpdate.cpp 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipUpdate.cpp 2009-10-28 05:48:04.000000000 +0300 +@@ -87,6 +87,7 @@ + item.NtfsATime = ui.NtfsATime; + item.NtfsCTime = ui.NtfsCTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; ++ archive.Recode(item); + } + else + isDir = item.IsDir(); +@@ -359,9 +360,11 @@ + item.NtfsCTime = ui.NtfsCTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; + ++ archive.Recode(item); ++ + item.CentralExtra.RemoveUnknownSubBlocks(); + item.LocalExtra.RemoveUnknownSubBlocks(); +- ++ + archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField()); + item.LocalHeaderPosition = archive.GetCurrentPosition(); + archive.SeekToPackedDataPosition(); +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile 2009-10-28 03:29:24.000000000 +0300 +@@ -244,6 +244,7 @@ + + + OBJS=\ ++rccrecode.o \ + myGetTickCount.o \ + wine_date_and_time.o \ + myAddExeFlag.o \ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile.list p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile.list +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile.list 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile.list 2009-10-28 03:40:17.000000000 +0300 +@@ -192,6 +192,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/Aes.c \ + ../../../../C/7zStream.c \ + ../../../../C/Bra.c \ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile 2009-10-28 03:29:24.000000000 +0300 +@@ -284,6 +284,7 @@ + + + OBJS = \ ++ rccrecode.o \ + wine_date_and_time.o \ + myGetTickCount.o \ + $(COMMON_OBJS) \ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile.list p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile.list +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-10-28 03:34:02.000000000 +0300 +@@ -218,6 +218,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/7zBuf2.c \ + ../../../../C/7zStream.c \ + ../../../../C/Aes.c \ +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_amd64 p7zip-9.04~dfsg.1-ds/makefile.linux_amd64 +--- p7zip-9.04~dfsg.1/makefile.linux_amd64 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_amd64 2009-10-28 03:54:47.000000000 +0300 +@@ -12,7 +12,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_amd64_asm p7zip-9.04~dfsg.1-ds/makefile.linux_amd64_asm +--- p7zip-9.04~dfsg.1/makefile.linux_amd64_asm 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_amd64_asm 2009-10-28 03:54:47.000000000 +0300 +@@ -13,7 +13,7 @@ + LINK_SHARED=-fPIC -shared + ASM=yasm -f elf -m amd64 + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x64 +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_amd64_asm_icc p7zip-9.04~dfsg.1-ds/makefile.linux_amd64_asm_icc +--- p7zip-9.04~dfsg.1/makefile.linux_amd64_asm_icc 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_amd64_asm_icc 2009-10-28 03:54:47.000000000 +0300 +@@ -16,7 +16,7 @@ + LINK_SHARED=-fPIC -shared + ASM=yasm -f elf -m amd64 + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x64 +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_gcc_2.95_no_need_for_libstdc p7zip-9.04~dfsg.1-ds/makefile.linux_gcc_2.95_no_need_for_libstdc +--- p7zip-9.04~dfsg.1/makefile.linux_gcc_2.95_no_need_for_libstdc 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_gcc_2.95_no_need_for_libstdc 2009-10-28 03:54:47.000000000 +0300 +@@ -11,7 +11,7 @@ + LINK_SHARED=-shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_s390x p7zip-9.04~dfsg.1-ds/makefile.linux_s390x +--- p7zip-9.04~dfsg.1/makefile.linux_s390x 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_s390x 2009-10-28 03:54:47.000000000 +0300 +@@ -15,7 +15,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_x86_asm_gcc_4.X p7zip-9.04~dfsg.1-ds/makefile.linux_x86_asm_gcc_4.X +--- p7zip-9.04~dfsg.1/makefile.linux_x86_asm_gcc_4.X 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_x86_asm_gcc_4.X 2009-10-28 03:54:47.000000000 +0300 +@@ -15,7 +15,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_x86_asm_gcc_4.X_fltk p7zip-9.04~dfsg.1-ds/makefile.linux_x86_asm_gcc_4.X_fltk +--- p7zip-9.04~dfsg.1/makefile.linux_x86_asm_gcc_4.X_fltk 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_x86_asm_gcc_4.X_fltk 2009-10-28 03:54:47.000000000 +0300 +@@ -15,7 +15,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread `fltk-config --ldflags` ++LOCAL_LIBS=-lpthread -lrcc `fltk-config --ldflags` + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_x86_asm_icc p7zip-9.04~dfsg.1-ds/makefile.linux_x86_asm_icc +--- p7zip-9.04~dfsg.1/makefile.linux_x86_asm_icc 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_x86_asm_icc 2009-10-28 03:54:47.000000000 +0300 +@@ -16,7 +16,7 @@ + LINK_SHARED=-fPIC -shared + ASM=nasm -f elf + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + CPU=x86 +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_x86_ppc_alpha p7zip-9.04~dfsg.1-ds/makefile.linux_x86_ppc_alpha +--- p7zip-9.04~dfsg.1/makefile.linux_x86_ppc_alpha 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_x86_ppc_alpha 2009-10-28 03:54:47.000000000 +0300 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip-9.04~dfsg.1/makefile.linux_x86_ppc_alpha_gcc_4.X p7zip-9.04~dfsg.1-ds/makefile.linux_x86_ppc_alpha_gcc_4.X +--- p7zip-9.04~dfsg.1/makefile.linux_x86_ppc_alpha_gcc_4.X 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.linux_x86_ppc_alpha_gcc_4.X 2009-10-28 03:54:47.000000000 +0300 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip-9.04~dfsg.1/makefile.machine p7zip-9.04~dfsg.1-ds/makefile.machine +--- p7zip-9.04~dfsg.1/makefile.machine 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.machine 2009-10-28 03:29:24.000000000 +0300 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip-9.04~dfsg.1/makefile.rules p7zip-9.04~dfsg.1-ds/makefile.rules +--- p7zip-9.04~dfsg.1/makefile.rules 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.rules 2009-10-28 03:29:24.000000000 +0300 +@@ -586,3 +586,5 @@ + 7zCrcT8.o : ../../../../C/7zCrcT8.c + $(CC) $(CFLAGS) ../../../../C/7zCrcT8.c + ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CFLAGS) ../../../../C/rccrecode.c +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.cpp 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.cpp 2009-10-28 05:49:01.000000000 +0300 +@@ -7,9 +7,24 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ ++void COutArchive::Recode(CItem &item) { ++ char *rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) item.Name = rccrec; ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + if (!m_OutBuffer.Create(1 << 16)) diff --git a/patches/p7zip/p7zip_9.04-ds-rusxmms.patch b/patches/p7zip/p7zip_9.04-ds-rusxmms.patch new file mode 100644 index 0000000..7678241 --- /dev/null +++ b/patches/p7zip/p7zip_9.04-ds-rusxmms.patch @@ -0,0 +1,294 @@ +diff -dPNur p7zip-9.04~dfsg.1/C/rccrecode.c p7zip-9.04~dfsg.1-ds/C/rccrecode.c +--- p7zip-9.04~dfsg.1/C/rccrecode.c 1970-01-01 03:00:00.000000000 +0300 ++++ p7zip-9.04~dfsg.1-ds/C/rccrecode.c 2009-10-28 03:29:23.000000000 +0300 +@@ -0,0 +1,71 @@ ++#include <pthread.h> ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define ARC_CLASS 0 ++#define OUT_CLASS 1 ++#define ARCOUT_CLASS 0 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM Encoding", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int initialized = 0; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++void *rcc_init() { ++ rcc_context ctx; ++ ++ pthread_mutex_lock(&mutex); ++ if (!initialized) { ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "zip"); ++ rccInitDb4(NULL, NULL, 0); ++ } ++ initialized++; ++ pthread_mutex_unlock(&mutex); ++ ++ ctx = rccCreateContext(NULL, 0, 0, classes, 0); ++ if (ctx) rccInitDb4(ctx, NULL, 0); ++ if (ctx) rccLoad(ctx, "zip"); ++ ++ return ctx; ++} ++ ++ ++void rcc_free(void *ctx) { ++ if (ctx) rccFreeContext((rcc_context)ctx); ++ ++ pthread_mutex_lock(&mutex); ++ if (initialized == 1) rccFree(); ++ initialized--; ++ pthread_mutex_unlock(&mutex); ++} ++ ++ ++char *rcc_read(void *ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, ARC_CLASS, OUT_CLASS, string, size, NULL); ++} ++ ++char *rcc_write(rcc_context ctx, const char *string, size_t size) { ++ if (!initialized) { ++ rcc_init(); ++ if (!initialized) return NULL; ++ } ++ return rccSizedRecode((rcc_context)ctx, OUT_CLASS, ARCOUT_CLASS, string, size, NULL); ++} +diff -dPNur p7zip-9.04~dfsg.1/C/rccrecode.h p7zip-9.04~dfsg.1-ds/C/rccrecode.h +--- p7zip-9.04~dfsg.1/C/rccrecode.h 1970-01-01 03:00:00.000000000 +0300 ++++ p7zip-9.04~dfsg.1-ds/C/rccrecode.h 2009-10-28 03:29:23.000000000 +0300 +@@ -0,0 +1,17 @@ ++#ifndef _RCC_RECODE_H ++#define _RCC_RECODE_H ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++ void *rcc_init(); ++ void rcc_free(void *ctx); ++ char *rcc_read(void *ctx, const char *string, size_t size); ++ char *rcc_write(void *ctx, const char *string, size_t size); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif /* _RCC_RECODE_H */ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.cpp p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.cpp +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.cpp 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.cpp 2009-10-28 03:49:06.000000000 +0300 +@@ -9,6 +9,8 @@ + #include "../../Common/LimitedStreams.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + #include "ZipIn.h" + + #define Get16(p) GetUi16(p) +@@ -17,7 +19,17 @@ + + namespace NArchive { + namespace NZip { +- ++ ++CInArchive::CInArchive() ++{ ++ rccctx = rcc_init(); ++} ++ ++CInArchive::~CInArchive() ++{ ++ rcc_free(rccctx); ++} ++ + HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) + { + _inBufMode = false; +@@ -200,12 +212,20 @@ + + void CInArchive::ReadFileName(UInt32 nameSize, AString &dest) + { ++ char *rccrec; ++ + if (nameSize == 0) + dest.Empty(); + char *p = dest.GetBuffer((int)nameSize); + SafeReadBytes(p, nameSize); + p[nameSize] = 0; + dest.ReleaseBuffer(); ++ ++ rccrec = rcc_read(rccctx, (LPCSTR)dest, 0); ++ if (rccrec) { ++ dest = rccrec; ++ free(rccrec); ++ } + } + + void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.h p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.h +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipIn.h 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipIn.h 2009-10-28 03:29:23.000000000 +0300 +@@ -114,6 +114,10 @@ + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); + ++ void *rccctx; ++ CInArchive(); ++ ~CInArchive(); ++ + bool IsOpen() const { return m_Stream != NULL; } + }; + +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.h p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.h +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.h 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.h 2009-10-28 05:49:05.000000000 +0300 +@@ -49,6 +49,11 @@ + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); ++ ++ void *rccctx; ++ COutArchive(); ++ ~COutArchive(); ++ void Recode(CItem &item); + }; + + }} +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipUpdate.cpp p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipUpdate.cpp +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipUpdate.cpp 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipUpdate.cpp 2009-10-28 05:48:04.000000000 +0300 +@@ -87,6 +87,7 @@ + item.NtfsATime = ui.NtfsATime; + item.NtfsCTime = ui.NtfsCTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; ++ archive.Recode(item); + } + else + isDir = item.IsDir(); +@@ -359,9 +360,11 @@ + item.NtfsCTime = ui.NtfsCTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; + ++ archive.Recode(item); ++ + item.CentralExtra.RemoveUnknownSubBlocks(); + item.LocalExtra.RemoveUnknownSubBlocks(); +- ++ + archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField()); + item.LocalHeaderPosition = archive.GetCurrentPosition(); + archive.SeekToPackedDataPosition(); +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile 2009-10-28 03:29:24.000000000 +0300 +@@ -244,6 +244,7 @@ + + + OBJS=\ ++rccrecode.o \ + myGetTickCount.o \ + wine_date_and_time.o \ + myAddExeFlag.o \ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile.list p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile.list +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Alone/makefile.list 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Alone/makefile.list 2009-10-28 03:40:17.000000000 +0300 +@@ -192,6 +192,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/Aes.c \ + ../../../../C/7zStream.c \ + ../../../../C/Bra.c \ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile 2009-10-28 03:29:24.000000000 +0300 +@@ -284,6 +284,7 @@ + + + OBJS = \ ++ rccrecode.o \ + wine_date_and_time.o \ + myGetTickCount.o \ + $(COMMON_OBJS) \ +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile.list p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile.list +--- p7zip-9.04~dfsg.1/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Bundles/Format7zFree/makefile.list 2009-10-28 03:34:02.000000000 +0300 +@@ -218,6 +218,7 @@ + ../../Crypto/ZipStrong.cpp + + SRCS_C=\ ++ ../../../../C/rccrecode.c \ + ../../../../C/7zBuf2.c \ + ../../../../C/7zStream.c \ + ../../../../C/Aes.c \ +diff -dPNur p7zip-9.04~dfsg.1/makefile.machine p7zip-9.04~dfsg.1-ds/makefile.machine +--- p7zip-9.04~dfsg.1/makefile.machine 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.machine 2009-10-28 03:29:24.000000000 +0300 +@@ -14,7 +14,7 @@ + CC_SHARED=-fPIC + LINK_SHARED=-fPIC -shared + +-LOCAL_LIBS=-lpthread ++LOCAL_LIBS=-lpthread -lrcc + LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl + + OBJ_CRC32=$(OBJ_CRC32_C) +diff -dPNur p7zip-9.04~dfsg.1/makefile.rules p7zip-9.04~dfsg.1-ds/makefile.rules +--- p7zip-9.04~dfsg.1/makefile.rules 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/makefile.rules 2009-10-28 03:29:24.000000000 +0300 +@@ -586,3 +586,5 @@ + 7zCrcT8.o : ../../../../C/7zCrcT8.c + $(CC) $(CFLAGS) ../../../../C/7zCrcT8.c + ++rccrecode.o : ../../../../C/rccrecode.c ++ $(CC) $(CFLAGS) ../../../../C/rccrecode.c +diff -dPNur p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.cpp p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.cpp +--- p7zip-9.04~dfsg.1/CPP/7zip/Archive/Zip/ZipOut.cpp 2009-06-27 18:18:14.000000000 +0400 ++++ p7zip-9.04~dfsg.1-ds/CPP/7zip/Archive/Zip/ZipOut.cpp 2009-10-28 05:49:01.000000000 +0300 +@@ -7,9 +7,24 @@ + #include "../../Common/OffsetStream.h" + #include "../../Common/StreamUtils.h" + ++#include "../../../../C/rccrecode.h" ++ + namespace NArchive { + namespace NZip { + ++COutArchive::COutArchive() { ++ rccctx = rcc_init(); ++} ++ ++COutArchive::~COutArchive() { ++ rcc_free(rccctx); ++} ++ ++void COutArchive::Recode(CItem &item) { ++ char *rccrec = rcc_write(rccctx, (const char *)item.Name, item.Name.Length()); ++ if (rccrec) item.Name = rccrec; ++} ++ + void COutArchive::Create(IOutStream *outStream) + { + if (!m_OutBuffer.Create(1 << 16)) 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) diff --git a/patches/unzip/README b/patches/unzip/README new file mode 100644 index 0000000..03c08f6 --- /dev/null +++ b/patches/unzip/README @@ -0,0 +1,30 @@ +You can use patch in two modes: + standard: The unzip will be dynamically linked with librcc (In that case + some problems with building OpenOffice from sources may arise) + + lazy: In this case the librcc will be dynamically loaded (with help of + dlopen, dlsym) during execution. + + +Usage +===== +1. Apply patches: unzip-*-ds-rusxmms.patch, unzip-ds-unixenc.patch +2. In the root of `unzip` source tree run either `update_shared` for standard +mode or `update_lazy` for lazy mode. + + +Configuration +============= + - The patch uses "zip" configuration of RCC. This means settings could be + altered using "rcc-gtk2-config zip". + - ZIP OEM / ZIP ISO / Output - encodings are important for patch. + + +Build +===== + On Unix, call following command to get list of possible targets: + make -f unix/Makefile list + and then just build with: + make -f unix/Makefile <target> + for example: + make -f unix/Makefile linux_noasm diff --git a/patches/unzip/unzip-5.52-ds-rusxmms.patch b/patches/unzip/unzip-5.52-ds-rusxmms.patch new file mode 100644 index 0000000..87835f0 --- /dev/null +++ b/patches/unzip/unzip-5.52-ds-rusxmms.patch @@ -0,0 +1,159 @@ +diff -dPNur unzip-5.52/dsrecode.h unzip-5.52-ds/dsrecode.h +--- unzip-5.52/dsrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ unzip-5.52-ds/dsrecode.h 2008-04-11 22:24:24.000000000 +0200 +@@ -0,0 +1,128 @@ ++#include <librcc.h> ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define OEM_CLASS 0 ++#define ISO_CLASS 1 ++#define OUT_CLASS 2 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM_INTERN", 0 }, ++ { "iso", RCC_CLASS_STANDARD, NULL, default_iso, "ISO_INTERN", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL } ++}; ++ ++int initialized = 0; ++ ++#ifdef RCC_LAZY ++#include <dlfcn.h> ++# define RCC_LIBRARY "librcc.so.0" ++int (*rccInit2)(); ++int (*rccFree2)(); ++int (*rccInitDefaultContext2)(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags); ++int (*rccInitDb42)(rcc_context ctx, const char *name, rcc_db4_flags flags); ++char* (*rccSizedRecode2)(rcc_context ctx, rcc_class_id from, rcc_class_id to, const char *buf, size_t len, size_t *rlen); ++int (*rccLoad2)(rcc_context ctx, const char *name); ++ ++ ++static char *rccRecode2(rcc_context ctx, rcc_class_id from, rcc_class_id to, const char *buf) { ++ return rccSizedRecode2(ctx, from, to, buf, 0, NULL); ++} ++ ++void *rcc_handle; ++#else /* RCC_LAZY */ ++#define rccInit2 rccInit ++#define rccFree2 rccFree ++#define rccInitDefaultContext2 rccInitDefaultContext ++#define rccInitDb42 rccInitDb4 ++#define rccRecode2 rccRecode ++#define rccLoad2 rccLoad ++#endif /* RCC_LAZY */ ++ ++static void rccUnzipFree() { ++ if (initialized > 0) { ++ rccFree2(); ++#ifdef RCC_LAZY ++ dlclose(rcc_handle); ++#endif /* RCC_LAZY */ ++ initialized = 0; ++ } ++} ++ ++ ++static int rccUnzipInit() { ++ if (initialized) return 0; ++ ++#ifdef RCC_LAZY ++ if (sizeof(size_t) == 8) { ++ rcc_handle = dlopen("/usr/lib64/" RCC_LIBRARY, RTLD_NOW); ++ if (!rcc_handle) rcc_handle = dlopen("/usr/local/lib64/" RCC_LIBRARY, RTLD_NOW); ++ } else { ++ rcc_handle = dlopen("/usr/lib32/" RCC_LIBRARY, RTLD_NOW); ++ if (!rcc_handle) rcc_handle = dlopen("/usr/local/lib32/" RCC_LIBRARY, RTLD_NOW); ++ } ++ if (!rcc_handle) { ++ rcc_handle = dlopen("/usr/lib/" RCC_LIBRARY, RTLD_NOW); ++ if (!rcc_handle) rcc_handle = dlopen("/usr/local/lib/" RCC_LIBRARY, RTLD_NOW); ++ } ++ if (!rcc_handle) { ++ initialized = -1; ++ return 1; ++ } ++ ++ rccInit2 = dlsym(rcc_handle, "rccInit"); ++ rccFree2 = dlsym(rcc_handle, "rccFree"); ++ rccInitDefaultContext2 = dlsym(rcc_handle, "rccInitDefaultContext"); ++ rccInitDb42 = dlsym(rcc_handle, "rccInitDb4"); ++ rccSizedRecode2 = dlsym(rcc_handle, "rccSizedRecode"); ++ rccLoad2 = dlsym(rcc_handle, "rccLoad"); ++ ++ if ((!rccInit2)||(!rccFree2)||(!rccInitDefaultContext2)||(!rccInitDb42)||(!rccSizedRecode2)||(!rccLoad2)) { ++ dlclose(rcc_handle); ++ initialized = -1; ++ return 1; ++ } ++#endif /* RCC_LAZY */ ++ ++ rccInit2(); ++ rccInitDefaultContext2(NULL, 0, 0, classes, 0); ++ rccLoad2(NULL, "zip"); ++ rccInitDb42(NULL, NULL, 0); ++ atexit(rccUnzipFree); ++ initialized = 1; ++ return 0; ++} ++ ++ ++ ++void _DS_OEM_INTERN(char *string) { ++ char *str; ++ rccUnzipInit(); ++ if (initialized>0) { ++ str = rccRecode2(NULL, OEM_CLASS, OUT_CLASS, string); ++ if (str) { ++ strncpy(string,str,FILNAMSIZ); ++ free(str); ++ } ++ } ++} ++ ++void _DS_ISO_INTERN(char *string) { ++ char *str; ++ rccUnzipInit(); ++ if (initialized>0) { ++ str = rccRecode2(NULL, ISO_CLASS, OUT_CLASS, string); ++ if (str) { ++ strncpy(string,str,FILNAMSIZ); ++ free(str); ++ } ++ } ++} +diff -dPNur unzip-5.52/fileio.c unzip-5.52-ds/fileio.c +--- unzip-5.52/fileio.c 2005-02-27 03:10:12.000000000 +0100 ++++ unzip-5.52-ds/fileio.c 2008-04-11 22:25:31.000000000 +0200 +@@ -78,7 +78,7 @@ + # endif + #endif + #include "ebcdic.h" /* definition/initialization of ebcdic[] */ +- ++#include "dsrecode.h" + + /* + Note: Under Windows, the maximum size of the buffer that can be used +diff -dPNur unzip-5.52/unzpriv.h unzip-5.52-ds/unzpriv.h +--- unzip-5.52/unzpriv.h 2005-02-04 00:26:42.000000000 +0100 ++++ unzip-5.52-ds/unzpriv.h 2008-04-11 22:25:31.000000000 +0200 +@@ -2564,9 +2564,9 @@ + ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \ + (hostnum) == FS_HPFS_ || \ + ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \ +- _OEM_INTERN((string)); \ ++ _DS_OEM_INTERN((string)); \ + } else { \ +- _ISO_INTERN((string)); \ ++ _DS_ISO_INTERN((string)); \ + } + #endif + diff --git a/patches/unzip/unzip-5.52-ds-rusxmms2.patch b/patches/unzip/unzip-5.52-ds-rusxmms2.patch new file mode 100644 index 0000000..6670a10 --- /dev/null +++ b/patches/unzip/unzip-5.52-ds-rusxmms2.patch @@ -0,0 +1,149 @@ +diff -dPNur unzip-5.52/fileio.c unzip-5.52-ds/fileio.c +--- unzip-5.52/fileio.c 2005-02-27 03:10:12.000000000 +0100 ++++ unzip-5.52-ds/fileio.c 2008-04-11 22:25:31.000000000 +0200 +@@ -78,7 +78,7 @@ + # endif + #endif + #include "ebcdic.h" /* definition/initialization of ebcdic[] */ +- ++#include "dsrecode.h" + + /* + Note: Under Windows, the maximum size of the buffer that can be used +diff -dPNur unzip-5.52/unzpriv.h unzip-5.52-ds/unzpriv.h +--- unzip-5.52/unzpriv.h 2005-02-04 00:26:42.000000000 +0100 ++++ unzip-5.52-ds/unzpriv.h 2008-04-11 22:25:31.000000000 +0200 +@@ -2564,9 +2564,9 @@ + ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \ + (hostnum) == FS_HPFS_ || \ + ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \ +- _OEM_INTERN((string)); \ ++ _DS_OEM_INTERN((string)); \ + } else { \ +- _ISO_INTERN((string)); \ ++ _DS_ISO_INTERN((string)); \ + } + #endif + +diff -dPNur unzip-5.52/dsrecode.h unzip-5.52-ds/dsrecode.h +--- unzip-5.52/dsrecode.h 1970-01-01 01:00:00.000000000 +0100 ++++ unzip-5.52-ds/dsrecode.h 2008-04-11 22:24:24.000000000 +0200 +@@ -0,0 +1,118 @@ ++#include "librcc.h" ++ ++static rcc_class_default_charset default_oem[] = { ++ { "ru", "IBM866" }, ++ { NULL, NULL } ++}; ++ ++static rcc_class_default_charset default_iso[] = { ++ { "ru", "CP1251" }, ++ { NULL, NULL } ++}; ++ ++#define OEM_CLASS 0 ++#define ISO_CLASS 1 ++#define OUT_CLASS 2 ++static rcc_class classes[] = { ++ { "oem", RCC_CLASS_STANDARD, NULL, default_oem, "OEM_INTERN", 0 }, ++ { "iso", RCC_CLASS_STANDARD, NULL, default_iso, "ISO_INTERN", 0 }, ++ { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output", 0 }, ++ { NULL } ++}; ++ ++int initialized = 0; ++ ++#ifdef RCC_LAZY ++#include <dlfcn.h> ++# define RCC_LIBRARY "librcc.so.0" ++int (*rccInit2)(); ++int (*rccFree2)(); ++int (*rccInitDefaultContext2)(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags); ++int (*rccInitDb42)(rcc_context ctx, const char *name, rcc_db4_flags flags); ++char* (*rccSizedRecode2)(rcc_context ctx, rcc_class_id from, rcc_class_id to, const char *buf, size_t len, size_t *rlen); ++int (*rccLoad2)(rcc_context ctx, const char *name); ++ ++ ++static char *rccRecode2(rcc_context ctx, rcc_class_id from, rcc_class_id to, const char *buf) { ++ return rccSizedRecode2(ctx, from, to, buf, 0, NULL); ++} ++ ++void *rcc_handle; ++#else /* RCC_LAZY */ ++#define rccInit2 rccInit ++#define rccFree2 rccFree ++#define rccInitDefaultContext2 rccInitDefaultContext ++#define rccInitDb42 rccInitDb4 ++#define rccRecode2 rccRecode ++#define rccLoad2 rccLoad ++#endif /* RCC_LAZY */ ++ ++static void rccUnzipFree() { ++ if (initialized > 0) { ++ rccFree2(); ++#ifdef RCC_LAZY ++ dlclose(rcc_handle); ++#endif /* RCC_LAZY */ ++ initialized = 0; ++ } ++} ++ ++ ++static int rccUnzipInit() { ++ if (initialized) return 0; ++ ++#ifdef RCC_LAZY ++ rcc_handle = dlopen(RCC_LIBRARY, RTLD_NOW); ++ if (!rcc_handle) { ++ initialized = -1; ++ return 1; ++ } ++ ++ rccInit2 = dlsym(rcc_handle, "rccInit"); ++ rccFree2 = dlsym(rcc_handle, "rccFree"); ++ rccInitDefaultContext2 = dlsym(rcc_handle, "rccInitDefaultContext"); ++ rccInitDb42 = dlsym(rcc_handle, "rccInitDb4"); ++ rccSizedRecode2 = dlsym(rcc_handle, "rccSizedRecode"); ++ rccLoad2 = dlsym(rcc_handle, "rccLoad"); ++ ++ if ((!rccInit2)||(!rccFree2)||(!rccInitDefaultContext2)||(!rccInitDb42)||(!rccSizedRecode2)||(!rccLoad2)) { ++ dlclose(rcc_handle); ++ initialized = -1; ++ return 1; ++ } ++#endif /* RCC_LAZY */ ++ ++ rccInit2(); ++ rccInitDefaultContext2(NULL, 0, 0, classes, 0); ++ rccLoad2(NULL, "zip"); ++ rccInitDb42(NULL, NULL, 0); ++ atexit(rccUnzipFree); ++ initialized = 1; ++ return 0; ++} ++ ++ ++ ++void _DS_OEM_INTERN(char *string) { ++ char *str; ++ rccUnzipInit(); ++ if (initialized>0) { ++ str = rccRecode2(NULL, OEM_CLASS, OUT_CLASS, string); ++ if (str) { ++ strncpy(string,str,FILNAMSIZ); ++ free(str); ++ } ++ } ++} ++ ++void _DS_ISO_INTERN(char *string) { ++ char *str; ++ rccUnzipInit(); ++ if (initialized>0) { ++ str = rccRecode2(NULL, ISO_CLASS, OUT_CLASS, string); ++ if (str) { ++ strncpy(string,str,FILNAMSIZ); ++ free(str); ++ } ++ } ++} diff --git a/patches/unzip/unzip-ds-unixenc.patch b/patches/unzip/unzip-ds-unixenc.patch new file mode 100644 index 0000000..e33e6ba --- /dev/null +++ b/patches/unzip/unzip-ds-unixenc.patch @@ -0,0 +1,9 @@ +diff -dPNur unzip-5.50/unzpriv.h unzip-5.50-new/unzpriv.h +--- unzip-5.50/unzpriv.h Sun Feb 17 21:01:48 2002 ++++ unzip-5.50-new/unzpriv.h Tue Jun 10 07:16:23 2003 +@@ -2424,4 +2424,5 @@ + !(((islochdr) || (isuxatt)) && \ + ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \ + (hostnum) == FS_HPFS_ || \ ++ (hostnum) == UNIX_ || \ + ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \ diff --git a/patches/unzip/unzip60-ds-isprint.patch b/patches/unzip/unzip60-ds-isprint.patch new file mode 100644 index 0000000..64ea1ee --- /dev/null +++ b/patches/unzip/unzip60-ds-isprint.patch @@ -0,0 +1,12 @@ +diff -dPNur unzip60/extract.c unzip60-ds/extract.c +--- unzip60/extract.c 2009-03-14 02:32:52.000000000 +0100 ++++ unzip60-ds/extract.c 2010-07-06 16:34:09.000000000 +0200 +@@ -2596,7 +2596,7 @@ + */ + # define UZ_FNFILTER_REPLACECHAR '?' + # endif +- if (!isprint(*r)) { ++ if (*r < 32) { //(!isprint(*r)) { + if (*r < 32) { + /* ASCII control codes are escaped as "^{letter}". */ + if (se != NULL && (s > (space + (size-4)))) { diff --git a/patches/unzip/update_lazy b/patches/unzip/update_lazy new file mode 100755 index 0000000..de1b04a --- /dev/null +++ b/patches/unzip/update_lazy @@ -0,0 +1,9 @@ +#!/bin/bash + + sed -i \ + -e "s:-O3:\${CFLAGS}:" \ + -e "s:CC=gcc :CC=\"gcc -DRCC_LAZY=1\":" \ + -e "s:LD=gcc :LD=\"gcc \${LDFLAGS} -ldl\" :" \ + -e "s:-O :\${CFLAGS} :" \ + -e "s:LF2 = -s:LF2 = :" \ + unix/Makefile \ diff --git a/patches/unzip/update_shared b/patches/unzip/update_shared new file mode 100755 index 0000000..1dd8b2a --- /dev/null +++ b/patches/unzip/update_shared @@ -0,0 +1,9 @@ +#!/bin/bash + + sed -i \ + -e "s:-O3:\${CFLAGS}:" \ + -e "s:CC=gcc :CC=gcc :" \ + -e "s:LD=gcc :LD=\"gcc \${LDFLAGS} -lrcc\" :" \ + -e "s:-O :\${CFLAGS} :" \ + -e "s:LF2 = -s:LF2 = :" \ + unix/Makefile \ diff --git a/patches/xmms-plugins/xmms-wma-csa1.tar.bz2 b/patches/xmms-plugins/xmms-wma-csa1.tar.bz2 Binary files differnew file mode 100644 index 0000000..de6968c --- /dev/null +++ b/patches/xmms-plugins/xmms-wma-csa1.tar.bz2 diff --git a/patches/xmms/extra/xmms-ds-mpg123-wrongencoding.patch b/patches/xmms/extra/xmms-ds-mpg123-wrongencoding.patch new file mode 100644 index 0000000..66a2100 --- /dev/null +++ b/patches/xmms/extra/xmms-ds-mpg123-wrongencoding.patch @@ -0,0 +1,157 @@ +diff -dPNur xmms-1.2.11-orig/Input/mpg123/id3_frame_text.c xmms-1.2.11/Input/mpg123/id3_frame_text.c +--- xmms-1.2.11-orig/Input/mpg123/id3_frame_text.c 2008-04-11 15:44:34.000000000 +0200 ++++ xmms-1.2.11/Input/mpg123/id3_frame_text.c 2008-04-11 15:52:25.000000000 +0200 +@@ -46,6 +46,7 @@ + break; + case ID3_ENCODING_UTF16: + case ID3_ENCODING_UTF16BE: ++ case ID3_ENCODING_UTF16LE: + while (*text != 0 || *(text + 1) != 0) + { + text += 2; +@@ -73,6 +74,8 @@ + return xmms_charset_from_utf16(text); + case ID3_ENCODING_UTF16BE: + return xmms_charset_from_utf16be(text); ++ case ID3_ENCODING_UTF16LE: ++ return xmms_charset_from_utf16le(text); + default: + return NULL; + } +@@ -88,6 +91,8 @@ + */ + gint8 id3_get_encoding(struct id3_frame *frame) + { ++ gint8 encoding; ++ + /* Type check */ + if (!id3_frame_is_text(frame) && + frame->fr_desc->fd_id != ID3_WXXX && +@@ -106,7 +111,21 @@ + if (id3_decompress_frame(frame) == -1) + return -1; + +- return *(gint8 *) frame->fr_data; ++ encoding = *(gint8 *) frame->fr_data; ++ ++ switch (encoding) { ++ case ID3_ENCODING_ISO_8859_1: ++ case ID3_ENCODING_UTF8: ++ case ID3_ENCODING_UTF16: ++ case ID3_ENCODING_UTF16BE: ++ return encoding; ++ case ID3_ENCODING_UTF16LE: ++ printf("ID3V2 frame (%.4s) has invalid encoding (%u). Assuming UTF-16LE.\n", frame->fr_desc->fd_idstr?frame->fr_desc->fd_idstr:"UNKN", encoding); ++ return encoding; ++ default: ++ printf("ID3V2 frame (%.4s) has invalid encoding (%u). Assuming Latin1.\n", frame->fr_desc->fd_idstr?frame->fr_desc->fd_idstr:"UNKN", encoding); ++ return ID3_ENCODING_ISO_8859_1; ++ } + } + + +@@ -269,6 +288,7 @@ + else if (encoding == ID3_ENCODING_UTF8) ctext = xmms_charset_to_utf8(text); + else if (encoding == ID3_ENCODING_UTF16) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16"); + else if (encoding == ID3_ENCODING_UTF16BE) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16BE"); ++ else if (encoding == ID3_ENCODING_UTF16LE) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16LE"); + else ctext = NULL; + + if (ctext) text = ctext; +@@ -433,6 +453,7 @@ + else if (encoding == ID3_ENCODING_UTF8) ctext = xmms_charset_to_utf8(text); + else if (encoding == ID3_ENCODING_UTF16) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16"); + else if (encoding == ID3_ENCODING_UTF16BE) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16BE"); ++ else if (encoding == ID3_ENCODING_UTF16LE) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16LE"); + else ctext = NULL; + + if (ctext) text = ctext; +@@ -453,11 +474,12 @@ + *(gint8 *) frame->fr_raw_data = encoding; + memcpy((char*)frame->fr_raw_data + 1, xmms_rcc_get_language(), 3); + +- if ((encoding == ID3_ENCODING_UTF16)||(encoding == ID3_ENCODING_UTF16BE)) { ++ if ((encoding == ID3_ENCODING_UTF16)||(encoding == ID3_ENCODING_UTF16BE)||(encoding == ID3_ENCODING_UTF16LE)) { + int i; + lang = "Comments"; + if (encoding == ID3_ENCODING_UTF16) cdata = xmms_charset_convert(lang, strlen(lang), NULL, "UTF-16"); +- else cdata = xmms_charset_convert(lang, strlen(lang), NULL, "UTF-16BE"); ++ else if (encoding == ID3_ENCODING_UTF16BE) cdata = xmms_charset_convert(lang, strlen(lang), NULL, "UTF-16BE"); ++ else cdata = xmms_charset_convert(lang, strlen(lang), NULL, "UTF-16LE"); + memcpy((char *) frame->fr_raw_data + 4, cdata, 20); + g_free(cdata); + } else +diff -dPNur xmms-1.2.11-orig/Input/mpg123/id3.h xmms-1.2.11/Input/mpg123/id3.h +--- xmms-1.2.11-orig/Input/mpg123/id3.h 2008-04-11 15:44:34.000000000 +0200 ++++ xmms-1.2.11/Input/mpg123/id3.h 2008-04-11 15:50:58.000000000 +0200 +@@ -141,6 +141,7 @@ + #define ID3_ENCODING_UTF16 0x01 + #define ID3_ENCODING_UTF16BE 0x02 + #define ID3_ENCODING_UTF8 0x03 ++#define ID3_ENCODING_UTF16LE 0x04 + + /* + * ID3 frame id numbers. +@@ -312,7 +313,7 @@ + + + #define ID3_TEXT_FRAME_ENCODING(frame) \ +- (*(guint8*)(frame)->fr_data) ++ id3_get_encoding(frame) + + #define ID3_TEXT_FRAME_PTR(frame) \ + ((char *)(frame)->fr_data + 1) +diff -dPNur xmms-1.2.11-orig/libxmms/charset.c xmms-1.2.11/libxmms/charset.c +--- xmms-1.2.11-orig/libxmms/charset.c 2008-04-10 22:49:57.000000000 +0200 ++++ xmms-1.2.11/libxmms/charset.c 2008-04-11 15:50:21.000000000 +0200 +@@ -141,6 +141,14 @@ + return xmms_charset_convert(string, utf16_strlen(string), "UTF-16BE", NULL); + } + ++char *xmms_charset_from_utf16le(const unsigned char *string) ++{ ++ if (!string) ++ return NULL; ++ ++ return xmms_charset_convert(string, utf16_strlen(string), "UTF-16LE", NULL); ++} ++ + char* xmms_charset_from_latin1(const char *string) + { + char *cstring; +@@ -174,6 +182,9 @@ + if (!strcmp(from, "UTF-16BE") && !to) + return xmms_charset_from_utf16be(string); + ++ if (!strcmp(from, "UTF-16LE") && !to) ++ return xmms_charset_from_utf16le(string); ++ + return g_strdup(string); + } + +@@ -275,6 +286,14 @@ + return utf16_to_ascii(string, FALSE); + } + ++char *xmms_charset_from_utf16le(const unsigned char *string) ++{ ++ if (!string) ++ return NULL; ++ ++ return utf16_to_ascii(string, TRUE); ++} ++ + char* xmms_charset_from_latin1(const char *string) + { + char *cstring; +diff -dPNur xmms-1.2.11-orig/libxmms/charset.h xmms-1.2.11/libxmms/charset.h +--- xmms-1.2.11-orig/libxmms/charset.h 2008-04-10 22:49:57.000000000 +0200 ++++ xmms-1.2.11/libxmms/charset.h 2008-04-11 15:49:47.000000000 +0200 +@@ -14,6 +14,7 @@ + char* xmms_charset_from_utf8(const char *string); + char* xmms_charset_from_utf16(const unsigned char *string); + char* xmms_charset_from_utf16be(const unsigned char *string); ++char *xmms_charset_from_utf16le(const unsigned char *string); + char* xmms_charset_from_latin1(const char *string); + + size_t utf16_strlen(const char *string); diff --git a/patches/xmms/plugins/xmms-ds-mpg123-editor-keys.patch b/patches/xmms/plugins/xmms-ds-mpg123-editor-keys.patch new file mode 100644 index 0000000..38a74e2 --- /dev/null +++ b/patches/xmms/plugins/xmms-ds-mpg123-editor-keys.patch @@ -0,0 +1,164 @@ +diff -dPNur rusxmms-new/Input/mpg123/fileinfo.c rusxmms-new-keys/Input/mpg123/fileinfo.c +--- rusxmms-new/Input/mpg123/fileinfo.c 2005-07-17 11:46:05.000000000 +0200 ++++ rusxmms-new-keys/Input/mpg123/fileinfo.c 2005-07-18 01:12:36.000000000 +0200 +@@ -31,6 +31,10 @@ + #define MAX_STR_LEN 100 + #define MAX_ENTRY_LEN2 1023 + ++#include <gdk/gdkkeysyms.h> ++#include <gdk/gdktypes.h> ++#include "../../xmms/xmms.h" ++ + static GtkWidget *window = NULL; + static GtkWidget *notebook = NULL; + static GtkWidget *filename_entry, *id3v1_frame, *id3v2_frame; +@@ -507,6 +511,106 @@ + gtk_widget_destroy(w); + } + ++static int restore_focus; ++static GtkWidget *save; ++ ++ ++static GtkWidget **widgets1[] = { &v1_title_entry, &v1_artist_entry, &v1_album_entry, &v1_comment_entry, &v1_year_entry, NULL }; ++static GtkWidget **widgets2[] = { &v2_title_entry, &v2_artist_entry, &v2_album_entry, &v2_comment_entry, &v2_year_entry, &v2_composer_entry, &v2_orig_artist_entry, &v2_url_entry, &v2_encoded_by_entry, NULL }; ++/* Info: gdktypes.h, gdkkeysyms.h */ ++gboolean mpg123_keypress_cb(GtkWidget * w, GdkEventKey * event, gpointer close) { ++ gint pos; ++ GtkWidget ***widgets, *widget, *focused; ++ ++ switch(event->keyval) { ++ case GDK_Return: ++ restore_focus=1; ++ gtk_signal_emit_by_name(GTK_OBJECT(save), "clicked", NULL); ++ gtk_signal_emit_by_name(GTK_OBJECT(close), "clicked", NULL); ++ return TRUE; ++ break; ++ case GDK_Escape: ++ restore_focus=1; ++ return TRUE; ++ break; ++ } ++ ++ if (event->state&GDK_CONTROL_MASK) { ++ switch(event->keyval) { ++ case GDK_Left: ++ gtk_notebook_prev_page(GTK_NOTEBOOK(notebook)); ++ pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); ++ if (pos == 0) gtk_window_set_focus(GTK_WINDOW(window), *widgets2[0]); ++ else if (pos == 1) gtk_window_set_focus(GTK_WINDOW(window), *widgets1[0]); ++ gtk_window_activate_focus(GTK_WINDOW(window)); ++ return TRUE; ++ break; ++ case GDK_Right: ++ gtk_notebook_next_page(GTK_NOTEBOOK(notebook)); ++ pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); ++ if (pos == 0) gtk_window_set_focus(GTK_WINDOW(window), *widgets2[0]); ++ else if (pos == 1) gtk_window_set_focus(GTK_WINDOW(window), *widgets1[0]); ++ gtk_window_activate_focus(GTK_WINDOW(window)); ++ return TRUE; ++ break; ++ } ++ } ++ { ++ switch(event->keyval) { ++ case GDK_Page_Up: ++ pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); ++ ++ focused = GTK_WINDOW(window)->focus_widget; ++ if (pos == 1) widgets = widgets1; ++ else if (pos == 0) widgets = widgets2; ++ else return FALSE; ++ ++ for (pos = 0; widgets[pos]; pos++) { ++ if (focused == *widgets[pos]) { ++ if (pos == 0) { ++ while (widgets[pos+1]) pos++; ++ widget = *widgets[pos]; ++ } else widget = *widgets[pos - 1]; ++ ++ gtk_window_set_focus(GTK_WINDOW(window), widget); ++ return TRUE; ++ } ++ } ++ break; ++ case GDK_Page_Down: ++ case GDK_Tab: ++ pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); ++ ++ focused = GTK_WINDOW(window)->focus_widget; ++ if (pos == 1) widgets = widgets1; ++ else if (pos == 0) widgets = widgets2; ++ else return FALSE; ++ ++ for (pos = 0; widgets[pos]; pos++) { ++ if (focused == *widgets[pos]) { ++ if (widgets[pos + 1]) widget = *widgets[pos + 1]; ++ else widget = *widgets[0]; ++ ++ gtk_window_set_focus(GTK_WINDOW(window), widget); ++ return TRUE; ++ } ++ } ++ ++ break; ++ } ++ } ++ ++ return FALSE; ++} ++ ++void gtk_widget_destroyed_focus(GtkWidget *widget, GtkWidget **widget_pointer) { ++ gtk_widget_destroyed(widget,widget_pointer); ++ if (restore_focus) { ++ gtk_widget_hide(playlistwin); ++ gtk_widget_show(playlistwin); ++ } ++} ++ + void mpg123_file_info_box(char *filename) + { + int i; +@@ -517,6 +621,8 @@ + const char *emphasis[4]; + const char *bool_label[2]; + ++ restore_focus = 0; ++ + emphasis[0] = _("None"); + emphasis[1] = _("50/15 ms"); + emphasis[2] = ""; +@@ -529,15 +635,16 @@ + GtkWidget *window_vbox, + *id3v1_vbox, *id3v2_vbox, *id3v1_frame_vbox, *id3v2_frame_vbox, + *mpeg_lvbox, *mpeg_rvbox, *mpeg_hbox, *mpeg_box, *mpeg_frame, +- *bbox, *save, *close, *copy_to, *copy_from, ++ *bbox, *close, *copy_to, *copy_from, + *table, *label, *filename_hbox; ++ GtkAccelGroup *ag; + + v1_labels_list = g_ptr_array_new(); + v2_labels_list = g_ptr_array_new(); + + window = gtk_window_new(GTK_WINDOW_DIALOG); +- gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window); +- gtk_signal_connect(GTK_OBJECT(window), "key_press_event", file_info_box_keypress_cb, NULL); ++ gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed_focus), &window); ++// gtk_signal_connect(GTK_OBJECT(window),"key_press_event",file_info_box_keypress_cb, NULL); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + + window_vbox = gtk_vbox_new(FALSE,10); +@@ -916,6 +1023,13 @@ + GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window)); + gtk_box_pack_start(GTK_BOX(bbox), close, TRUE, TRUE, 5); + ++ ag = gtk_accel_group_new(); ++ gtk_accel_group_add(ag, GDK_Escape, 0, 0, GTK_OBJECT(close), "clicked"); ++ gtk_accel_group_add(ag, GDK_Return, 0, 0, GTK_OBJECT(save), "clicked"); ++ gtk_window_add_accel_group(GTK_WINDOW(window), ag); ++ ++ gtk_signal_connect(GTK_OBJECT(window), "key_press_event", GTK_SIGNAL_FUNC(mpg123_keypress_cb), close); ++ + gtk_container_add(GTK_CONTAINER(window), window_vbox); + gtk_widget_show_all(window); + } diff --git a/patches/xmms/plugins/xmms-ds-mpg123-editor.patch b/patches/xmms/plugins/xmms-ds-mpg123-editor.patch new file mode 100644 index 0000000..a4afb70 --- /dev/null +++ b/patches/xmms/plugins/xmms-ds-mpg123-editor.patch @@ -0,0 +1,202 @@ +diff -dPNur xmms-1.2.10/Input/mpg123/fileinfo.c xmms-1.2.10-new/Input/mpg123/fileinfo.c +--- rusxmms/Input/mpg123/fileinfo.c 2005-07-17 01:54:55.000000000 +0200 ++++ rusxmms-new/Input/mpg123/fileinfo.c 2005-07-17 11:46:05.000000000 +0200 +@@ -24,6 +24,7 @@ + #include <string.h> + #include <errno.h> + #include <libxmms/xentry.h> ++#include <libxmms/rcc.h> + #include <gdk/gdkkeysyms.h> + #include "mpg123.h" + +@@ -60,19 +61,33 @@ + + static void set_entry_tag_v1(GtkEntry * entry, const char * tag, int length) + { +- char *text = g_strchomp(g_strndup(tag, length)); ++ char *text; ++ ++ text = xmms_rcc_sized_recode(XMMS_RCC_ID3, XMMS_RCC_CTYPE, tag, length); ++ if (!text) text = g_strchomp(g_strndup(tag, length)); ++ + gtk_entry_set_text(entry, text); + g_free(text); + } + + static void get_entry_tag_v1(GtkEntry * entry, char * tag, int length) + { ++ gchar *ctext; ++ ++ ctext = xmms_rcc_recode(XMMS_RCC_CTYPE, XMMS_RCC_ID3, gtk_entry_get_text(entry)); ++ ++ if (ctext) { ++ strncpy(tag, ctext, length); ++ free(ctext); ++ } else + strncpy(tag, gtk_entry_get_text(entry), length); + } + + void copy_entry_tag_v1(GtkEntry * src, GtkEntry * dest, int length) + { +- set_entry_tag_v1(dest, gtk_entry_get_text(src), length); ++ char *text = g_strchomp(g_strndup(gtk_entry_get_text(src), length)); ++ gtk_entry_set_text(dest, text); ++ g_free(text); + return; + } + +@@ -497,6 +512,7 @@ + int i; + struct id3v1tag_t id3v1tag; + FILE *fh; ++ gchar *cfilename; + char *tmp, *title; + const char *emphasis[4]; + const char *bool_label[2]; +@@ -908,6 +924,9 @@ + g_free(current_filename); + current_filename = g_strdup(filename); + ++ cfilename = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_OUT, filename); ++ if (cfilename) filename=cfilename; ++ + title = g_strdup_printf(_("File Info - %s"), g_basename(filename)); + gtk_window_set_title(GTK_WINDOW(window), title); + g_free(title); +@@ -922,6 +941,8 @@ + gtk_entry_set_text(GTK_ENTRY(v2_title_entry), title); + g_free(title); + ++ if (cfilename) g_free(cfilename); ++ + gtk_entry_set_text(GTK_ENTRY(v1_artist_entry), ""); + gtk_entry_set_text(GTK_ENTRY(v1_album_entry), ""); + gtk_entry_set_text(GTK_ENTRY(v1_year_entry), ""); +diff -dPNur xmms-1.2.10/Input/mpg123/id3_frame_text.c xmms-1.2.10-new/Input/mpg123/id3_frame_text.c +--- xmms-1.2.10/Input/mpg123/id3_frame_text.c 2005-08-10 03:20:03.000000000 +0200 ++++ xmms-1.2.10-new/Input/mpg123/id3_frame_text.c 2005-08-10 03:29:40.000000000 +0200 +@@ -28,6 +28,7 @@ + #include "id3_header.h" + + #include "libxmms/charset.h" ++#include "libxmms/rcc.h" + + /* For extern mpg123_cfg */ + #include "mpg123.h" +@@ -247,6 +248,9 @@ + */ + int id3_set_text(struct id3_frame *frame, char *text) + { ++ char *ctext; ++ gint8 encoding; ++ + /* Type check */ + if (frame->fr_desc->fd_idstr[0] != 'T') + return -1; +@@ -256,18 +260,36 @@ + */ + id3_frame_clear_data(frame); + ++ ++ /* ++ * Recoding. ++ */ ++ encoding = (gint8)xmms_rcc_get_id3v2_encoding(); ++ if (encoding == ID3_ENCODING_ISO_8859_1) ctext = xmms_rcc_recode(XMMS_RCC_CTYPE, XMMS_RCC_ID3V2, text); ++ else if (encoding == ID3_ENCODING_UTF8) ctext = xmms_charset_to_utf8(text); ++ else if (encoding == ID3_ENCODING_UTF16) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16"); ++ else if (encoding == ID3_ENCODING_UTF16BE) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16BE"); ++ else ctext = NULL; ++ ++ if (ctext) text = ctext; ++ + /* + * Allocate memory for new data. + */ ++ if ((encoding == ID3_ENCODING_UTF16)||(encoding == ID3_ENCODING_UTF16BE)) ++ frame->fr_raw_size = utf16_strlen(text) + 2; ++ else + frame->fr_raw_size = strlen(text) + 1; + frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); + + /* + * Copy contents. + */ +- *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; ++ *(gint8 *) frame->fr_raw_data = encoding; + memcpy((char *) frame->fr_raw_data + 1, text, frame->fr_raw_size); + ++ if (ctext) free(ctext); ++ + frame->fr_altered = 1; + frame->fr_owner->id3_altered = 1; + +@@ -389,7 +411,10 @@ + */ + int id3_set_comment(struct id3_frame *frame, char *text) + { ++ char *ctext, *cdata; ++ const char *lang; + int *intp; ++ gint8 encoding; + + /* Type check */ + if (frame->fr_desc->fd_id != ID3_COMM) +@@ -401,8 +426,23 @@ + id3_frame_clear_data(frame); + + /* ++ * Recoding. ++ */ ++ encoding = (gint8)xmms_rcc_get_id3v2_encoding(); ++ if (encoding == ID3_ENCODING_ISO_8859_1) ctext = xmms_rcc_recode(XMMS_RCC_CTYPE, XMMS_RCC_ID3V2, text); ++ else if (encoding == ID3_ENCODING_UTF8) ctext = xmms_charset_to_utf8(text); ++ else if (encoding == ID3_ENCODING_UTF16) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16"); ++ else if (encoding == ID3_ENCODING_UTF16BE) ctext = xmms_charset_convert(text, strlen(text), NULL, "UTF-16BE"); ++ else ctext = NULL; ++ ++ if (ctext) text = ctext; ++ ++ /* + * Allocate memory for new data. + */ ++ if ((encoding == ID3_ENCODING_UTF16)||(encoding == ID3_ENCODING_UTF16BE)) ++ frame->fr_raw_size = 25 + utf16_strlen(text); ++ else + frame->fr_raw_size = 13 + strlen(text); + frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); /* <encode>XXXComments\0<comment><\0> + +@@ -410,18 +450,29 @@ + * block, so don't waste time with a calloc() + */ + +- ((guint8 *)frame->fr_raw_data)[0] = ID3_ENCODING_ISO_8859_1; +- ((guint8 *)frame->fr_raw_data)[1] = 0x58; +- ((guint8 *)frame->fr_raw_data)[2] = 0x58; +- ((guint8 *)frame->fr_raw_data)[3] = 0x58; ++ *(gint8 *) frame->fr_raw_data = encoding; ++ memcpy((char*)frame->fr_raw_data + 1, xmms_rcc_get_language(), 3); + ++ if ((encoding == ID3_ENCODING_UTF16)||(encoding == ID3_ENCODING_UTF16BE)) { ++ int i; ++ lang = "Comments"; ++ if (encoding == ID3_ENCODING_UTF16) cdata = xmms_charset_convert(lang, strlen(lang), NULL, "UTF-16"); ++ else cdata = xmms_charset_convert(lang, strlen(lang), NULL, "UTF-16BE"); ++ memcpy((char *) frame->fr_raw_data + 4, cdata, 20); ++ g_free(cdata); ++ } else + memcpy((char *) frame->fr_raw_data + 4, "Comments", 9); + + /* + * Copy contents. + */ ++ if ((encoding == ID3_ENCODING_UTF16)||(encoding == ID3_ENCODING_UTF16BE)) ++ memcpy((char *) frame->fr_raw_data + 24, text, utf16_strlen(text) + 2); ++ else + memcpy((char *) frame->fr_raw_data + 13, text, strlen(text) + 1); + ++ if (ctext) free(ctext); ++ + frame->fr_altered = 1; + frame->fr_owner->id3_altered = 1; + diff --git a/patches/xmms/plugins/xmms-ds-mpg123.patch b/patches/xmms/plugins/xmms-ds-mpg123.patch new file mode 100644 index 0000000..fc9c42e --- /dev/null +++ b/patches/xmms/plugins/xmms-ds-mpg123.patch @@ -0,0 +1,20 @@ +diff -dPNur xmms-1.2.11/Input/mpg123/mpg123.c xmms-1.2.11-new/Input/mpg123/mpg123.c +--- xmms-1.2.11/Input/mpg123/mpg123.c 2007-11-25 00:04:27.000000000 +0100 ++++ xmms-1.2.11-new/Input/mpg123/mpg123.c 2007-11-25 01:18:57.000000000 +0100 +@@ -3,6 +3,7 @@ + #include "libxmms/configfile.h" + #include "libxmms/titlestring.h" + #include "libxmms/charset.h" ++#include "libxmms/rcc.h" + #include <string.h> + #include <stdlib.h> + #include <pthread.h> +@@ -496,6 +497,8 @@ + /* + * Format according to filename. + */ ++ ret = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_CTYPE, g_basename(filename)); ++ if (!ret) + ret = g_strdup(g_basename(filename)); + if (extname(ret) != NULL) + *(extname(ret) - 1) = '\0'; /* removes period */ diff --git a/patches/xmms/plugins/xmms-ds-vorbis-editor-keys.patch b/patches/xmms/plugins/xmms-ds-vorbis-editor-keys.patch new file mode 100644 index 0000000..bf59951 --- /dev/null +++ b/patches/xmms/plugins/xmms-ds-vorbis-editor-keys.patch @@ -0,0 +1,78 @@ +diff -dPNur xmms-1.2.11/Input/vorbis/fileinfo.c xmms-1.2.11-new/Input/vorbis/fileinfo.c +--- xmms-1.2.11/Input/vorbis/fileinfo.c 2007-11-25 01:23:31.000000000 +0100 ++++ xmms-1.2.11-new/Input/vorbis/fileinfo.c 2007-11-25 01:24:01.000000000 +0100 +@@ -39,6 +39,9 @@ + #include "libxmms/charset.h" + #include <xmms/i18n.h> + ++#include "../../xmms/xmms.h" ++#include <gdk/gdkkeysyms.h> ++ + #include "vorbis.h" + #include "vcedit.h" + +@@ -444,6 +447,28 @@ + } + + /***********************************************************************/ ++static int restore_focus; ++ ++gboolean vorbis_keypress_cb(GtkWidget * w, GdkEventKey * event, gpointer save) { ++ switch(event->keyval) { ++ case GDK_Return: ++ restore_focus=1; ++ gtk_signal_emit_by_name(GTK_OBJECT(save), "clicked", NULL); ++ break; ++ case GDK_Escape: ++ restore_focus=1; ++ break; ++ } ++ return TRUE; ++} ++ ++void gtk_widget_destroyed_focus(GtkWidget *widget, GtkWidget **widget_pointer) { ++ gtk_widget_destroyed(widget,widget_pointer); ++ if (restore_focus) { ++ gtk_widget_hide(playlistwin); ++ gtk_widget_show(playlistwin); ++ } ++} + + void vorbis_file_info_box(char *fn) + { +@@ -465,6 +490,8 @@ + + g_free(vte.filename); + vte.filename = g_strdup(fn); ++ ++ restore_focus = 0; + + if (!window) + { +@@ -472,11 +499,12 @@ + GtkWidget *hbox, *label, *filename_hbox, *vbox, *left_vbox; + GtkWidget *table, *bbox, *cancel_button; + GtkWidget *save_button, *remove_button; ++ GtkAccelGroup *ag; + + window = gtk_window_new(GTK_WINDOW_DIALOG); + gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); + gtk_signal_connect(GTK_OBJECT(window), "destroy", +- GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window); ++ GTK_SIGNAL_FUNC(gtk_widget_destroyed_focus), &window); + gtk_signal_connect(GTK_OBJECT(window), "key_press_event", + keypress_cb, NULL); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); +@@ -809,6 +837,12 @@ + FALSE, 0); + + gtk_widget_show_all(window); ++ ++ ag = gtk_accel_group_new(); ++ gtk_accel_group_add(ag, GDK_Escape, 0, 0, GTK_OBJECT(cancel_button), "clicked"); ++ gtk_accel_group_add(ag, GDK_Return, 0, 0, GTK_OBJECT(save_button), "clicked"); ++ gtk_window_add_accel_group(GTK_WINDOW(window), ag); ++ gtk_signal_connect(GTK_OBJECT(window),"key_press_event",GTK_SIGNAL_FUNC(vorbis_keypress_cb),save_button); + } else + gdk_window_raise(window->window); + diff --git a/patches/xmms/plugins/xmms-ds-vorbis-editor.patch b/patches/xmms/plugins/xmms-ds-vorbis-editor.patch new file mode 100644 index 0000000..47a7ba9 --- /dev/null +++ b/patches/xmms/plugins/xmms-ds-vorbis-editor.patch @@ -0,0 +1,51 @@ +diff -dPNur xmms-1.2.11/Input/vorbis/fileinfo.c xmms-1.2.11-new/Input/vorbis/fileinfo.c +--- xmms-1.2.11/Input/vorbis/fileinfo.c 2007-11-25 00:04:27.000000000 +0100 ++++ xmms-1.2.11-new/Input/vorbis/fileinfo.c 2007-11-25 01:20:57.000000000 +0100 +@@ -34,6 +34,7 @@ + #include <vorbis/codec.h> + #include <vorbis/vorbisfile.h> + ++#include "libxmms/rcc.h" + #include "libxmms/util.h" + #include "libxmms/charset.h" + #include <xmms/i18n.h> +@@ -451,6 +452,7 @@ + char *description, *version, *isrc, *copyright, *organization; + char *location, *vendor = "N/A"; + char *rg_track_gain, *rg_album_gain, *rg_track_peak, *rg_album_peak; ++ gchar *cfilename; + + int time, minutes, seconds, bitrate, avgbitrate, rate, channels; + int filesize, i; +@@ -931,6 +933,11 @@ + gtk_entry_set_text(GTK_ENTRY(isrc_entry), isrc); + gtk_entry_set_text(GTK_ENTRY(location_entry), location); + #endif ++ cfilename = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_CTYPE, vte.filename); ++ if (cfilename) { ++ gtk_entry_set_text(GTK_ENTRY(filename_entry), cfilename); ++ g_free(cfilename); ++ } else + gtk_entry_set_text(GTK_ENTRY(filename_entry), vte.filename); + gtk_editable_set_position(GTK_EDITABLE(filename_entry), -1); + +diff -dPNur xmms-1.2.11/Input/vorbis/vorbis.c xmms-1.2.11-new/Input/vorbis/vorbis.c +--- xmms-1.2.11/Input/vorbis/vorbis.c 2007-11-25 00:04:27.000000000 +0100 ++++ xmms-1.2.11-new/Input/vorbis/vorbis.c 2007-11-25 01:20:57.000000000 +0100 +@@ -46,6 +46,7 @@ + #include "xmms/plugin.h" + #include "libxmms/util.h" + #include "libxmms/configfile.h" ++#include "libxmms/rcc.h" + #include "libxmms/titlestring.h" + #include "libxmms/charset.h" + #include <xmms/i18n.h> +@@ -754,6 +755,8 @@ + if (!vorbis_is_streaming) + { + char *tmp; ++ displaytitle = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_OUT, g_basename(fn)); ++ if (!displaytitle) + displaytitle = g_strdup(g_basename(fn)); + if ((tmp = strrchr(displaytitle, '.')) != NULL) + *tmp = '\0'; diff --git a/patches/xmms/xmms-ds-playlist.patch b/patches/xmms/xmms-ds-playlist.patch new file mode 100644 index 0000000..b72c8d0 --- /dev/null +++ b/patches/xmms/xmms-ds-playlist.patch @@ -0,0 +1,526 @@ +diff -dPNur xmms-1.2.11/xmms/input.c xmms-1.2.11-new/xmms/input.c +--- xmms-1.2.11/xmms/input.c 2005-05-15 02:01:21.000000000 +0200 ++++ xmms-1.2.11-new/xmms/input.c 2008-10-27 18:14:08.000000000 +0100 +@@ -22,6 +22,7 @@ + #include "libxmms/titlestring.h" + #include "libxmms/util.h" + #include "libxmms/xentry.h" ++#include "libxmms/rcc.h" + + static pthread_mutex_t vis_mutex = PTHREAD_MUTEX_INITIALIZER; + +@@ -372,8 +373,12 @@ + + (*title) = xmms_get_titlestring(xmms_get_gentitle_format(), + input); +- if ( (*title) == NULL ) ++ if ( (*title) == NULL ) { ++ (*title) = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_CTYPE, input->file_name); ++ if (!*title) + (*title) = g_strdup(input->file_name); ++ } ++ + (*length) = -1; + g_free(temp); + g_free(input); +diff -dPNur xmms-1.2.11/xmms/main.c xmms-1.2.11-new/xmms/main.c +--- xmms-1.2.11/xmms/main.c 2006-07-16 15:40:04.000000000 +0200 ++++ xmms-1.2.11-new/xmms/main.c 2008-10-27 18:14:08.000000000 +0100 +@@ -36,6 +36,7 @@ + #include "libxmms/xmmsctrl.h" + #include "libxmms/util.h" + #include "libxmms/dirbrowser.h" ++#include "libxmms/rcc.h" + #include "xmms_mini.xpm" + + #define RANDTABLE_SIZE 128 +@@ -899,6 +900,7 @@ + gtk_timeout_remove(mainwin_timeout_tag); + util_set_cursor(NULL); + save_config(); ++ xmms_rcc_free(); + cleanup_ctrlsocket(); + playlist_stop_get_info_thread(); + playlist_clear(); +@@ -1036,8 +1038,14 @@ + + void mainwin_lock_info_text(char *text) + { ++ gchar *ctext; ++ ctext = xmms_rcc_recode(XMMS_RCC_CTYPE, XMMS_RCC_OUT, text); ++ if (ctext) text=ctext; ++ + mainwin_info_text_locked = TRUE; + textbox_set_text(mainwin_info, text); ++ ++ if (ctext) g_free(ctext); + } + + void mainwin_release_info_text(void) +@@ -1695,9 +1703,10 @@ + int match = 0; + char *title, *filename; + +- title = ((PlaylistEntry *) playlist->data)->title; +- filename = ((PlaylistEntry *) playlist->data)->filename; +- ++ title = playlist_check_entrytitle((PlaylistEntry *) playlist->data); ++ filename = xmms_rcc_get(XMMS_RCC_OUT, ((PlaylistEntry *) playlist->data)->fnstring); ++ if (!filename) filename = g_strdup(((PlaylistEntry *) playlist->data)->filename); ++ + if (title) + desc_buf[1] = title; + else if (strchr(filename, '/')) +@@ -1749,7 +1758,7 @@ + */ + match = mainwin_jump_to_file_match(song, words, nw); + } +- ++ + if (match) + { + int row, queue_pos, *data_buf; +@@ -1772,6 +1781,10 @@ + row_to_select = row; + } + ++ g_free(filename); ++ g_free(title); ++ ++ + songnr++; + playlist = playlist->next; + } +@@ -2072,8 +2085,10 @@ + int row, *data_buf; + char *title, *filename, *tmp_buf, *desc_buf[2]; + +- title = ((PlaylistEntry *) queue->data)->title; +- filename = ((PlaylistEntry *) queue->data)->filename; ++ title = playlist_check_entrytitle((PlaylistEntry *) queue->data); ++ filename = xmms_rcc_get(XMMS_RCC_OUT, ((PlaylistEntry *) queue->data)->fnstring); ++ if (!filename) filename = g_strdup(((PlaylistEntry *) queue->data)->filename); ++ + if (title) + desc_buf[1] = title; + else if (strchr(filename, '/')) +@@ -2086,6 +2101,9 @@ + row = gtk_clist_append(GTK_CLIST(qlist), desc_buf); + g_free(tmp_buf); + ++ g_free(filename); ++ g_free(title); ++ + data_buf = g_malloc(sizeof (int)); + *data_buf = pos; + gtk_clist_set_row_data_full(qlist, row, data_buf, g_free); +@@ -4217,6 +4235,7 @@ + #endif + + read_config(); ++ xmms_rcc_init(); + + #if defined(HAVE_SCHED_SETSCHEDULER) && defined(HAVE_SCHED_GET_PRIORITY_MAX) + if (cfg.use_realtime) +diff -dPNur xmms-1.2.11/xmms/playlist.c xmms-1.2.11-new/xmms/playlist.c +--- xmms-1.2.11/xmms/playlist.c 2007-11-16 22:51:30.000000000 +0100 ++++ xmms-1.2.11-new/xmms/playlist.c 2008-10-27 18:14:31.000000000 +0100 +@@ -20,6 +20,8 @@ + #include "xmms.h" + #include <time.h> + #include "libxmms/util.h" ++#include <locale.h> ++#include "libxmms/rcc.h" + #include <sys/stat.h> + #include <unistd.h> + +@@ -91,6 +93,8 @@ + entry = node->data; + if (entry->filename) + g_free(entry->filename); ++ if (entry->fnstring) ++ g_free(entry->fnstring); + if (entry->title) + g_free(entry->title); + g_free(entry); +@@ -166,6 +170,8 @@ + + if (entry->filename) + g_free(entry->filename); ++ if (entry->fnstring) ++ g_free(entry->fnstring); + if (entry->title) + g_free(entry->title); + shuffle_list = g_list_remove(shuffle_list, entry); +@@ -280,9 +286,17 @@ + PlaylistEntry *entry; + + entry = g_malloc0(sizeof (PlaylistEntry)); ++ + entry->filename = g_strdup(filename); ++ entry->fnstring = xmms_rcc_put(XMMS_RCC_FS, filename); ++ if (!entry->fnstring) entry->fnstring = g_strdup(filename); ++ + if (title) ++ { ++ entry->title = xmms_rcc_put(XMMS_RCC_CTYPE, title); ++ if (!entry->title) + entry->title = g_strdup(title); ++ } + entry->length = len; + + PL_LOCK(); +@@ -624,6 +638,8 @@ + if (playlist_position) + { + g_free(playlist_position->title); ++ playlist_position->title = xmms_rcc_put(XMMS_RCC_CTYPE, title); ++ if (!playlist_position->title) + playlist_position->title = g_strdup(title); + playlist_position->length = length; + } +@@ -1015,6 +1031,7 @@ + char *playlist_get_info_text(void) + { + char *text, *title, *tmp, *numbers, *length; ++ char *ctitle; + + PL_LOCK(); + if (!playlist_position) +@@ -1023,10 +1040,20 @@ + return NULL; + } + +- if (playlist_position->title) ++ if (playlist_position->title) { ++ ctitle = xmms_rcc_get(XMMS_RCC_OUT, playlist_position->title); ++ if (ctitle) title = ctitle; ++ else + title = playlist_position->title; +- else ++ } else { ++ ctitle = xmms_rcc_get(XMMS_RCC_OUT, playlist_position->fnstring); ++ if (ctitle) { ++ title = g_strdup(g_basename(ctitle)); ++ g_free(ctitle); ++ ctitle = title; ++ } else + title = g_basename(playlist_position->filename); ++ } + + /* + * If the user don't want numbers in the playlist, don't +@@ -1048,6 +1075,7 @@ + text = g_strdup_printf("%s%s%s", numbers, title, length); + g_free(numbers); + g_free(length); ++ if (ctitle) g_free(ctitle); + + PL_UNLOCK(); + +@@ -1083,6 +1111,7 @@ + { + GList *node; + FILE *file; ++ gchar *ctitle, *cfn; + + if ((file = fopen(filename, "w")) == NULL) + return FALSE; +@@ -1101,10 +1130,12 @@ + while (node) + { + PlaylistEntry *entry = node->data; ++ if (!strstr(entry->filename,"://")) cfn = xmms_rcc_fs2pl(entry->fnstring, entry->filename); ++ else cfn=NULL; + if (is_pls) + fprintf(file, "File%d=%s\n", + g_list_position(playlist, node) + 1, +- entry->filename); ++ cfn?cfn:entry->filename); + else + { + if (entry->title && cfg.use_pl_metadata) +@@ -1116,11 +1147,14 @@ + else + seconds = -1; + ++ ctitle = xmms_rcc_get(XMMS_RCC_PL, entry->title); + fprintf(file, "#EXTINF:%d,%s\n", +- seconds, entry->title); ++ seconds, ctitle?ctitle:entry->title); ++ if (ctitle) g_free(ctitle); + } +- fprintf(file, "%s\n", entry->filename); ++ fprintf(file, "%s\n", cfn?cfn:entry->filename); + } ++ if (cfn) g_free(cfn); + node = g_list_next(node); + } + PL_UNLOCK(); +@@ -1151,16 +1185,32 @@ + *temp = '\0'; + else + { ++ if ((!strstr(filename,"://"))&&(!strstr(playlist_name, "://"))) { ++ temp = xmms_rcc_fs(XMMS_RCC_PLFS, XMMS_RCC_FS, NULL, NULL, filename); ++ if (temp) filename = temp; ++ } else temp = NULL; + __playlist_ins_with_info(filename, pos, title, len); ++ if (temp) g_free(temp); + return; + } ++ if ((!strstr(filename,"://"))&&(!strstr(playlist_name, "://"))) { ++ temp = xmms_rcc_fs(XMMS_RCC_PLFS, XMMS_RCC_FS, path, path, filename); ++ if (temp) filename = temp; ++ } else temp = NULL; ++ if (!temp) + temp = g_strdup_printf("%s/%s", path, filename); + __playlist_ins_with_info(temp, pos, title, len); + g_free(temp); + g_free(path); + } +- else ++ else { ++ if ((filename[0] == '/')&&(!strstr(playlist_name, "://"))) { ++ temp = xmms_rcc_fs(XMMS_RCC_PLFS, XMMS_RCC_FS, NULL, NULL, filename); ++ if (temp) filename = temp; ++ } else temp = NULL; + __playlist_ins_with_info(filename, pos, title, len); ++ if (temp) g_free(temp); ++ } + } + + static void parse_extm3u_info(char *info, char **title, int *length) +@@ -1182,6 +1232,10 @@ + *length *= 1000; + if ((str = strchr(info, ',')) != NULL) + { ++ if (*str) ++ while ((*(str+1)==' ')||(*(str+1)=='\t')) str++; /* g_strstrip removes leading and ending whitespaces */ ++ *title = xmms_rcc_put(XMMS_RCC_PL, str + 1); ++ if (!*title) + *title = g_strdup(str + 1); + g_strstrip(*title); + if (strlen(*title) < 1) +@@ -1210,7 +1264,7 @@ + line = read_ini_string(filename, "playlist", "NumberOfEntries"); + if (line == NULL) + return 0; +- ++ + noe = atoi(line); + g_free(line); + +@@ -1372,9 +1426,27 @@ + return ret; + } + ++gchar* playlist_check_entrytitle(PlaylistEntry *entry) { ++ gchar *title, *fn; ++ ++ if (!entry) return NULL; ++ ++ title = xmms_rcc_get(XMMS_RCC_OUT, entry->title); ++ if (!title) { ++ fn = xmms_rcc_get(XMMS_RCC_OUT, entry->fnstring); ++ if (fn) { ++ title = g_strdup(g_basename(fn)); ++ g_free(fn); ++ } else title = g_strdup(g_basename(entry->filename)); ++ } ++ ++ return title; ++} ++ + char * playlist_get_songtitle(int pos) + { + char *title = NULL, *filename; ++ char *ctitle; + PlaylistEntry *entry; + GList *node; + +@@ -1396,19 +1468,30 @@ + + if (entry->title == NULL && entry->length == -1) + { +- if (playlist_get_info_entry(entry)) ++ if (playlist_get_info_entry(entry)&&(entry->title)) { ++ title = xmms_rcc_get(XMMS_RCC_OUT, entry->title); ++ if (!title) + title = g_strdup(entry->title); ++ } + + PL_UNLOCK(); + } + else + { ++ title = xmms_rcc_get(XMMS_RCC_OUT, entry->title); ++ if (!title) + title = g_strdup(entry->title); + PL_UNLOCK(); + } + +- if (title == NULL) ++ if (title == NULL) { ++ ctitle = xmms_rcc_get(XMMS_RCC_OUT, entry->filename); ++ if (ctitle) { ++ title = g_strdup(g_basename(ctitle)); ++ g_free(ctitle); ++ } else + title = g_strdup(g_basename(filename)); ++ } + + g_free(filename); + +@@ -1453,36 +1536,41 @@ + + static int playlist_sort_by_title_cmpfunc(PlaylistEntry * a, PlaylistEntry * b) + { +- char *a_title, *b_title; ++ const char *a_title, *b_title; + + if (a->title) +- a_title = a->title; ++ a_title = xmms_rcc_string(a->title); + else + { +- if (strrchr(a->filename, '/')) +- a_title = strrchr(a->filename, '/') + 1; ++ if (strrchr(xmms_rcc_string(a->fnstring), '/')) ++ a_title = strrchr(xmms_rcc_string(a->fnstring), '/') + 1; + else +- a_title = a->filename; ++ a_title = xmms_rcc_string(a->filename); + } + + if (b->title) +- b_title = b->title; ++ b_title = xmms_rcc_string(b->title); + else + { +- if (strrchr(a->filename, '/')) +- b_title = strrchr(b->filename, '/') + 1; ++ if (strrchr(xmms_rcc_string(a->fnstring), '/')) ++ b_title = strrchr(xmms_rcc_string(b->fnstring), '/') + 1; + else +- b_title = b->filename; +- ++ b_title = xmms_rcc_string(b->filename); + } +- return strcasecmp(a_title, b_title); ++ return strcoll(a_title, b_title); + } + + void playlist_sort_by_title(void) + { ++ char *locale; ++ locale = setlocale(LC_COLLATE,"en_US.UTF-8"); ++ playlist_select_all(1); ++ playlist_read_info_selection(); ++ playlist_select_all(0); + PL_LOCK(); + playlist = g_list_sort(playlist, (GCompareFunc) playlist_sort_by_title_cmpfunc); + PL_UNLOCK(); ++ setlocale(LC_COLLATE,locale); + } + + static int playlist_sort_by_filename_cmpfunc(PlaylistEntry * a, PlaylistEntry * b) +@@ -1640,9 +1728,13 @@ + + void playlist_sort_selected_by_title(void) + { ++ char *locale; ++ locale = setlocale(LC_COLLATE,"en_US.UTF-8"); ++ playlist_read_info_selection(); + PL_LOCK(); + playlist = playlist_sort_selected(playlist, (GCompareFunc) playlist_sort_by_title_cmpfunc); + PL_UNLOCK(); ++ setlocale(LC_COLLATE,locale); + } + + void playlist_sort_selected_by_filename(void) +@@ -1859,6 +1951,8 @@ + return FALSE; + + /* entry is still around */ ++ entry->title = xmms_rcc_put(XMMS_RCC_CTYPE, temp_title); ++ if (!entry->title) + entry->title = temp_title; + entry->length = temp_length; + +diff -dPNur xmms-1.2.11/xmms/playlist.h xmms-1.2.11-new/xmms/playlist.h +--- xmms-1.2.11/xmms/playlist.h 2007-11-16 22:51:30.000000000 +0100 ++++ xmms-1.2.11-new/xmms/playlist.h 2008-10-27 18:14:08.000000000 +0100 +@@ -23,6 +23,7 @@ + typedef struct + { + gchar *filename; ++ gchar *fnstring; + gchar *title; + gint length; + gboolean selected; +@@ -86,6 +87,7 @@ + void playlist_fileinfo(gint pos); + void playlist_delete_index(glong index); + void playlist_delete_filenames(GList *filenames); ++gchar* playlist_check_entrytitle(PlaylistEntry *entry); + gchar* playlist_get_filename(gint pos); + gchar* playlist_get_songtitle(gint pos); + gint playlist_get_songtime(gint pos); +diff -dPNur xmms-1.2.11/xmms/playlist_list.c xmms-1.2.11-new/xmms/playlist_list.c +--- xmms-1.2.11/xmms/playlist_list.c 2003-06-11 20:44:17.000000000 +0200 ++++ xmms-1.2.11-new/xmms/playlist_list.c 2008-10-27 18:14:08.000000000 +0100 +@@ -451,10 +451,8 @@ + else + gdk_gc_set_foreground(gc, get_skin_color(SKIN_PLEDIT_NORMAL)); + +- if (entry->title) +- title = entry->title; +- else +- title = g_basename(entry->filename); ++ ++ title = playlist_check_entrytitle(entry); + + pos = playlist_get_queue_position(entry); + +@@ -497,6 +495,8 @@ + playlist_list_draw_string(pl, playlist_list_font, + i - pl->pl_first, tw, text); + g_free(text); ++ ++ g_free(title); + } + PL_UNLOCK(); + } +diff -dPNur xmms-1.2.11/xmms/prefswin.c xmms-1.2.11-new/xmms/prefswin.c +--- xmms-1.2.11/xmms/prefswin.c 2007-11-16 22:51:30.000000000 +0100 ++++ xmms-1.2.11-new/xmms/prefswin.c 2008-10-27 18:14:08.000000000 +0100 +@@ -18,6 +18,7 @@ + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + #include "xmms.h" ++#include "libxmms/rcc.h" + #include "libxmms/util.h" + #include "libxmms/titlestring.h" + +@@ -397,6 +398,8 @@ + draw_playlist_window(TRUE); + draw_equalizer_window(TRUE); + ++ xmms_rcc_prefswin_apply(); ++ + save_config(); + } + +@@ -1105,6 +1108,11 @@ + gtk_notebook_append_page(GTK_NOTEBOOK(prefswin_notebook), prefswin_fonts_vbox, gtk_label_new(_("Fonts"))); + + /* ++ * Coding Conversion page ++ */ ++ xmms_rcc_prefswin_create(prefswin_notebook); ++ ++ /* + * Title page + */ + prefswin_title_vbox = gtk_vbox_new(FALSE, 0); diff --git a/patches/xmms/xmms-ds-rusxmms-charset.patch b/patches/xmms/xmms-ds-rusxmms-charset.patch new file mode 100644 index 0000000..670f9e3 --- /dev/null +++ b/patches/xmms/xmms-ds-rusxmms-charset.patch @@ -0,0 +1,87 @@ +diff -dPNur xmms-1.2.10/libxmms/charset.c xmms-1.2.10-new/libxmms/charset.c +--- xmms-1.2.10/libxmms/charset.c 2005-08-10 03:20:03.000000000 +0200 ++++ xmms-1.2.10-new/libxmms/charset.c 2005-08-10 02:54:12.000000000 +0200 +@@ -20,6 +20,7 @@ + #include <langinfo.h> + #endif + ++#include "rcc.h" + #include "charset.h" + + char* xmms_charset_get_current(void) +@@ -37,7 +38,7 @@ + return charset; + } + +-static size_t utf16_strlen(const char *string) ++size_t utf16_strlen(const char *string) + { + size_t len = 0; + +@@ -78,7 +79,7 @@ + /* + 1 for nul in case len == 1 */ + outsize = ((insize + 3) & ~3) + 1; + out = g_malloc(outsize); +- outleft = outsize - 1; ++ outleft = outsize - 2; + outptr = out; + + retry: +@@ -92,7 +93,7 @@ + outsize = (outsize - 1) * 2 + 1; + out = g_realloc(out, outsize); + outptr = out + used; +- outleft = outsize - 1 - used; ++ outleft = outsize - 2 - used; + goto retry; + case EINVAL: + break; +@@ -110,6 +111,7 @@ + } + } + *outptr = '\0'; ++ *(outptr+1) = '\0'; + + iconv_close(cd); + return out; +@@ -141,10 +143,14 @@ + + char* xmms_charset_from_latin1(const char *string) + { ++ char *cstring; + char *to = xmms_charset_get_current(); + + if (!string) + return NULL; ++ ++ cstring = xmms_rcc_recode(XMMS_RCC_ID3, XMMS_RCC_CTYPE, string); ++ if (cstring) return cstring; + + if (!strcmp(to, "UTF-8")) + return xmms_charset_convert(string, strlen(string), "ISO-8859-1", to); +@@ -271,9 +277,14 @@ + + char* xmms_charset_from_latin1(const char *string) + { ++ char *cstring; ++ + if (!string) + return NULL; + ++ cstring = xmms_rcc_recode(XMMS_RCC_ID3, XMMS_RCC_CTYPE, string); ++ if (cstring) return cstring; ++ + return g_strdup(string); + } + +diff -dPNur xmms-1.2.10/libxmms/charset.h xmms-1.2.10-new/libxmms/charset.h +--- xmms-1.2.10/libxmms/charset.h 2005-08-10 03:20:03.000000000 +0200 ++++ xmms-1.2.10-new/libxmms/charset.h 2005-08-10 01:41:01.000000000 +0200 +@@ -16,5 +16,7 @@ + char* xmms_charset_from_utf16be(const unsigned char *string); + char* xmms_charset_from_latin1(const char *string); + ++size_t utf16_strlen(const char *string); ++ + #endif /* XMMS_CHARSET_H */ + diff --git a/patches/xmms/xmms-ds-rusxmms.patch b/patches/xmms/xmms-ds-rusxmms.patch new file mode 100644 index 0000000..6b9287f --- /dev/null +++ b/patches/xmms/xmms-ds-rusxmms.patch @@ -0,0 +1,172 @@ +diff -dPNur xmms-1.2.11/libxmms/configure.in xmms-1.2.11-new/libxmms/configure.in +--- xmms-1.2.11/libxmms/configure.in 2007-11-16 22:51:24.000000000 +0100 ++++ xmms-1.2.11-new/libxmms/configure.in 2007-11-25 17:38:56.000000000 +0100 +@@ -57,6 +57,16 @@ + AC_DEFINE([HAVE_CODESET],,[Define if nl_langinfo(CODESET) is available.]) + fi + ++AC_CHECK_LIB(rccgtk, rccUiInit,[ ++ AC_CHECK_HEADERS(librcc.h librccui.h,[ ++ LIBRCC_LIBS="-lrccgtk" ++ LIBRCC_INCLUDES="" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) + + AC_OUTPUT([ + Makefile +diff -dPNur xmms-1.2.11/libxmms/Makefile.am xmms-1.2.11-new/libxmms/Makefile.am +--- xmms-1.2.11/libxmms/Makefile.am 2004-04-04 10:51:20.000000000 +0200 ++++ xmms-1.2.11-new/libxmms/Makefile.am 2007-11-25 17:38:56.000000000 +0100 +@@ -4,10 +4,11 @@ + lib_LTLIBRARIES = libxmms.la + + libxmms_la_LDFLAGS = -export-dynamic -version-info $(LIBXMMS_MAJOR_VERSION):$(LIBXMMS_MINOR_VERSION):$(LIBXMMS_MICRO_VERSION) +-libxmms_la_LIBADD = @GTK_LIBS@ @POSIX_LIBS@ +-INCLUDES = @GTK_CFLAGS@ -I../intl -I.. ++libxmms_la_LIBADD = @LIBRCC_LIBS@ @GTK_LIBS@ @POSIX_LIBS@ ++INCLUDES = @LIBRCC_INCLUDES@ @GTK_CFLAGS@ -I../intl -I.. + + libxmms_la_SOURCES = \ ++rcc.c rcc.h rcc_langs.h \ + configfile.c configfile.h \ + xmmsctrl.c xmmsctrl.h \ + dirbrowser.c dirbrowser.h \ +diff -dPNur xmms-1.2.11/libxmms/titlestring.c xmms-1.2.11-new/libxmms/titlestring.c +--- xmms-1.2.11/libxmms/titlestring.c 2006-07-24 00:11:51.000000000 +0200 ++++ xmms-1.2.11-new/libxmms/titlestring.c 2007-11-25 17:39:21.000000000 +0100 +@@ -29,6 +29,7 @@ + #include <string.h> + #include <ctype.h> + ++#include "rcc.h" + #include "titlestring.h" + #include "../xmms/i18n.h" + +@@ -42,8 +43,9 @@ + PAD_SIDE_RIGHT, + }; + ++#define xmms_vputstr(out, pstr, pad) xmms_charset_vputstr(out, pstr, pad, from, pflag, c) + +-static int xmms_vputstr(GString *output, char *pstr, struct padding *pad) ++static int xmms_orig_vputstr(GString *output, char *pstr, struct padding *pad) + { + int i; + /* Lenght of the string that is actually printed */ +@@ -83,6 +85,22 @@ + return TRUE; + } + ++static int xmms_charset_vputstr(GString *output, char *pstr, struct padding *pad, int from, gint pflag, char c) { ++ int res; ++ gchar *cstring = NULL; ++ ++ if ((pflag&1)&&((c=='f')||(c=='F'))) { ++ cstring = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_CTYPE, pstr); ++ } ++ if ((pflag&2)&&((c=='a')||(c=='c')||(c=='g')||(c=='p')||(c=='t'))) { ++ cstring = xmms_rcc_recode((xmms_rcc_class)from, XMMS_RCC_CTYPE, pstr); ++ } ++ ++ res = xmms_orig_vputstr(output, cstring?cstring:pstr, pad); ++ if (cstring) g_free(cstring); ++ ++ return res; ++} + + static int xmms_vputnum(GString *output, int ival, struct padding *pad) + { +@@ -124,7 +142,7 @@ + return TRUE; + } + +-static int parse_variable(char **fmt, GString *string, TitleInput *input) ++static int parse_variable(char **fmt, GString *string, TitleInput *input, int from, gint pflag) + { + struct padding padding; + char *ptr = *fmt; +@@ -237,9 +255,33 @@ + return exp; + } + ++static int xmms_charset_analyze_fmt(gchar *fmt) { ++ int flag = 0; ++ ++ if (!fmt) return 0; ++ for (;*fmt;fmt++) { ++ while ((*fmt != '%')&&(*fmt != 0)) fmt++; ++ if (!*fmt) break; ++ while ((*fmt == '-')||(*fmt == ' ')||(*fmt == '0')) fmt++; ++ while (*fmt >= '0' && *fmt <= '9') fmt++; ++ if (*fmt == '.') { fmt++; while (*fmt >= '0' && *fmt <= '9') fmt++; } ++ if ((*fmt=='a')||(*fmt=='c')||(*fmt=='g')||(*fmt=='p')||(*fmt=='t')) flag|=1; ++ if ((*fmt=='f')||(*fmt=='F')) flag|=2; ++ } ++ ++ return flag; ++} ++ ++gchar *xmms_charset_get_titlestring(gchar *fmt, TitleInput *input, int from); + + char *xmms_get_titlestring(char *fmt, TitleInput *input) + { ++ return xmms_charset_get_titlestring(fmt, input, (xmms_rcc_class)-1); ++} ++ ++gchar *xmms_charset_get_titlestring(gchar *fmt, TitleInput *input, int from) { ++ gint pflag; ++ gchar *cstring = NULL; + int f_output = 0; + GString *string; + char *strptr; +@@ -249,12 +291,14 @@ + + string = g_string_new(""); + ++ pflag = (from == (xmms_rcc_class)-1)?0:xmms_charset_analyze_fmt(fmt); ++ + while (*fmt) + { + if (*fmt == '%') + { + fmt++; +- f_output += parse_variable(&fmt, string, input); ++ f_output += parse_variable(&fmt, string, input, from, pflag); + } + else + /* Normal character */ +@@ -271,6 +315,19 @@ + /* Return the result */ + strptr = string->str; + g_string_free(string, FALSE); ++ ++ if (pflag<3) { ++ if (pflag&2) ++ cstring = xmms_rcc_recode(XMMS_RCC_FS, XMMS_RCC_CTYPE, strptr); ++ else ++ cstring = xmms_rcc_recode((xmms_rcc_class)from, XMMS_RCC_CTYPE, strptr); ++ ++ if (cstring) { ++ g_free(strptr); ++ return cstring; ++ } ++ } ++ + return strptr; + } + +diff -dPNur xmms-1.2.11/libxmms/titlestring.h xmms-1.2.11-new/libxmms/titlestring.h +--- xmms-1.2.11/libxmms/titlestring.h 2005-05-15 02:01:20.000000000 +0200 ++++ xmms-1.2.11-new/libxmms/titlestring.h 2007-11-25 17:38:56.000000000 +0100 +@@ -77,6 +77,7 @@ + #endif + + gchar *xmms_get_titlestring(gchar *fmt, TitleInput *input); ++gchar *xmms_charset_get_titlestring(gchar *fmt, TitleInput *input, int from); + GtkWidget* xmms_titlestring_descriptions(char* tags, int rows); + + #ifdef __cplusplus diff --git a/patches/xmms/xmms-ds-shade.patch b/patches/xmms/xmms-ds-shade.patch new file mode 100644 index 0000000..41362df --- /dev/null +++ b/patches/xmms/xmms-ds-shade.patch @@ -0,0 +1,194 @@ +diff -dPNur xmms-1.2.11/xmms/main.c xmms-1.2.11-new/xmms/main.c +--- xmms-1.2.11/xmms/main.c 2007-11-25 01:10:52.000000000 +0100 ++++ xmms-1.2.11-new/xmms/main.c 2007-11-25 01:11:13.000000000 +0100 +@@ -382,6 +382,8 @@ + + cfg.gentitle_format = NULL; + ++ cfg.shade_font = NULL; ++ + filename = g_strconcat(g_get_home_dir(), "/.xmms/config", NULL); + cfgfile = xmms_cfg_open_file(filename); + if (cfgfile) +@@ -481,6 +483,8 @@ + } + xmms_cfg_read_string(cfgfile, "xmms", "generic_title_format", &cfg.gentitle_format); + ++ xmms_cfg_read_string(cfgfile, "xmms", "shade_font", &cfg.shade_font); ++ + xmms_cfg_free(cfgfile); + } + +@@ -519,6 +523,13 @@ + if (cfg.eqpreset_extension == NULL) + cfg.eqpreset_extension = g_strdup("preset"); + ++ if (cfg.shade_font && strlen(cfg.shade_font) == 0) { ++ g_free(cfg.shade_font); ++ cfg.shade_font = NULL; ++ } ++ if (!cfg.shade_font) ++ cfg.shade_font = g_strdup("-misc-fixed-medium-r-*-*-7-*"); ++ + g_free(filename); + } + +@@ -677,6 +688,8 @@ + } + xmms_cfg_write_string(cfgfile, "xmms", "generic_title_format", cfg.gentitle_format); + ++ xmms_cfg_write_string(cfgfile, "xmms", "shade_font", cfg.shade_font); ++ + xmms_cfg_write_file(cfgfile, filename); + xmms_cfg_free(cfgfile); + +diff -dPNur xmms-1.2.11/xmms/main.h xmms-1.2.11-new/xmms/main.h +--- xmms-1.2.11/xmms/main.h 2006-07-16 15:40:04.000000000 +0200 ++++ xmms-1.2.11-new/xmms/main.h 2007-11-25 01:12:55.000000000 +0100 +@@ -60,6 +60,7 @@ + gint mouse_change; + gboolean playlist_transparent; + gchar *gentitle_format; ++ gchar *shade_font; + } + Config; + +diff -dPNur xmms-1.2.11/xmms/playlistwin.c xmms-1.2.11-new/xmms/playlistwin.c +--- xmms-1.2.11/xmms/playlistwin.c 2007-11-16 22:51:30.000000000 +0100 ++++ xmms-1.2.11-new/xmms/playlistwin.c 2007-11-25 01:11:13.000000000 +0100 +@@ -39,7 +39,8 @@ + PButton *playlistwin_shade, *playlistwin_close; + static PlaylistSlider *playlistwin_slider = NULL; + static TextBox *playlistwin_time_min, *playlistwin_time_sec; +-static TextBox *playlistwin_info, *playlistwin_sinfo; ++static TextBox *playlistwin_info; ++TextBox *playlistwin_sinfo; + static SButton *playlistwin_srew, *playlistwin_splay; + static SButton *playlistwin_spause, *playlistwin_sstop; + static SButton *playlistwin_sfwd, *playlistwin_seject; +@@ -1882,6 +1883,7 @@ + static void playlistwin_create_widgets(void) + { + playlistwin_sinfo = create_textbox(&playlistwin_wlist, playlistwin_bg, playlistwin_gc, 4, 4, cfg.playlist_width - 35, FALSE, SKIN_TEXT); ++ textbox_set_xfont(playlistwin_sinfo, cfg.mainwin_use_xfont, cfg.shade_font); + if (!cfg.playlist_shaded) + hide_widget(playlistwin_sinfo); + if (cfg.playlist_shaded) +diff -dPNur xmms-1.2.11/xmms/prefswin.c xmms-1.2.11-new/xmms/prefswin.c +--- xmms-1.2.11/xmms/prefswin.c 2007-11-25 01:10:52.000000000 +0100 ++++ xmms-1.2.11-new/xmms/prefswin.c 2007-11-25 01:11:13.000000000 +0100 +@@ -35,6 +35,7 @@ + + static GtkWidget *prefswin_options_sd_entry, *prefswin_options_pbs_entry; + ++static GtkWidget *prefswin_shade_font_entry, *prefswin_shade_font_browse; + static GtkWidget *prefswin_options_font_entry, *prefswin_options_font_browse; + static GtkWidget *prefswin_options_fontset, *prefswin_mainwin_font_entry; + static GtkWidget *prefswin_mainwin_xfont, *prefswin_options_mouse_spin; +@@ -48,6 +49,7 @@ + extern PButton *playlistwin_shade, *playlistwin_close, *equalizerwin_close; + extern PButton *mainwin_menubtn, *mainwin_minimize, *mainwin_shade, *mainwin_close; + extern TextBox *mainwin_info; ++extern TextBox *playlistwin_sinfo; + extern gboolean mainwin_focus, equalizerwin_focus, playlistwin_focus; + + static gboolean is_opening = FALSE; +@@ -343,11 +345,13 @@ + gboolean show_wm_old = cfg.show_wm_decorations; + g_free(cfg.playlist_font); + g_free(cfg.mainwin_font); ++ g_free(cfg.shade_font); + g_free(cfg.gentitle_format); + prefswin_options_write_data(); + cfg.snap_distance = CLAMP(atoi(gtk_entry_get_text(GTK_ENTRY(prefswin_options_sd_entry))), 0, 1000); + cfg.playlist_font = g_strdup(gtk_entry_get_text(GTK_ENTRY(prefswin_options_font_entry))); + cfg.mainwin_font = g_strdup(gtk_entry_get_text(GTK_ENTRY(prefswin_mainwin_font_entry))); ++ cfg.shade_font = g_strdup(gtk_entry_get_text(GTK_ENTRY(prefswin_shade_font_entry))); + cfg.gentitle_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(prefswin_title_entry))); + cfg.pause_between_songs_time = CLAMP(atoi(gtk_entry_get_text(GTK_ENTRY(prefswin_options_pbs_entry))), 0, 1000); + cfg.mouse_change = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(prefswin_options_mouse_spin)); +@@ -390,6 +394,7 @@ + prefswin_toggle_wm_decorations(); + + textbox_set_xfont(mainwin_info, cfg.mainwin_use_xfont, cfg.mainwin_font); ++ textbox_set_xfont(playlistwin_sinfo, cfg.mainwin_use_xfont, cfg.shade_font); + playlist_list_set_font(cfg.playlist_font); + playlistwin_update_list(); + mainwin_set_info_text(); +@@ -475,6 +480,34 @@ + } + } + ++void prefswin_shade_font_browse_ok(GtkWidget * w, gpointer data) ++{ ++ GtkFontSelectionDialog *fontsel = GTK_FONT_SELECTION_DIALOG(data); ++ gchar *fontname; ++ ++ fontname = gtk_font_selection_dialog_get_font_name(fontsel); ++ ++ if (fontname) ++ gtk_entry_set_text(GTK_ENTRY(prefswin_shade_font_entry), fontname); ++ ++ gtk_widget_destroy(GTK_WIDGET(fontsel)); ++} ++ ++void prefswin_shade_font_browse_cb(GtkWidget * w, gpointer data) ++{ ++ static GtkWidget *fontsel; ++ ++ if (fontsel != NULL) ++ return; ++ ++ fontsel = gtk_font_selection_dialog_new(_("Select playlist font:")); ++ gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(fontsel), gtk_entry_get_text(GTK_ENTRY(prefswin_shade_font_entry))); ++ gtk_signal_connect(GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(fontsel)->ok_button), "clicked", GTK_SIGNAL_FUNC(prefswin_shade_font_browse_ok), fontsel); ++ gtk_signal_connect_object(GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(fontsel)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fontsel)); ++ gtk_signal_connect(GTK_OBJECT(fontsel), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &fontsel); ++ gtk_widget_show(fontsel); ++} ++ + void prefswin_gplugins_use_cb(GtkToggleButton * w, gpointer data) + { + gint sel; +@@ -693,7 +726,10 @@ + GtkWidget *prefswin_vplugins_box, *prefswin_vplugins_vbox; + GtkWidget *prefswin_vplugins_frame, *prefswin_vplugins_hbox; + GtkWidget *prefswin_vplugins_hbbox; +- ++ ++ GtkWidget *prefswin_fonts_shade_frame; ++ GtkWidget *options_font_shade_hbox, *options_font_shade_vbox; ++ + GtkWidget *prefswin_options_frame, *prefswin_options_vbox; + GtkWidget *prefswin_mainwin_frame, *prefswin_mainwin_vbox; + GtkWidget *prefswin_fonts_vbox, *prefswin_fonts_playlist_frame; +@@ -1105,6 +1141,21 @@ + gtk_widget_set_usize(prefswin_mainwin_font_browse, 85, 17); + gtk_box_pack_start(GTK_BOX(prefswin_mainwin_font_hbox), prefswin_mainwin_font_browse, FALSE, TRUE, 0); + ++ prefswin_fonts_shade_frame = gtk_frame_new(_("Shade")); ++ gtk_container_set_border_width(GTK_CONTAINER(prefswin_fonts_shade_frame), 5); ++ gtk_box_pack_start(GTK_BOX(prefswin_fonts_vbox), prefswin_fonts_shade_frame, FALSE, FALSE, 0); ++ options_font_shade_vbox = gtk_vbox_new(FALSE, 5); ++ gtk_container_border_width(GTK_CONTAINER(options_font_shade_vbox), 5); ++ gtk_container_add(GTK_CONTAINER(prefswin_fonts_shade_frame), options_font_shade_vbox); ++ options_font_shade_hbox = gtk_hbox_new(FALSE, 5); ++ gtk_box_pack_start_defaults(GTK_BOX(options_font_shade_vbox), options_font_shade_hbox); ++ prefswin_shade_font_entry = gtk_entry_new(); ++ gtk_box_pack_start(GTK_BOX(options_font_shade_hbox), prefswin_shade_font_entry, TRUE, TRUE, 0); ++ prefswin_shade_font_browse = gtk_button_new_with_label(_("Browse")); ++ gtk_signal_connect(GTK_OBJECT(prefswin_shade_font_browse), "clicked", GTK_SIGNAL_FUNC(prefswin_shade_font_browse_cb), NULL); ++ gtk_widget_set_usize(prefswin_shade_font_browse, 85, 17); ++ gtk_box_pack_start(GTK_BOX(options_font_shade_hbox), prefswin_shade_font_browse, FALSE, TRUE, 0); ++ + gtk_notebook_append_page(GTK_NOTEBOOK(prefswin_notebook), prefswin_fonts_vbox, gtk_label_new(_("Fonts"))); + + /* +@@ -1390,6 +1441,7 @@ + + gtk_entry_set_text(GTK_ENTRY(prefswin_options_font_entry), cfg.playlist_font); + gtk_entry_set_text(GTK_ENTRY(prefswin_mainwin_font_entry), cfg.mainwin_font); ++ gtk_entry_set_text(GTK_ENTRY(prefswin_shade_font_entry), cfg.shade_font); + gtk_entry_set_text(GTK_ENTRY(prefswin_title_entry), cfg.gentitle_format); + sprintf(temp, "%u", cfg.snap_distance); + gtk_entry_set_text(GTK_ENTRY(prefswin_options_sd_entry), temp); diff --git a/patches/xmms/xmms-ds-textbox.patch b/patches/xmms/xmms-ds-textbox.patch new file mode 100644 index 0000000..8442606 --- /dev/null +++ b/patches/xmms/xmms-ds-textbox.patch @@ -0,0 +1,31 @@ +diff -dPNur xmms-1.2.10/xmms/textbox.c xmms-1.2.10-patched/xmms/textbox.c +--- xmms-1.2.10/xmms/textbox.c 2001-12-01 18:00:51.000000000 +0100 ++++ xmms-1.2.10-patched/xmms/textbox.c 2005-06-02 22:43:42.000000000 +0200 +@@ -166,6 +166,8 @@ + GdkGC *gc, *maskgc; + GdkColor *c, pattern; + GdkBitmap *mask; ++ GdkWChar *wtext; ++ int len; + + length = strlen(pixmaptext); + +@@ -192,6 +194,18 @@ + tb->tb_pixmap_width, tb->tb_widget.height); + pattern.pixel = 1; + gdk_gc_set_foreground(maskgc, &pattern); ++ if (cfg.use_fontsets) { ++ wtext = g_malloc((length + 1) * sizeof(GdkWChar)); ++ len = gdk_mbstowcs(wtext, pixmaptext, length + 1); ++ if (len == -1) { ++ for (len = 0; pixmaptext[len] != '\0'; len++) ++ wtext[len] = pixmaptext[len]; ++ } ++ wtext[len] = L'\0'; ++ gdk_draw_text_wc(mask,tb->tb_font, maskgc, 0, tb->tb_font->ascent, wtext, len ); ++ g_free(wtext); ++ } ++ else + gdk_draw_text(mask, tb->tb_font, maskgc, 0, + tb->tb_font->ascent, pixmaptext, length); + gdk_gc_unref(maskgc); diff --git a/source/rcc.c b/source/rcc.c new file mode 100644 index 0000000..c02f050 --- /dev/null +++ b/source/rcc.c @@ -0,0 +1,185 @@ +#include <stdio.h> +#include <string.h> + +#include <gtk/gtklabel.h> +#include <gtk/gtknotebook.h> + +#include "config.h" +#ifdef HAVE_LIBRCC_H +# ifdef HAVE_LIBRCCUI_H +# define HAVE_LIBRCC +# include <librcc.h> +# include <librccui.h> +# endif /* HAVE_LIBRCCUI_H */ +#endif /* HAVE_LIBRCC_H */ + +#include "rcc.h" +#include "rcc_langs.h" + +#ifdef HAVE_LIBRCC +static rcc_context ctx = NULL; +static rcc_ui_context uictx = NULL; + +static rcc_class_default_charset default_id3[] = { + { "ru", "CP1251" }, + { NULL, NULL } +}; + +static rcc_class classes[] = { + { "id3", RCC_CLASS_STANDARD, NULL, default_id3, "ID3 Encoding", 0 }, + { "id3v2", RCC_CLASS_STANDARD, "id3", default_id3, "ID3 v.2 Encoding", 0 }, + { "pl", RCC_CLASS_STANDARD, "id3", default_id3, "PlayList Title Encoding", 0 }, + { "plfs", RCC_CLASS_STANDARD, "pl", NULL, "PlayList File Encoding", 0 }, + { "fs", RCC_CLASS_FS, "LC_CTYPE", NULL, "FileSystem Encoding", 0 }, + { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, NULL, 0 }, + { "ctype", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, NULL, RCC_CLASS_FLAG_CONST|RCC_CLASS_FLAG_SKIP_SAVELOAD }, + { "utf8", RCC_CLASS_STANDARD, "UTF-8", NULL, NULL, RCC_CLASS_FLAG_CONST|RCC_CLASS_FLAG_SKIP_SAVELOAD }, + { NULL } +}; +#endif /* HAVE_LIBRCC */ + + + +void xmms_rcc_init() { +#ifdef HAVE_LIBRCC + rccInit(); + rccUiInit(); + ctx = rccCreateContext(NULL, 0, 0, classes, 0); + rccInitDb4(ctx, NULL, 0); + rccLoad(ctx, "xmms"); + uictx = rccUiCreateContext(ctx); +#endif /* HAVE_LIBRCC */ +} + +void xmms_rcc_free() { +#ifdef HAVE_LIBRCC + rccUiFreeContext(uictx); + rccSave(ctx, "xmms"); + rccFreeContext(ctx); + rccUiFree(); + rccFree(); +#endif /* HAVE_LIBRCC */ +} + +void xmms_rcc_prefswin_create(void *prefswin_notebook) { +#ifdef HAVE_LIBRCC + GtkWidget *vbox; + vbox = (GtkWidget*)rccUiGetPage(uictx, NULL); + gtk_notebook_append_page(GTK_NOTEBOOK(prefswin_notebook), vbox, gtk_label_new(rccUiGetDefaultPageName()->title)); +#endif /* HAVE_LIBRCC */ +} + +void xmms_rcc_prefswin_apply() { +#ifdef HAVE_LIBRCC + rccUiUpdate(uictx); + rccSave(ctx, "xmms"); +#endif /* HAVE_LIBRCC */ +} + +char *xmms_rcc_fs2pl(const char *fnstring, const char *filename) { +#ifdef HAVE_LIBRCC + rcc_language_config config; + + if (!rccStringCheck(fnstring)) return NULL; + + config = rccGetConfig(ctx, rccStringGetLanguage(fnstring)); + if (!config) return NULL; + + if (rccConfigGetCurrentCharset(config, (rcc_class_id)XMMS_RCC_FS) == rccConfigGetCurrentCharset(config, (rcc_class_id)XMMS_RCC_PLFS)) + return NULL; +#endif /* HAVE_LIBRCC */ + + return xmms_rcc_get(XMMS_RCC_PLFS, fnstring); +} + + +/* rcc_string to out */ +char *xmms_rcc_get(xmms_rcc_class charset, const char *buf) { +#ifdef HAVE_LIBRCC + return (char*)rccTo(ctx, (rcc_class_id)charset, (const rcc_string)buf); +#else /* HAVE_LIBRCC */ + return NULL; +#endif /* HAVE_LIBRCC */ +} + +char *xmms_rcc_put(xmms_rcc_class charset, const char *buf) { +#ifdef HAVE_LIBRCC + return (char*)rccFrom(ctx, (rcc_class_id)charset, buf); +#else /* HAVE_LIBRCC */ + return NULL; +#endif /* HAVE_LIBRCC */ +} + +char *xmms_rcc_sized_put(xmms_rcc_class charset, const char *buf, int size) { +#ifdef HAVE_LIBRCC + return (char*)rccSizedFrom(ctx, (rcc_class_id)charset, buf, size); +#else /* HAVE_LIBRCC */ + return NULL; +#endif /* HAVE_LIBRCC */ +} + +char *xmms_rcc_recode(xmms_rcc_class from, xmms_rcc_class to, const char *buf) { +#ifdef HAVE_LIBRCC + if (((from==XMMS_RCC_CTYPE)&&(to==XMMS_RCC_OUT))||((from==XMMS_RCC_OUT)&&(to==XMMS_RCC_CTYPE))) { + if (!rccGetSelectedCharset(ctx, XMMS_RCC_OUT)) return NULL; + } + + return (char*)rccRecode(ctx, (rcc_class_id)from, (rcc_class_id)to, buf); +#else /* HAVE_LIBRCC */ + return NULL; +#endif /* HAVE_LIBRCC */ +} + +char *xmms_rcc_sized_recode(xmms_rcc_class from, xmms_rcc_class to, const char *buf, int size) { +#ifdef HAVE_LIBRCC + return (char*)rccSizedRecode(ctx, (rcc_class_id)from, (rcc_class_id)to, buf, size, NULL); +#else /* HAVE_LIBRCC */ + return NULL; +#endif /* HAVE_LIBRCC */ +} + +char *xmms_rcc_fs(xmms_rcc_class from, xmms_rcc_class to, const char *fspath, const char *path, const char *filename) { +#ifdef HAVE_LIBRCC + return (char*)rccFS(ctx, (rcc_class_id)from, (rcc_class_id)to, fspath, path, filename); +#else /* HAVE_LIBRCC */ + return NULL; +#endif /* HAVE_LIBRCC */ +} + +const char *xmms_rcc_string(const char *buf) { +#ifdef HAVE_LIBRCC + return rccGetString((const rcc_string)buf); +#else /* HAVE_LIBRCC */ + return buf; +#endif /* HAVE_LIBRCC */ +} + +const char *xmms_rcc_get_language() { + const char *lang; +#ifdef HAVE_LIBRCC + lang = rccGetCurrentLanguageName(ctx); +#else /* HAVE_LIBRCC */ + lang = NULL; +#endif /* HAVE_LIBRCC */ + return xmms_rcc_get_639_2_name(lang); +} + +#define ID3_ENCODING_ISO_8859_1 0x00 +#define ID3_ENCODING_UTF16 0x01 +#define ID3_ENCODING_UTF16BE 0x02 +#define ID3_ENCODING_UTF8 0x03 + +int xmms_rcc_get_id3v2_encoding() { +#ifdef HAVE_LIBRCC + const char *name; + + name = rccGetCurrentCharsetName(ctx, (rcc_class_id)XMMS_RCC_ID3V2); + if (!name) return ID3_ENCODING_ISO_8859_1; + + if ((!strcasecmp(name,"UTF-8"))||(!strcasecmp(name,"UTF8"))) return ID3_ENCODING_UTF8; + if ((!strcasecmp(name,"UTF-16"))||(!strcasecmp(name,"UTF16"))||(!strcasecmp(name,"UTF16LE"))||(!strcasecmp(name,"UTF-16LE"))) return ID3_ENCODING_UTF16; + if ((!strcasecmp(name,"UTF-16BE"))||(!strcasecmp(name,"UTF16BE"))) return ID3_ENCODING_UTF16BE; +#endif /* HAVE_LIBRCC */ + + return ID3_ENCODING_ISO_8859_1; +} diff --git a/source/rcc.h b/source/rcc.h new file mode 100644 index 0000000..d5bc9b2 --- /dev/null +++ b/source/rcc.h @@ -0,0 +1,32 @@ +#ifndef _XMMS_CHARSET_H +#define _XMMS_CHARSET_H + +typedef enum xmms_rcc_class_t { + XMMS_RCC_ID3 = 0, + XMMS_RCC_ID3V2, + XMMS_RCC_PL, + XMMS_RCC_PLFS, + XMMS_RCC_FS, + XMMS_RCC_OUT, + XMMS_RCC_CTYPE, + XMMS_RCC_UTF8 +} xmms_rcc_class; + +void xmms_rcc_init(); +void xmms_rcc_free(); +void xmms_rcc_prefswin_create(void *prefswin_notebook); +void xmms_rcc_prefswin_apply(); + +char *xmms_rcc_fs2pl(const char *fnstring, const char *filename); +char *xmms_rcc_get(xmms_rcc_class charset, const char *buf); +char *xmms_rcc_put(xmms_rcc_class charset, const char *buf); +char *xmms_rcc_sized_put(xmms_rcc_class charset, const char *buf, int size); +char *xmms_rcc_recode(xmms_rcc_class from, xmms_rcc_class to, const char *buf); +char *xmms_rcc_sized_recode(xmms_rcc_class from, xmms_rcc_class to, const char *buf, int size); +char *xmms_rcc_fs(xmms_rcc_class from, xmms_rcc_class to, const char *fspath, const char *path, const char *filename); + +const char *xmms_rcc_string(const char *buf); +const char *xmms_rcc_get_language(); +int xmms_rcc_get_id3v2_encoding(); + +#endif /* _XMMS_CHARSET_H */ diff --git a/source/rcc_langs.h b/source/rcc_langs.h new file mode 100644 index 0000000..70abebf --- /dev/null +++ b/source/rcc_langs.h @@ -0,0 +1,120 @@ +typedef struct xmms_rcc_langs_t { + const char *sn; + const char *name; +} xmms_rcc_langs; + +static const char *default_lang = "XXX"; +static xmms_rcc_langs langs[] = { + { "aa", "aar" }, + { "ab", "abk" }, + { "af", "afr" }, + { "ak", "aka" }, + { "am", "amh" }, + { "ar", "ara" }, + { "an", "arg" }, + { "as", "asm" }, + { "av", "ava" }, + { "ae", "ave" }, + { "ay", "aym" }, + { "ba", "bak" }, + { "bm", "bam" }, + { "bn", "ben" }, + { "bh", "bih" }, + { "bi", "bis" }, + { "bs", "bos" }, + { "br", "bre" }, + { "bg", "bul" }, + { "ch", "cha" }, + { "cv", "chv" }, + { "kw", "cor" }, + { "co", "cos" }, + { "cr", "cre" }, + { "dv", "div" }, + { "dz", "dzo" }, + { "en", "eng" }, + { "et", "est" }, + { "fj", "fij" }, + { "fi", "fin" }, + { "fy", "fry" }, + { "ff", "ful" }, + { "ig", "ibo" }, + { "io", "ido" }, + { "iu", "iku" }, + { "ie", "ile" }, + { "ik", "ipk" }, + { "it", "ita" }, + { "jv", "jav" }, + { "ja", "jpn" }, + { "kn", "kan" }, + { "ks", "kas" }, + { "kr", "kau" }, + { "kk", "kaz" }, + { "km", "khm" }, + { "rw", "kin" }, + { "ky", "kir" }, + { "kv", "kom" }, + { "kg", "kon" }, + { "ku", "kur" }, + { "lo", "lao" }, + { "la", "lat" }, + { "lv", "lav" }, + { "ln", "lin" }, + { "lt", "lit" }, + { "lg", "lug" }, + { "mh", "mah" }, + { "ml", "mal" }, + { "mr", "mar" }, + { "mg", "mlg" }, + { "mt", "mlt" }, + { "mo", "mol" }, + { "mn", "mon" }, + { "na", "nau" }, + { "ng", "ndo" }, + { "oj", "oji" }, + { "or", "ori" }, + { "om", "orm" }, + { "pi", "pli" }, + { "ps", "pus" }, + { "qu", "que" }, + { "rn", "run" }, + { "ru", "rus" }, + { "sg", "sag" }, + { "sa", "san" }, + { "sn", "sna" }, + { "sd", "snd" }, + { "so", "som" }, + { "sc", "srd" }, + { "ss", "ssw" }, + { "sw", "swa" }, + { "ty", "tah" }, + { "ta", "tam" }, + { "tg", "tgk" }, + { "tl", "tgl" }, + { "ti", "tir" }, + { "tn", "tsn" }, + { "ts", "tso" }, + { "tr", "tur" }, + { "tw", "twi" }, + { "uk", "ukr" }, + { "ur", "urd" }, + { "uz", "uzb" }, + { "vi", "vie" }, + { "wa", "wln" }, + { "wo", "wol" }, + { "xh", "xho" }, + { "yi", "yid" }, + { "yo", "yor" }, + { "zu", "zul" }, + { NULL, NULL } +}; + +const char *xmms_rcc_get_639_2_name(const char *sn) { + unsigned int i; + + if ((!sn)||(!strcasecmp(sn, "off"))) return default_lang; + + for (i=0; langs[i].sn; i++) + if (!strcasecmp(sn, langs[i].sn)) return langs[i].name; + + return default_lang; +} |