summaryrefslogtreecommitdiffstats
path: root/patches/xmms
diff options
context:
space:
mode:
Diffstat (limited to 'patches/xmms')
-rw-r--r--patches/xmms/extra/xmms-ds-mpg123-wrongencoding.patch157
-rw-r--r--patches/xmms/plugins/xmms-ds-mpg123-editor-keys.patch164
-rw-r--r--patches/xmms/plugins/xmms-ds-mpg123-editor.patch202
-rw-r--r--patches/xmms/plugins/xmms-ds-mpg123.patch20
-rw-r--r--patches/xmms/plugins/xmms-ds-vorbis-editor-keys.patch78
-rw-r--r--patches/xmms/plugins/xmms-ds-vorbis-editor.patch51
-rw-r--r--patches/xmms/xmms-ds-playlist.patch526
-rw-r--r--patches/xmms/xmms-ds-rusxmms-charset.patch87
-rw-r--r--patches/xmms/xmms-ds-rusxmms.patch172
-rw-r--r--patches/xmms/xmms-ds-shade.patch194
-rw-r--r--patches/xmms/xmms-ds-textbox.patch31
11 files changed, 1682 insertions, 0 deletions
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);