changeset 2890:5e97b55f87cf

Manual merge to fix repository breakage.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 12 Aug 2008 20:40:31 +0300
parents 7c7471554d88 (diff) 6c53f9fa9029 (current diff)
children c27da2c06805 aa6acdb93c1e
files src/bluetooth/bluetooth.c src/bluetooth/bluetooth.h src/bluetooth/scan_gui.c src/bluetooth/scan_gui.h
diffstat 44 files changed, 731 insertions(+), 513 deletions(-) [+]
line wrap: on
line diff
--- a/acinclude.m4	Tue Aug 12 20:29:49 2008 +0300
+++ b/acinclude.m4	Tue Aug 12 20:40:31 2008 +0300
@@ -91,18 +91,18 @@
 
 dnl ** Check for GNU make
 AC_DEFUN([AUD_CHECK_GNU_MAKE],[
-    AC_CACHE_CHECK([for GNU make],cv_gnu_make_command,[
-    cv_gnu_make_command=""
+    AC_CACHE_CHECK([for GNU make],_cv_gnu_make_command,[
+    _cv_gnu_make_command=""
     for a in "$MAKE" make gmake gnumake; do
         test "x$a" = "x" && continue
         if ( sh -c "$a --version" 2>/dev/null | grep "GNU Make" >/dev/null ) ; then
-            cv_gnu_make_command="$a"
+            _cv_gnu_make_command="$a"
             break
         fi
     done
     ])
-    if test "x$cv_gnu_make_command" != "x" ; then
-        MAKE="$cv_gnu_make_command"
+    if test "x$_cv_gnu_make_command" != "x" ; then
+        MAKE="$_cv_gnu_make_command"
     else
         AC_MSG_ERROR([** GNU make not found. If it is installed, try setting MAKE environment variable. **])
     fi
@@ -206,6 +206,7 @@
 int main()
 {
   _mm_setzero_pd();
+  asm volatile("xorpd %xmm0,%xmm0\n\t");
   return 0;
 }
     ],[
--- a/buildsys.mk.in	Tue Aug 12 20:29:49 2008 +0300
+++ b/buildsys.mk.in	Tue Aug 12 20:40:31 2008 +0300
@@ -102,7 +102,7 @@
 		case $$i in \
 			*.o) \
 				test $$i -nt .deps && regen=1; \
-				deps="$${deps%.o}.dep $$i"; \
+				deps="$${deps} $${i%.o}.dep"; \
 				;; \
 		esac; \
 	done; \
--- a/src/OSS/OSS.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/OSS/OSS.c	Tue Aug 12 20:40:31 2008 +0300
@@ -27,31 +27,31 @@
 
 OSSConfig oss_cfg;
 
+static GtkWidget *about_dialog = NULL;
+
 static void oss_about(void)
 {
-    static GtkWidget *dialog;
-
-    if (dialog != NULL)
+    if (about_dialog != NULL)
         return;
 
-    dialog = audacious_info_dialog(_("About OSS Driver"),
-                               _("Audacious OSS Driver\n\n "
-                                 "This program is free software; you can redistribute it and/or modify\n"
-                                 "it under the terms of the GNU General Public License as published by\n"
-                                 "the Free Software Foundation; either version 2 of the License, or\n"
-                                 "(at your option) any later version.\n"
-                                 "\n"
-                                 "This program is distributed in the hope that it will be useful,\n"
-                                 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-                                 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
-                                 "GNU General Public License for more details.\n"
-                                 "\n"
-                                 "You should have received a copy of the GNU General Public License\n"
-                                 "along with this program; if not, write to the Free Software\n"
-                                 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
-                                 "USA."), _("Ok"), FALSE, NULL, NULL);
-    g_signal_connect(G_OBJECT(dialog), "destroy",
-                     G_CALLBACK(gtk_widget_destroyed), &dialog);
+    about_dialog = audacious_info_dialog(_("About OSS Driver"),
+    _("Audacious OSS Driver\n\n "
+    "This program is free software; you can redistribute it and/or modify\n"
+    "it under the terms of the GNU General Public License as published by\n"
+    "the Free Software Foundation; either version 2 of the License, or\n"
+    "(at your option) any later version.\n"
+    "\n"
+    "This program is distributed in the hope that it will be useful,\n"
+    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+    "GNU General Public License for more details.\n"
+    "\n"
+    "You should have received a copy of the GNU General Public License\n"
+    "along with this program; if not, write to the Free Software\n"
+    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
+    "USA."), _("Ok"), FALSE, NULL, NULL);
+    g_signal_connect(G_OBJECT(about_dialog), "destroy",
+                     G_CALLBACK(gtk_widget_destroyed), &about_dialog);
 }
 
 static void oss_init(void)
--- a/src/OSS/configure.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/OSS/configure.c	Tue Aug 12 20:40:31 2008 +0300
@@ -72,6 +72,7 @@
         if (oss_cfg.alt_mixer_device[0] != '/')
             oss_cfg.use_alt_mixer_device = FALSE;
 
+    /* Save configuration */
     db = aud_cfg_db_open();
 
     aud_cfg_db_set_int(db, "OSS", "audio_device", oss_cfg.audio_device);
--- a/src/aac/libfaad2/ic_predict.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/aac/libfaad2/ic_predict.c	Tue Aug 12 20:40:31 2008 +0300
@@ -52,9 +52,9 @@
         tmp2 = tmp;                             /* add 1 lsb and elided one */
         tmp &= (uint32_t)0xff800000;       /* extract exponent and sign */
         
-        *pf = *(float32_t*)(void*)&tmp1 + *(float32_t*)(void*)&tmp2 - *(float32_t*)(void*)&tmp;
+        *pf = (float32_t)tmp1 + (float32_t)tmp2 - (float32_t)tmp;
     } else {
-        *pf = *(float32_t*)(void*)&tmp;
+        *pf = (float32_t)tmp;
     }
 }
 
--- a/src/adplug/core/adlibemu.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/adplug/core/adlibemu.c	Tue Aug 12 20:40:31 2008 +0300
@@ -144,7 +144,7 @@
 
     ftol(ctc->t+modulator,&i);
 
-    if (*(long *)&ctc->amp <= 0x37800000)
+    if ((long)ctc->amp <= 0x37800000)
     {
 	ctc->amp = 0;
 	ctc->cellfunc = docell4;
@@ -160,7 +160,7 @@
 
     ftol(ctc->t+modulator,&i);
 
-    if ((*(long *)&ctc->amp) <= (*(long *)&ctc->sustain))
+    if ((long)ctc->amp <= (long)ctc->sustain)
     {
 	if (ctc->flags&32)
 	{
@@ -183,7 +183,7 @@
     ftol(ctc->t+modulator,&i);
 
     ctc->amp = ((ctc->a3*ctc->amp + ctc->a2)*ctc->amp + ctc->a1)*ctc->amp + ctc->a0;
-    if ((*(long *)&ctc->amp) > 0x3f800000)
+    if ((long)ctc->amp > 0x3f800000)
     {
 	ctc->amp = 1;
 	ctc->cellfunc = docell1;
--- a/src/adplug/core/fmc.cxx	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/adplug/core/fmc.cxx	Tue Aug 12 20:40:31 2008 +0300
@@ -130,6 +130,7 @@
         if (tracks[t][k].command == 0x0E)   // 0x0E (14): Retrig
           tracks[t][k].param1 = 3;
         if (tracks[t][k].command == 0x1A)   // 0x1A (26): Volume Slide
+        {
           if (tracks[t][k].param1 > tracks[t][k].param2)
           {
             tracks[t][k].param1 -= tracks[t][k].param2;
@@ -140,6 +141,7 @@
             tracks[t][k].param2 -= tracks[t][k].param1;
             tracks[t][k].param1 = 0;
           }
+        }
       }
 
       t++;
--- a/src/adplug/core/mid.cxx	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/adplug/core/mid.cxx	Tue Aug 12 20:40:31 2008 +0300
@@ -328,11 +328,13 @@
     break;
   case 0x84:
     if (s[1] == 0x00 && load_sierra_ins (filename, fp))
+    {
       if (s[2] == 0xf0)
         good = FILE_ADVSIERRA;
       else
         good = FILE_SIERRA;
     break;
+    }
   default:
     if (s[4] == 'A' && s[5] == 'D')
       good = FILE_OLDLUCAS;
@@ -900,10 +902,12 @@
   midiprintf ("\n");
   for (i = 0; i < 16; i++)
     if (track[i].on)
+    {
       if (track[i].pos < track[i].tend)
         midiprintf ("<%d>", track[i].iwait);
       else
         midiprintf ("stop");
+    }
 
   /*
      if (ret==0 && type==FILE_ADVSIERRA)
--- a/src/adplug/core/s3m.cxx	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/adplug/core/s3m.cxx	Tue Aug 12 20:40:31 2008 +0300
@@ -212,15 +212,19 @@
         tone_portamento (realchan, channel[realchan].dualinfo);
     case 4:
       if (info <= 0x0f)         // volume slide down
+      {
         if (channel[realchan].vol - info >= 0)
           channel[realchan].vol -= info;
         else
           channel[realchan].vol = 0;
+      }
       if ((info & 0x0f) == 0)   // volume slide up
+      {
         if (channel[realchan].vol + (info >> 4) <= 63)
           channel[realchan].vol += info >> 4;
         else
           channel[realchan].vol = 63;
+      }
       setvolume (realchan);
       break;
     case 5:
@@ -323,6 +327,7 @@
       // set channel values
       donote = 0;
       if (pattern[pattnr][row][chan].note < 14)
+      {
         // tone portamento
         if (pattern[pattnr][row][chan].command == 7
             || pattern[pattnr][row][chan].command == 12)
@@ -339,6 +344,7 @@
           channel[realchan].key = 1;
           donote = 1;
         }
+      }
       if (pattern[pattnr][row][chan].note == 14)
       {                         // key off (is 14 here, cause note is only first 4 bits)
         channel[realchan].key = 0;
@@ -371,10 +377,12 @@
           donote = 1;
       }
       if (pattern[pattnr][row][chan].volume != 255)
+      {
         if (pattern[pattnr][row][chan].volume < 64) // set volume
           channel[realchan].vol = pattern[pattnr][row][chan].volume;
         else
           channel[realchan].vol = 63;
+      }
       channel[realchan].fx = pattern[pattnr][row][chan].command;    // set command
       if (pattern[pattnr][row][chan].info)  // set infobyte
         channel[realchan].info = pattern[pattnr][row][chan].info;
@@ -420,15 +428,19 @@
         break;                  // pattern break
       case 4:
         if (info > 0xf0)        // fine volume down
+        {
           if (channel[realchan].vol - (info & 0x0f) >= 0)
             channel[realchan].vol -= info & 0x0f;
           else
             channel[realchan].vol = 0;
+        }
         if ((info & 0x0f) == 0x0f && info >= 0x1f)  // fine volume up
+        {
           if (channel[realchan].vol + ((info & 0xf0) >> 4) <= 63)
             channel[realchan].vol += (info & 0xf0) >> 4;
           else
             channel[realchan].vol = 63;
+        }
         setvolume (realchan);
         break;
       case 5:
@@ -468,6 +480,7 @@
         if (info == 0xb0)       // set loop start
           loopstart = row;
         if (info > 0xb0 && info <= 0xbf)    // pattern loop
+        {
           if (!loopcnt)
           {
             loopcnt = info & 0x0f;
@@ -479,6 +492,7 @@
             crow = loopstart;
             pattbreak = 1;
           }
+        }
         if ((info & 0xf0) == 0xe0)  // patterndelay
           del = speed * (info & 0x0f) - 1;
         break;
--- a/src/bluetooth/Makefile	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/Makefile	Tue Aug 12 20:40:31 2008 +0300
@@ -1,9 +1,8 @@
 PLUGIN = bluetooth${PLUGIN_SUFFIX}
 
-SRCS = bluetooth.c gui.c marshal.c scan_gui.c agent.c
+SRCS = bluetooth.c gui.c marshal.c scan_gui.c agent.c 
 include ../../buildsys.mk
 include ../../extra.mk
-
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${BEEP_DEFINES} ${MOWGLI_CFLAGS} ${DBUS_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${DBUS_GLIB_CFLAGS} ${PANGO_CFLAGS} -I../../intl -I../.. ${BLUEZ_CFLAGS}
--- a/src/bluetooth/agent.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/agent.c	Tue Aug 12 20:40:31 2008 +0300
@@ -27,8 +27,8 @@
 #include "agent.h"
 #include "gui.h"
 
-#define PASSKEY_AGENT_PATH	"/org/bluez/audacious_passkey"
-#define AUTH_AGENT_PATH		"/org/bluez/audacious_auth"
+#define PASSKEY_AGENT_PATH	"/org/bluez/passkey_agent"
+#define AUTH_AGENT_PATH		"/org/bluez/auth_agent"
 
 static GtkWidget *agent_window = NULL;
 static GtkWidget *window_box = NULL;
@@ -40,7 +40,7 @@
 static GtkWidget *passkey_entry = NULL;
 static GtkWidget *ok_button = NULL;
 static GtkWidget *cancel_button = NULL;
-static char* passkey;
+static const char* passkey;
 static GList *adapter_list = NULL;
 DBusGProxy *pair_obj = NULL;
 
@@ -199,62 +199,13 @@
         GError *error;
         error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
                 "Pairing request rejected");
+        printf("passkey error\n");
         dbus_g_method_return_error(input->context, error);
     }
 
     input_free(input);
-}
-
-static void confirm_callback(gint response, gpointer user_data)
-{
-    struct input_data *input = user_data;
-
-    if (response != GTK_RESPONSE_YES) {
-        GError *error;
-        error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
-                "Confirmation request rejected");
-        dbus_g_method_return_error(input->context, error);
-    } else
-        dbus_g_method_return(input->context);
-
-    input_free(input);
-}
-
-static void set_trusted(struct input_data *input)
-{
-    DBusGProxy *object;
-    gboolean active;
-
-    //aways set trusted -- we dont have yet an active button -
-    //maybe I'll add one	
-    object = dbus_g_proxy_new_for_name(connection, "org.bluez",
-            input->path, "org.bluez.Adapter");
-
-    dbus_g_proxy_call(object, "SetTrusted", NULL,
-            G_TYPE_STRING, input->address, G_TYPE_INVALID,
-            G_TYPE_INVALID);
-}
-
-static void auth_callback(gint response, gpointer user_data)
-{
-
-    /* I must call this function with the alway allow option and 
-     * don't boder to aks the user - to many questions 
-     */
-    struct input_data *input = user_data;
-
-    if (response == GTK_RESPONSE_YES) {
-        set_trusted(input);
-        dbus_g_method_return(input->context);
-    } else {
-        GError *error;
-        error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
-                "Authorization request rejected");
-        dbus_g_method_return_error(input->context, error);
-    }
-
-    input_free(input);
-}
+    printf("return\n");
+ }
 
 
 static void passkey_dialog(const char *path, const char *address,
@@ -271,26 +222,6 @@
 
     input->context = context;
 
-
-
-    /*
-       g_signal_connect(G_OBJECT(entry), "changed",
-       G_CALLBACK(changed_callback), input);
-
-
-       g_signal_connect(G_OBJECT(button), "toggled",
-       G_CALLBACK(toggled_callback), input);
-
-       gtk_container_add(GTK_CONTAINER(vbox), button);
-
-       input_list = g_list_append(input_list, input);
-
-       g_signal_connect(G_OBJECT(dialog), "response",
-       G_CALLBACK(passkey_callback), input);
-
-       enable_blinking();
-       */
-    printf("passkey callback\n");
     passkey_callback(GTK_RESPONSE_ACCEPT,input);
 
 
@@ -300,7 +231,8 @@
         const char *value, const gchar *device,
         DBusGMethodInvocation *context)
 {
-    struct input_data *input;
+   printf("confirm dialog \n");
+   struct input_data *input;
 
     input = g_try_malloc0(sizeof(*input));
     if (!input)
@@ -310,8 +242,6 @@
     input->address = g_strdup(address);
 
     input->context = context;
-
-printf("confirm dialog\n");
     //	g_signal_connect(G_OBJECT(dialog), "response",
     //				G_CALLBACK(confirm_callback), input);
 
@@ -339,10 +269,11 @@
     /* translators: Whether to grant access to a particular service
      * to the device mentioned */
 
-    //	g_signal_connect(G_OBJECT(dialog), "response",
-    //				G_CALLBACK(auth_callback), input);
+   /* 	g_signal_connect(G_OBJECT(dialog), "response",
+    				G_CALLBACK(auth_callback), input);
 
-    //enable_blinking();
+    enable_blinking();
+    */
 }
 
 typedef struct {
@@ -392,9 +323,6 @@
     g_printf("new passkey agent \n");
     return agent;
 }
-
-
-
 static gboolean passkey_agent_request(PasskeyAgent *agent,
         const char *path, const char *address,
         DBusGMethodInvocation *context)
@@ -441,6 +369,7 @@
         const char *path, const char *address,
         const char *value, DBusGMethodInvocation *context)
 {
+    printf("passkey agent confirm \n");
     DBusGProxy *object;
     const char *adapter = NULL, *name = NULL;
     gchar *device, *line;
@@ -480,6 +409,7 @@
 static gboolean passkey_agent_cancel(PasskeyAgent *agent,
         const char *path, const char *address, GError **error)
 {
+    printf("passkey agent cancel \n");
     GList *list;
     GError *result;
     struct input_data *input;
@@ -516,6 +446,7 @@
 
 static gboolean passkey_agent_release(PasskeyAgent *agent, GError **error)
 {
+    printf("pass agent release \n");
     registered_passkey = 0;
 
     return TRUE;
@@ -574,6 +505,7 @@
         const char *path, const char *address, const char *service,
         const char *uuid, DBusGMethodInvocation *context)
 {
+    printf("auth agent authorize \n");
     DBusGProxy *object;
     const char *adapter = NULL, *name = NULL;
     gchar *device, *profile, *line;
@@ -721,6 +653,7 @@
 
 int setup_agents(DBusGConnection *conn)
 {
+    printf("setup agents\n");
     void *agent;
 
     connection = dbus_g_connection_ref(conn);
@@ -743,6 +676,7 @@
 
 void cleanup_agents(void)
 {
+    printf("clean up agents \n");
     unregister_agents();
 
     dbus_g_connection_unref(connection);
@@ -766,6 +700,8 @@
 static void bonding_created(DBusGProxy *object,
 				const char *address, gpointer user_data)
 {
+    bonded_dev_mutex = g_mutex_new (); 
+
 	const char *adapter = NULL, *name = NULL;
 	gchar *device, *text;
 
@@ -783,6 +719,10 @@
 			device = g_strdup_printf("%s (%s)", name, address);
 	} else
 		device = g_strdup(address);
+    
+    g_mutex_lock(bonded_dev_mutex);
+    bonded_dev = g_strdup_printf(address);
+    g_mutex_unlock(bonded_dev_mutex);
 
 	text = g_strdup_printf(_("Created bonding with %s"), device);
     bonding_finish = 1;
@@ -816,6 +756,7 @@
 	text = g_strdup_printf(_("Removed bonding with %s"), device);
 
 	g_free(device);
+    printf("bonding removed");
 
 //	show_notification(adapter ? adapter : _("Bluetooth device"),
 //						text, NULL, 6000, NULL);
@@ -887,7 +828,7 @@
 
 	set_new_mode(adapter, mode);
 }
-
+/*
 static void adapter_free(gpointer data, gpointer user_data)
 {
 	struct adapter_data *adapter = data;
@@ -905,6 +846,7 @@
 
 	adapter->attached = 0;
 }
+*/
 
 static gint adapter_compare(gconstpointer a, gconstpointer b)
 {
@@ -913,7 +855,7 @@
 
 	return g_ascii_strcasecmp(adapter->path, path);
 }
-
+/*
 static void adapter_count(gpointer data, gpointer user_data)
 {
 	struct adapter_data *adapter = data;
@@ -923,7 +865,7 @@
 		(*count)++;
 }
 
-
+*/
 
 
 void add_bonding(){
--- a/src/bluetooth/bluetooth.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/bluetooth.c	Tue Aug 12 20:40:31 2008 +0300
@@ -16,17 +16,21 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses>.
  */
 
+#include <glib/gstdio.h>
+#include <errno.h>
+#include <string.h>
 #include "bluetooth.h"
 #include "marshal.h"
 #include "gui.h"
 #include "scan_gui.h"
 #include "agent.h"
+#include <audacious/plugin.h>
 #define DEBUG 1
-static gboolean plugin_active = FALSE,exiting=FALSE;
 GList * current_device = NULL;
 gint config = 0;
 gint devices_no = 0;
 GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+static gchar *current_address=NULL;
 static GThread *connect_th;
 void bluetooth_init ( void );
 void bluetooth_cleanup ( void );
@@ -39,8 +43,8 @@
 static void discovery_completed(DBusGProxy *object, gpointer user_data);
 void discover_devices(void);
 void disconnect_dbus_signals(void);
-
-
+/*static void show_restart_dialog(void); */
+static void remove_bonding();
 GeneralPlugin bluetooth_gp =
 {
     .description = "Bluetooth audio support",
@@ -63,21 +67,31 @@
 void bluetooth_cleanup ( void )
 {
     printf("bluetooth: exit\n");
-    if (config ==1 ){
+    if (config ==1 )
+    {
         close_window();
         config =0;
     }
+    remove_bonding();
     if(discover_finish == 2) {
         dbus_g_connection_flush (bus);
         dbus_g_connection_unref(bus);
         disconnect_dbus_signals();
 
     }
+    /* switching back to default pcm device at cleanup */
+    mcs_handle_t *cfgfile = aud_cfg_db_open();
+    aud_cfg_db_set_string(cfgfile,"ALSA","pcm_device", "default");
+    aud_cfg_db_close(cfgfile);
+
 }
 
 void bt_about( void )
 {
     printf("about call\n");
+    dbus_g_object_register_marshaller(marshal_VOID__STRING_UINT_INT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT, G_TYPE_INVALID);    
+    dbus_g_proxy_call(obj,"RemoveBonding",NULL,G_TYPE_STRING,((DeviceData*)(selected_dev->data))->address,G_TYPE_INVALID,G_TYPE_INVALID); 
+
 }
 
 void bt_cfg(void)
@@ -105,14 +119,20 @@
 
 }
 
-void clean_devices_list(){
+void clean_devices_list()
+{
     g_list_free(audio_devices);
     dbus_g_connection_flush (bus);
     dbus_g_connection_unref(bus);
     audio_devices = NULL;
     //g_list_free(current_device);
 }
+static void remove_bonding()
+{
+    dbus_g_object_register_marshaller(marshal_VOID__STRING_UINT_INT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT, G_TYPE_INVALID);
+    dbus_g_proxy_call(obj,"RemoveBonding",NULL,G_TYPE_STRING,bonded_dev,G_TYPE_INVALID,G_TYPE_INVALID); 
 
+}
 void refresh_call(void)
 {
     printf("refresh function called\n");
@@ -136,18 +156,96 @@
 
     dbus_g_object_register_marshaller(marshal_VOID__STRING_UINT_INT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT, G_TYPE_INVALID);
     run_agents();
-    dbus_g_proxy_call(obj,"CreateBonding",NULL,G_TYPE_STRING,((DeviceData*)(selected_dev->data))->address,G_TYPE_INVALID,G_TYPE_INVALID); 
-     
+    close_call();
+    show_scan(1);
+
+    dbus_g_proxy_call(obj,"CreateBonding",NULL,G_TYPE_STRING,current_address,G_TYPE_INVALID,G_TYPE_INVALID); 
+    return NULL;
 }
 void connect_call(void)
 {
- connect_th = g_thread_create((GThreadFunc)connect_call_th,NULL,TRUE,NULL) ; 
- close_call();
- close_window();
- show_scan(1);
+    current_address = g_strdup(((DeviceData*)(selected_dev->data))->address);
+    connect_th = g_thread_create((GThreadFunc)connect_call_th,NULL,TRUE,NULL) ; 
+    close_call();
+    close_window();
+    show_scan(1);
 }
 
 
+void play_call()
+{
+
+    FILE *file;
+    FILE *temp_file;
+    gint prev=0;
+    char line[128];
+    const gchar *home;
+    gchar *device_line;
+    gchar *file_name="";
+    gchar *temp_file_name;
+    home = g_get_home_dir();
+    file_name = g_strconcat(home,"/.asoundrc",NULL);
+    temp_file_name = g_strconcat(home,"/temp_bt",NULL);
+    file = fopen(file_name,"r");
+    temp_file = fopen(temp_file_name,"w");
+    device_line = g_strdup_printf("device %s\n",current_address);
+    if ( file != NULL )
+    {
+        while ( fgets ( line, sizeof line, file ) != NULL )
+        {
+            if(!(strcmp(line,"pcm.audacious_bt{\n"))){
+                fputs(line,temp_file);
+                fgets ( line, sizeof line, file ); /* type bluetooth */
+                fputs(line,temp_file);
+                fgets ( line, sizeof line, file ); /* device MAC */
+                fputs(device_line,temp_file);
+                prev = 1;
+            } else 
+                fputs(line,temp_file);
+        }
+
+        fclose (file);
+    }
+    if(!prev){
+        fputs("pcm.audacious_bt{\n",temp_file);
+        fputs("type bluetooth\n",temp_file);
+        fputs(device_line,temp_file);
+        fputs("}\n",temp_file);
+        prev = 0;
+    }
+
+    fclose(temp_file);
+    int err = rename(temp_file_name,file_name);
+    printf("rename error : %d",err);
+    perror("zz");
+    g_free(device_line);
+    g_free(file_name);
+    g_free(temp_file_name);
+    mcs_handle_t *cfgfile = aud_cfg_db_open();
+    aud_cfg_db_set_string(cfgfile,"ALSA","pcm_device", "audacious_bt");
+    aud_cfg_db_close(cfgfile);
+
+    printf("play callback\n");
+    close_window();
+    aud_output_plugin_cleanup();
+    audacious_drct_stop();
+    audacious_drct_play();
+
+
+}
+/*static void show_restart_dialog()
+{
+    static GtkWidget *window = NULL;
+    GtkWidget *dialog;
+    dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+            GTK_MESSAGE_INFO,
+            GTK_BUTTONS_OK,
+            "Please restart the player to apply the bluetooth audio settings!");
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_destroy (dialog);
+}
+*/
 static void remote_device_found(DBusGProxy *object, char *address, const unsigned int class, const int rssi, gpointer user_data)
 {
     int found_in_list=FALSE; 
--- a/src/bluetooth/bluetooth.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/bluetooth.h	Tue Aug 12 20:40:31 2008 +0300
@@ -28,7 +28,9 @@
 #include <dbus/dbus-glib.h>
 #include <glib-object.h>
 #include <stdio.h>
-
+#include <audacious/configdb.h>
+#include <audacious/i18n.h>
+#include <audacious/util.h>
 #include "gui.h"
 typedef struct {
     guint class;
@@ -40,9 +42,11 @@
 
 void refresh_call(void);
 void connect_call(void);
+void play_call(void);
 GList * audio_devices;
 gint discover_finish ;
 DBusGConnection * bus;
 DBusGProxy * obj;
+gchar *bonded_dev;
+GMutex *bonded_dev_mutex;
 
-
--- a/src/bluetooth/gui.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/gui.c	Tue Aug 12 20:40:31 2008 +0300
@@ -84,8 +84,7 @@
     GtkTreeIter iter;
     gint dev_no=0;
     GList *dev;
-    gchar *temp;
-    if(!window) 
+      if(!window) 
         return NULL;
     /* create list store */
     store = gtk_list_store_new(NUM_COLUMNS,
@@ -118,12 +117,12 @@
                 ((DeviceData*)(dev->data))-> name,-1);
         dev = g_list_next(dev);
     }
-    //set the labels
-    //   temp = g_strdup_printf("0x%x",((DeviceData*)(dev->data))->class);
+    /*set the labels */
+    /*   temp = g_strdup_printf("0x%x",((DeviceData*)(dev->data))->class); */
     gtk_label_set_text(GTK_LABEL(label_prod),((DeviceData*)(dev->data))->name);
-    //    gtk_label_set_text(GTK_LABEL(label_class),temp);
+    /*    gtk_label_set_text(GTK_LABEL(label_class),temp); */
     gtk_label_set_text(GTK_LABEL(label_address),((DeviceData*)(dev->data))->address);
-    g_free(temp);
+   /* g_free(temp); */
     return GTK_TREE_MODEL(store);          
 
 }
@@ -187,14 +186,14 @@
         }else 
             gtk_label_set_text(GTK_LABEL(label_prod),status);
         g_free(status);
-
+        gtk_widget_set_sensitive(connect_button,TRUE);
     }
 }
 
 void refresh_resultsui(){
     gtk_widget_destroy (window);
     window = NULL;
-    selected_dev = NULL;
+selected_dev = NULL;
     refresh_call();
 }
 
@@ -232,6 +231,8 @@
         connect_button = gtk_button_new_with_mnemonic(_("_Connect"));
         g_signal_connect(connect_button,"clicked",G_CALLBACK (connect_call), NULL);
         gtk_container_add(GTK_CONTAINER(hbox_bottom),connect_button);
+        gtk_widget_set_sensitive(connect_button,FALSE);
+
 
         close_button = gtk_button_new_with_mnemonic(_("_Close"));
         g_signal_connect(close_button,"clicked",G_CALLBACK (close_call),NULL);
--- a/src/bluetooth/scan_gui.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/scan_gui.c	Tue Aug 12 20:40:31 2008 +0300
@@ -30,57 +30,62 @@
 static GtkWidget *rescan_buttton;
 static GtkWidget *close_button;
 static gint usage=0;
-
-gpointer progress() {
+void show_pairing_ok(void);
+gpointer progress()
+{
 
     for(;;){
         if(window){
             gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_bar));
         }
         sleep(1);
-       if(usage == 0){
-       if(discover_finish == 2 ) {            
-            if(window){
-                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar),1);
+        if(usage == 0){
+            if(discover_finish == 2 ) {            
+                if(window){
+                    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar),1);
+                    gtk_widget_set_sensitive(rescan_buttton,TRUE);
+                }
+                return 0;
             }
-            return 0;
+        }else 
+        {
+            if(bonding_finish == 1 ) {            
+                if(window){
+                    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar),1);
+                    show_pairing_ok();
+                    gtk_widget_set_sensitive(rescan_buttton,TRUE);
+
+                }
+                return 0;
+            }
         }
-       }else 
-           {
-                if(bonding_finish == 1 ) {            
-                    if(window){
-                        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar),1);
-                        show_pairing_ok();
-                    }
-                return 0;
-                }
-           }
     }
     return 0;
 }
 
 void show_pairing_ok()
 {
- if(window ){
+    if(window ){
         gtk_label_set_text(GTK_LABEL(scan_label),_("Bonding finish!"));
     }
 }
 
-void show_no_devices(){
+void show_no_devices()
+{
     if(window ){
         gtk_label_set_text(GTK_LABEL(scan_label),_("No devices found!"));
     }
 }
-void destroy_scan_window(){
+void destroy_scan_window()
+{
     gtk_widget_hide(window);
 }
-void close_window(void){
+void close_window(void)
+{
     printf("scan_gui close callback \n");
     gtk_widget_destroy (window);
     window = NULL;
 }
-
-
 void show_scan(gint use)
 {
     GThread *th1;
@@ -113,9 +118,9 @@
         if(usage == 0){
             scan_label = gtk_label_new_with_mnemonic(_("Scanning..."));
         }else
-            {
-                scan_label = gtk_label_new_with_mnemonic(_("Pairing..."));
-            }
+        {
+            scan_label = gtk_label_new_with_mnemonic(_("Pairing..."));
+        }
 
         gtk_container_add(GTK_CONTAINER(scanbox),scan_label);
 
@@ -129,8 +134,17 @@
         /* I have to modify the rescan button with a play one 
          * and treat the case when the bounding is not ok
          */
-        rescan_buttton = gtk_button_new_with_mnemonic(_("Rescan"));
-        g_signal_connect(rescan_buttton,"clicked",G_CALLBACK (refresh_call),NULL);
+        if(usage == 0){
+            rescan_buttton = gtk_button_new_with_mnemonic(_("Rescan"));
+            g_signal_connect(rescan_buttton,"clicked",G_CALLBACK (refresh_call),NULL);
+            gtk_widget_set_sensitive(rescan_buttton,FALSE);
+        }else{
+            rescan_buttton = gtk_button_new_with_mnemonic(_("Play"));
+            g_signal_connect(rescan_buttton,"clicked",G_CALLBACK (play_call),NULL);
+            gtk_widget_set_sensitive(rescan_buttton,FALSE);
+        }
+
+
 
         close_button = gtk_button_new_with_mnemonic(_("Close"));
         gtk_container_add(GTK_CONTAINER(buttonsbox),rescan_buttton);
--- a/src/bluetooth/scan_gui.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/bluetooth/scan_gui.h	Tue Aug 12 20:40:31 2008 +0300
@@ -18,6 +18,12 @@
 
 #include <gtk/gtk.h>
 #include <glib.h>
+#include <alsa/asoundlib.h>
+#include <alsa/pcm_plugin.h>
+#include <audacious/plugin.h>
+#include <audacious/i18n.h>
+
+
 void show_scan(gint use);
 void show_no_devices();
 void destroy_scan_window();
--- a/src/filewriter/Makefile	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/Makefile	Tue Aug 12 20:40:31 2008 +0300
@@ -4,7 +4,8 @@
        wav.c		\
        mp3.c		\
        vorbis.c		\
-       flac.c
+       flac.c           \
+       convert.c
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -13,4 +14,5 @@
 
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${GTK_CFLAGS}  ${MOWGLI_CFLAGS}  ${FILEWRITER_CFLAGS} ${OGG_VORBIS_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS}
+LDFLAGS += ${AUDLDFLAGS}
+LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS} -lSAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/filewriter/convert.c	Tue Aug 12 20:40:31 2008 +0300
@@ -0,0 +1,64 @@
+#include "convert.h"
+
+static SAD_dither_t *sad_state = NULL;
+gpointer convert_output = NULL;
+static gsize convert_output_length = 0;
+static gint nch;
+static AFormat in_fmt;
+static AFormat out_fmt;
+
+gboolean convert_init(AFormat input_fmt, AFormat output_fmt, gint channels)
+{
+    gint ret;
+    SAD_buffer_format input_sad_fmt;
+    SAD_buffer_format output_sad_fmt;
+
+
+    input_sad_fmt.sample_format = aud_sadfmt_from_afmt(input_fmt);
+    if (input_sad_fmt.sample_format < 0) return FALSE;
+    input_sad_fmt.fracbits = FMT_FRACBITS(input_fmt);
+    input_sad_fmt.channels = channels;
+    input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+    input_sad_fmt.samplerate = 0;
+
+    output_sad_fmt.sample_format = aud_sadfmt_from_afmt(output_fmt);
+    if (output_sad_fmt.sample_format < 0) return FALSE;
+    output_sad_fmt.fracbits = FMT_FRACBITS(output_fmt);
+    output_sad_fmt.channels = channels;
+    output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+    output_sad_fmt.samplerate = 0;
+
+    sad_state = SAD_dither_init(&input_sad_fmt, &output_sad_fmt, &ret);
+    if (sad_state == NULL) {
+        AUDDBG("ditherer init failed\n");
+        return FALSE;
+    }
+
+    in_fmt = input_fmt;
+    out_fmt = output_fmt;
+    nch = channels;
+
+    SAD_dither_set_dither(sad_state, FALSE);
+    return TRUE;
+}
+
+gint convert_process(gpointer ptr, gint length)
+{
+    gint frames, len;
+    frames = length / nch / FMT_SIZEOF(in_fmt);
+    len = frames * nch * FMT_SIZEOF(out_fmt);
+    
+    if (convert_output == NULL || convert_output_length < len)
+    {
+        convert_output_length = len;
+        convert_output = aud_smart_realloc(convert_output, &convert_output_length);
+    }
+
+    SAD_dither_process_buffer(sad_state, ptr, convert_output, frames);
+    return len;
+}
+
+void convert_free(void)
+{
+    if (sad_state != NULL) {SAD_dither_free(sad_state); sad_state = NULL;}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/filewriter/convert.h	Tue Aug 12 20:40:31 2008 +0300
@@ -0,0 +1,14 @@
+#ifndef CONVERT_H
+#define CONVERT_H
+
+#include "filewriter.h"
+
+gpointer convert_output;
+
+gboolean convert_init(AFormat input_fmt, AFormat output_fmt, gint channels);
+
+gint convert_process(gpointer ptr, gint length);
+
+void convert_free(void);
+
+#endif
--- a/src/filewriter/filewriter.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/filewriter.c	Tue Aug 12 20:40:31 2008 +0300
@@ -22,6 +22,7 @@
 
 #include "filewriter.h"
 #include "plugins.h"
+#include "convert.h"
 
 struct format_info input;
 
@@ -261,75 +262,20 @@
     if (!output_file)
         return 0;
 
+    convert_init(fmt, plugin.format_required, nch);
+
     rv = (plugin.open)();
 
     return rv;
 }
 
-static void convert_buffer(gpointer buffer, gint length)
-{
-    gint i;
-
-    if (input.format == FMT_S8)
-    {
-        guint8 *ptr1 = buffer;
-        gint8 *ptr2 = buffer;
-
-        for (i = 0; i < length; i++)
-            *(ptr1++) = *(ptr2++) ^ 128;
-    }
-    if (input.format == FMT_S16_BE)
-    {
-        gint16 *ptr = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr++)
-            *ptr = GUINT16_SWAP_LE_BE(*ptr);
-    }
-    if (input.format == FMT_S16_NE)
-    {
-        gint16 *ptr = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr++)
-            *ptr = GINT16_TO_LE(*ptr);
-    }
-    if (input.format == FMT_U16_BE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GINT16_TO_LE(GUINT16_FROM_BE(*ptr2) ^ 32768);
-    }
-    if (input.format == FMT_U16_LE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GINT16_TO_LE(GUINT16_FROM_LE(*ptr2) ^ 32768);
-    }
-    if (input.format == FMT_U16_NE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GINT16_TO_LE((*ptr2) ^ 32768);
-    }
-}
-
 static void file_write(void *ptr, gint length)
 {
-    if (input.format == FMT_S8 || input.format == FMT_S16_BE ||
-        input.format == FMT_U16_LE || input.format == FMT_U16_BE ||
-        input.format == FMT_U16_NE)
-        convert_buffer(ptr, length);
-#ifdef WORDS_BIGENDIAN
-    if (input.format == FMT_S16_NE)
-        convert_buffer(ptr, length);
-#endif
+    int len;
 
-    plugin.write(ptr, length);
+    len = convert_process(ptr, length);
+
+    plugin.write(convert_output, len);
 }
 
 static gint file_write_output(void *ptr, gint length)
@@ -340,6 +286,7 @@
 static void file_close(void)
 {
     plugin.close();
+    convert_free();
 
     if (output_file)
     {
--- a/src/filewriter/filewriter.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/filewriter.h	Tue Aug 12 20:40:31 2008 +0300
@@ -37,6 +37,8 @@
 #include <audacious/util.h>
 #include <audacious/vfs.h>
 
+#include <libSAD/libSAD.h>
+
 struct format_info { 
     AFormat format;
     int frequency;
@@ -65,6 +67,7 @@
     gint (*free)(void);
     gint (*playing)(void);
     gint (*get_written_time)(void);
+    AFormat format_required;
 };
 
 #endif
--- a/src/filewriter/flac.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/flac.c	Tue Aug 12 20:40:31 2008 +0300
@@ -44,7 +44,8 @@
     flac_close,
     flac_free,
     flac_playing,
-    flac_get_written_time
+    flac_get_written_time,
+    FMT_S16_NE
 };
 
 static FLAC__StreamEncoder *flac_encoder;
--- a/src/filewriter/mp3.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/mp3.c	Tue Aug 12 20:40:31 2008 +0300
@@ -50,7 +50,8 @@
     mp3_close,
     mp3_free,
     mp3_playing,
-    mp3_get_written_time
+    mp3_get_written_time,
+    FMT_S16_NE
 };
 
 static GtkWidget *configure_win = NULL;
--- a/src/filewriter/vorbis.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/vorbis.c	Tue Aug 12 20:40:31 2008 +0300
@@ -47,7 +47,8 @@
     vorbis_close,
     vorbis_free,
     vorbis_playing,
-    vorbis_get_written_time
+    vorbis_get_written_time,
+    FMT_S16_NE
 };
 
 static float v_base_quality = 0.5;
--- a/src/filewriter/wav.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/filewriter/wav.c	Tue Aug 12 20:40:31 2008 +0300
@@ -40,7 +40,8 @@
     wav_close,
     wav_free,
     wav_playing,
-    wav_get_written_time
+    wav_get_written_time,
+    FMT_S16_LE
 };
 
 
--- a/src/icecast/Makefile	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/icecast/Makefile	Tue Aug 12 20:40:31 2008 +0300
@@ -2,7 +2,8 @@
 
 SRCS = icecast.c		\
        ../filewriter/mp3.o	\
-       ../filewriter/vorbis.o
+       ../filewriter/vorbis.o	\
+       ../filewriter/convert.o
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -11,4 +12,5 @@
 
 CFLAGS += ${PLUGIN_CFLAGS} ${SHOUT_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${GTK_CFLAGS} ${PANGO_CFLAGS} ${MOWGLI_CFLAGS} ${DBUS_CFLAGS} ${FILEWRITER_CFLAGS} ${OGG_VORBIS_CFLAGS} ${SHOUT_CFLAGS} -I../../intl -I../..
-LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS} ${SHOUT_LIBS}
+LDFLAGS += ${AUDLDFLAGS}
+LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS} ${SHOUT_LIBS} -lSAD
--- a/src/icecast/icecast.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/icecast/icecast.c	Tue Aug 12 20:40:31 2008 +0300
@@ -24,6 +24,7 @@
 
 #include "../filewriter/filewriter.h"
 #include "../filewriter/plugins.h"
+#include "../filewriter/convert.h"
 #include <shout/shout.h>
 
 struct format_info input;
@@ -325,76 +326,21 @@
         }
     }
 
+    convert_init(fmt, plugin.format_required, nch);
+
     rv = (plugin.open)();
 
     g_debug("ICE_OPEN");
     return rv;
 }
 
-static void convert_buffer(gpointer buffer, gint length)
-{
-    gint i;
-
-    if (input.format == FMT_S8)
-    {
-        guint8 *ptr1 = buffer;
-        gint8 *ptr2 = buffer;
-
-        for (i = 0; i < length; i++)
-            *(ptr1++) = *(ptr2++) ^ 128;
-    }
-    if (input.format == FMT_S16_BE)
-    {
-        gint16 *ptr = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr++)
-            *ptr = GUINT16_SWAP_LE_BE(*ptr);
-    }
-    if (input.format == FMT_S16_NE)
-    {
-        gint16 *ptr = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr++)
-            *ptr = GINT16_TO_LE(*ptr);
-    }
-    if (input.format == FMT_U16_BE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GINT16_TO_LE(GUINT16_FROM_BE(*ptr2) ^ 32768);
-    }
-    if (input.format == FMT_U16_LE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GINT16_TO_LE(GUINT16_FROM_LE(*ptr2) ^ 32768);
-    }
-    if (input.format == FMT_U16_NE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GINT16_TO_LE((*ptr2) ^ 32768);
-    }
-}
-
 static void ice_write(void *ptr, gint length)
 {
-    if (input.format == FMT_S8 || input.format == FMT_S16_BE ||
-        input.format == FMT_U16_LE || input.format == FMT_U16_BE ||
-        input.format == FMT_U16_NE)
-        convert_buffer(ptr, length);
-#ifdef WORDS_BIGENDIAN
-    if (input.format == FMT_S16_NE)
-        convert_buffer(ptr, length);
-#endif
+    int len;
 
-    plugin.write(ptr, length);
+    len = convert_process(ptr, length);
+
+    plugin.write(convert_output, length);
 }
 
 static gint ice_real_write(void* ptr, gint length)
@@ -435,6 +381,7 @@
 static gboolean ice_real_close(gpointer data)
 {
     plugin.close();
+    convert_free();
 
     if (shout)
     {
--- a/src/skins/plugin.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/plugin.c	Tue Aug 12 20:40:31 2008 +0300
@@ -106,17 +106,16 @@
 
 gboolean skins_cleanup(void) {
     if (plugin_is_active == TRUE) {
+        gtk_widget_hide(mainwin);
+        gtk_widget_hide(equalizerwin);
+        gtk_widget_hide(playlistwin);
         skins_cfg_save();
+        cleanup_skins();
         skins_free_paths();
         ui_main_evlistener_dissociate();
         ui_playlist_evlistener_dissociate();
         skins_cfg_free();
-        gtk_widget_destroy(mainwin);
-        gtk_widget_destroy(equalizerwin);
-        gtk_widget_destroy(playlistwin);
         ui_manager_destroy();
-        skin_destroy(aud_active_skin);
-        aud_active_skin = NULL;
         mainwin = NULL;
         equalizerwin = NULL;
         playlistwin = NULL;
--- a/src/skins/ui_skin.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skin.c	Tue Aug 12 20:40:31 2008 +0300
@@ -1749,42 +1749,25 @@
                 gtk_widget_hide(widget);
                 return;
             }
-            gint x, y;
-            x = -1;
-            y = -1;
 
-            if (gtk_widget_get_parent(widget) == SKINNED_WINDOW(mainwin)->normal) {
-                GList *iter;
-                for (iter = GTK_FIXED (SKINNED_WINDOW(mainwin)->normal)->children; iter; iter = g_list_next (iter)) {
-                     GtkFixedChild *child_data = (GtkFixedChild *) iter->data;
-                     if (child_data->widget == widget) {
-                         x = child_data->x;
-                         y = child_data->y;
-                         break;
-                     }
-                }
+            /* Some skins include SKIN_VOLUME and/or SKIN_BALANCE without knobs */
+            if (pixmap_id == SKIN_VOLUME || pixmap_id == SKIN_BALANCE) {
+                if (ysrc+height > 421 && xsrc+width <= pixmap->width)
+                    return;
+            }
 
-                if (x != -1 && y != -1) {
-                    /* Some skins include SKIN_VOLUME and/or SKIN_BALANCE
-                       without knobs */
-                    if (pixmap_id == SKIN_VOLUME || pixmap_id == SKIN_BALANCE) {
-                        if (ysrc+height > 421 && xsrc+width <= pixmap->width)
-                            return;
-                    }
-                    /* let's copy what's under widget */
-                    gdk_pixbuf_copy_area(skin_get_pixmap(aud_active_skin, SKIN_MAIN)->pixbuf,
-                                         x, y, width, height, pix, xdest, ydest);
+            /* XMMS skins seems to have SKIN_MONOSTEREO with size 58x20 instead of 58x24 */
+            if (pixmap_id == SKIN_MONOSTEREO)
+                height = pixmap->height/2;
 
-                    /* XMMS skins seems to have SKIN_MONOSTEREO with size 58x20 instead of 58x24 */
-                    if (pixmap_id == SKIN_MONOSTEREO)
-                        height = pixmap->height/2;
-                }
-            } else if (gtk_widget_get_parent(widget) == SKINNED_WINDOW(equalizerwin)->normal) {
-                   if (!(pixmap_id == SKIN_EQMAIN && ysrc == 314)) /* equalizer preamp on equalizer graph */
-                         gtk_widget_hide(widget);
-            } else if (gtk_widget_get_parent(widget) == SKINNED_WINDOW(playlistwin)->normal) {
-                   /* I haven't seen any skin with substandard playlist */
-                   gtk_widget_hide(widget);
+            if (gtk_widget_get_parent(widget) == SKINNED_WINDOW(equalizerwin)->normal) {
+                if (!(pixmap_id == SKIN_EQMAIN && ysrc == 314)) /* equalizer preamp on equalizer graph */
+                    gtk_widget_hide(widget);
+            }
+
+            if (gtk_widget_get_parent(widget) == SKINNED_WINDOW(playlistwin)->normal) {
+                /* I haven't seen any skin with substandard playlist */
+                gtk_widget_hide(widget);
             }
         } else
             return;
@@ -2039,16 +2022,19 @@
     aud_active_skin_load(node->path);
 }
 
-
-void ui_skinned_widget_draw(GtkWidget *widget, GdkPixbuf *obj, gint width, gint height, gboolean scale) {
+void ui_skinned_widget_draw_with_coordinates(GtkWidget *widget, GdkPixbuf *obj, gint width, gint height, gint destx, gint desty, gboolean scale) {
     g_return_if_fail(widget != NULL);
     g_return_if_fail(obj != NULL);
 
     if (scale) {
         GdkPixbuf *image = gdk_pixbuf_scale_simple(obj, width * config.scale_factor, height* config.scale_factor, GDK_INTERP_NEAREST);
-        gdk_draw_pixbuf(widget->window, NULL, image, 0, 0, 0, 0, width * config.scale_factor , height * config.scale_factor, GDK_RGB_DITHER_NONE, 0, 0);
+        gdk_draw_pixbuf(widget->window, NULL, image, 0, 0, destx, desty, width * config.scale_factor , height * config.scale_factor, GDK_RGB_DITHER_NONE, 0, 0);
         g_object_unref(image);
     } else {
-        gdk_draw_pixbuf(widget->window, NULL, obj, 0, 0, 0, 0, width, height, GDK_RGB_DITHER_NONE, 0, 0);
+        gdk_draw_pixbuf(widget->window, NULL, obj, 0, 0, destx, desty, width, height, GDK_RGB_DITHER_NONE, 0, 0);
     }
 }
+
+void ui_skinned_widget_draw(GtkWidget *widget, GdkPixbuf *obj, gint width, gint height, gboolean scale) {
+    ui_skinned_widget_draw_with_coordinates(widget, obj, width, height, 0, 0, scale);
+}
--- a/src/skins/ui_skin.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skin.h	Tue Aug 12 20:40:31 2008 +0300
@@ -239,7 +239,7 @@
 
 void skin_set_random_skin(void);
 
-
+void ui_skinned_widget_draw_with_coordinates(GtkWidget *widget, GdkPixbuf *obj, gint width, gint height, gint destx, gint desty, gboolean scale);
 void ui_skinned_widget_draw(GtkWidget *widget, GdkPixbuf *obj, gint width, gint height, gboolean scale);
 
 #endif
--- a/src/skins/ui_skinned_button.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_button.c	Tue Aug 12 20:40:31 2008 +0300
@@ -157,6 +157,8 @@
     priv->move_x = 0;
     priv->move_y = 0;
     button->event_window = NULL;
+
+    GTK_WIDGET_SET_FLAGS (button, GTK_NO_WINDOW);
 }
 
 static void ui_skinned_button_destroy (GtkObject *object) {
@@ -174,40 +176,28 @@
 static void ui_skinned_button_realize (GtkWidget *widget) {
     g_return_if_fail (widget != NULL);
     g_return_if_fail (UI_SKINNED_IS_BUTTON(widget));
+
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
     UiSkinnedButton *button = UI_SKINNED_BUTTON (widget);
     GdkWindowAttr attributes;
     gint attributes_mask;
 
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
-
     attributes.x = widget->allocation.x;
     attributes.y = widget->allocation.y;
     attributes.width = widget->allocation.width;
     attributes.height = widget->allocation.height;
+    attributes.wclass = GDK_INPUT_ONLY;
     attributes.window_type = GDK_WINDOW_CHILD;
     attributes.event_mask = gtk_widget_get_events(widget);
     attributes.event_mask |= GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
 
-    if (button->type == TYPE_SMALL || button->type == TYPE_NOT_SET) {
-        widget->window = gtk_widget_get_parent_window (widget);
-        g_object_ref (widget->window);
-        attributes.wclass = GDK_INPUT_ONLY;
-        attributes_mask = GDK_WA_X | GDK_WA_Y;
-        button->event_window = gdk_window_new (widget->window, &attributes, attributes_mask);
-        GTK_WIDGET_SET_FLAGS (widget, GTK_NO_WINDOW);
-        gdk_window_set_user_data(button->event_window, widget);
-    } else {
-        attributes.visual = gtk_widget_get_visual(widget);
-        attributes.colormap = gtk_widget_get_colormap(widget);
-        attributes.wclass = GDK_INPUT_OUTPUT;
-        attributes.event_mask |= GDK_EXPOSURE_MASK;
-        attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-        widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
-        GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW);
-        gdk_window_set_user_data(widget->window, widget);
-    }
+    attributes.wclass = GDK_INPUT_ONLY;
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    button->event_window = gdk_window_new (widget->window, &attributes, attributes_mask);
 
-    widget->style = gtk_style_attach(widget->style, widget->window);
+    gdk_window_set_user_data(button->event_window, widget);
 }
 
 static void ui_skinned_button_unrealize (GtkWidget *widget) {
@@ -289,12 +279,9 @@
     if (button->type == TYPE_SMALL || button->type == TYPE_NOT_SET)
         return FALSE;
 
-    /* paranoia */
-    if (button->event_window != NULL)
-        return FALSE;
-
     GdkPixbuf *obj;
     obj = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, priv->w, priv->h);
+    gdk_pixbuf_fill(obj, 0x00000000); /* fill with alpha */
 
     switch (button->type) {
         case TYPE_PUSH:
@@ -322,7 +309,10 @@
             break;
     }
 
-    ui_skinned_widget_draw(widget, obj, priv->w, priv->h, priv->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, priv->w, priv->h,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            priv->scaled);
     g_object_unref(obj);
 
     return FALSE;
--- a/src/skins/ui_skinned_equalizer_graph.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_equalizer_graph.c	Tue Aug 12 20:40:31 2008 +0300
@@ -93,6 +93,8 @@
 static void ui_skinned_equalizer_graph_init(UiSkinnedEqualizerGraph *equalizer_graph) {
     equalizer_graph->width = 113;
     equalizer_graph->height = 19;
+
+    GTK_WIDGET_SET_FLAGS(equalizer_graph, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_equalizer_graph_new(GtkWidget *fixed, gint x, gint y) {
@@ -121,33 +123,8 @@
 }
 
 static void ui_skinned_equalizer_graph_realize(GtkWidget *widget) {
-    UiSkinnedEqualizerGraph *equalizer_graph;
-    GdkWindowAttr attributes;
-    gint attributes_mask;
-
-    g_return_if_fail (widget != NULL);
-    g_return_if_fail (UI_SKINNED_IS_EQUALIZER_GRAPH(widget));
-
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
-    equalizer_graph = UI_SKINNED_EQUALIZER_GRAPH(widget);
-
-    attributes.x = widget->allocation.x;
-    attributes.y = widget->allocation.y;
-    attributes.width = widget->allocation.width;
-    attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
-    attributes.window_type = GDK_WINDOW_CHILD;
-    attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
-
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
-
-    widget->style = gtk_style_attach(widget->style, widget->window);
-
-    gdk_window_set_user_data(widget->window, widget);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
 }
 
 static void ui_skinned_equalizer_graph_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -163,8 +140,6 @@
     widget->allocation = *allocation;
     widget->allocation.x *= (equalizer_graph->scaled ? config.scale_factor : 1);
     widget->allocation.y *= (equalizer_graph->scaled ? config.scale_factor : 1);
-    if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     equalizer_graph->x = widget->allocation.x/(equalizer_graph->scaled ? config.scale_factor : 1);
     equalizer_graph->y = widget->allocation.y/(equalizer_graph->scaled ? config.scale_factor : 1);
@@ -289,7 +264,10 @@
         }
     }
 
-    ui_skinned_widget_draw(widget, obj, equalizer_graph->width, equalizer_graph->height, equalizer_graph->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, equalizer_graph->width, equalizer_graph->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            equalizer_graph->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_equalizer_slider.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_equalizer_slider.c	Tue Aug 12 20:40:31 2008 +0300
@@ -51,6 +51,9 @@
 static void ui_skinned_equalizer_slider_init               (UiSkinnedEqualizerSlider *equalizer_slider);
 static void ui_skinned_equalizer_slider_destroy            (GtkObject *object);
 static void ui_skinned_equalizer_slider_realize            (GtkWidget *widget);
+static void ui_skinned_equalizer_slider_unrealize          (GtkWidget *widget);
+static void ui_skinned_equalizer_slider_map                (GtkWidget *widget);
+static void ui_skinned_equalizer_slider_unmap              (GtkWidget *widget); 
 static void ui_skinned_equalizer_slider_size_request       (GtkWidget *widget, GtkRequisition *requisition);
 static void ui_skinned_equalizer_slider_size_allocate      (GtkWidget *widget, GtkAllocation *allocation);
 static gboolean ui_skinned_equalizer_slider_expose         (GtkWidget *widget, GdkEventExpose *event);
@@ -97,6 +100,9 @@
     object_class->destroy = ui_skinned_equalizer_slider_destroy;
 
     widget_class->realize = ui_skinned_equalizer_slider_realize;
+    widget_class->unrealize = ui_skinned_equalizer_slider_unrealize;
+    widget_class->map = ui_skinned_equalizer_slider_map;
+    widget_class->unmap = ui_skinned_equalizer_slider_unmap; 
     widget_class->expose_event = ui_skinned_equalizer_slider_expose;
     widget_class->size_request = ui_skinned_equalizer_slider_size_request;
     widget_class->size_allocate = ui_skinned_equalizer_slider_size_allocate;
@@ -118,6 +124,9 @@
 static void ui_skinned_equalizer_slider_init(UiSkinnedEqualizerSlider *equalizer_slider) {
     UiSkinnedEqualizerSliderPrivate *priv = UI_SKINNED_EQUALIZER_SLIDER_GET_PRIVATE(equalizer_slider);
     priv->pressed = FALSE;
+
+    equalizer_slider->event_window = NULL;
+    GTK_WIDGET_SET_FLAGS(equalizer_slider, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_equalizer_slider_new(GtkWidget *fixed, gint x, gint y) {
@@ -155,26 +164,60 @@
     g_return_if_fail (widget != NULL);
     g_return_if_fail (UI_SKINNED_IS_EQUALIZER_SLIDER(widget));
 
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
     equalizer_slider = UI_SKINNED_EQUALIZER_SLIDER(widget);
 
     attributes.x = widget->allocation.x;
     attributes.y = widget->allocation.y;
     attributes.width = widget->allocation.width;
     attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.wclass = GDK_INPUT_ONLY;
     attributes.window_type = GDK_WINDOW_CHILD;
     attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+    attributes.event_mask |= GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
                              GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    equalizer_slider->event_window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
+
+    gdk_window_set_user_data(equalizer_slider->event_window, widget);
+}
+
+static void ui_skinned_equalizer_slider_unrealize(GtkWidget *widget) {
+    UiSkinnedEqualizerSlider *equalizer_slider = UI_SKINNED_EQUALIZER_SLIDER(widget);
+
+    if ( equalizer_slider->event_window != NULL )
+    {
+        gdk_window_set_user_data( equalizer_slider->event_window , NULL );
+        gdk_window_destroy( equalizer_slider->event_window );
+        equalizer_slider->event_window = NULL;
+    }
 
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
+    if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+        (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void ui_skinned_equalizer_slider_map (GtkWidget *widget)
+{
+    UiSkinnedEqualizerSlider *equalizer_slider = UI_SKINNED_EQUALIZER_SLIDER(widget);
+
+    if (equalizer_slider->event_window != NULL)
+        gdk_window_show (equalizer_slider->event_window);
 
-    widget->style = gtk_style_attach(widget->style, widget->window);
-    gdk_window_set_user_data(widget->window, widget);
+    if (GTK_WIDGET_CLASS (parent_class)->map)
+        (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+}
+
+static void ui_skinned_equalizer_slider_unmap (GtkWidget *widget)
+{
+    UiSkinnedEqualizerSlider *equalizer_slider = UI_SKINNED_EQUALIZER_SLIDER(widget);
+
+    if (equalizer_slider->event_window != NULL)
+        gdk_window_hide (equalizer_slider->event_window);
+
+    if (GTK_WIDGET_CLASS (parent_class)->unmap)
+        (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
 }
 
 static void ui_skinned_equalizer_slider_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -192,7 +235,8 @@
     widget->allocation.x *= (priv->scaled ? config.scale_factor : 1);
     widget->allocation.y *= (priv->scaled ? config.scale_factor : 1);
     if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
+        if (equalizer_slider->event_window)
+            gdk_window_move_resize(equalizer_slider->event_window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     equalizer_slider->x = widget->allocation.x/(priv->scaled ? config.scale_factor : 1);
     equalizer_slider->y = widget->allocation.y/(priv->scaled ? config.scale_factor : 1);
@@ -222,7 +266,10 @@
     else
         skin_draw_pixbuf(widget, aud_active_skin, obj, priv->skin_index, 0, 164, 1, priv->position, 11, 11);
 
-    ui_skinned_widget_draw(widget, obj, priv->width, priv->height, priv->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, priv->width, priv->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            priv->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_equalizer_slider.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_equalizer_slider.h	Tue Aug 12 20:40:31 2008 +0300
@@ -42,6 +42,7 @@
 
 struct _UiSkinnedEqualizerSlider {
     GtkWidget   widget;
+    GdkWindow   *event_window;
     gint        x, y;
 };
 
--- a/src/skins/ui_skinned_horizontal_slider.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_horizontal_slider.c	Tue Aug 12 20:40:31 2008 +0300
@@ -52,6 +52,9 @@
 static void ui_skinned_horizontal_slider_init               (UiSkinnedHorizontalSlider *horizontal_slider);
 static void ui_skinned_horizontal_slider_destroy            (GtkObject *object);
 static void ui_skinned_horizontal_slider_realize            (GtkWidget *widget);
+static void ui_skinned_horizontal_slider_unrealize          (GtkWidget *widget);
+static void ui_skinned_horizontal_slider_map                (GtkWidget *widget);
+static void ui_skinned_horizontal_slider_unmap              (GtkWidget *widget); 
 static void ui_skinned_horizontal_slider_size_request       (GtkWidget *widget, GtkRequisition *requisition);
 static void ui_skinned_horizontal_slider_size_allocate      (GtkWidget *widget, GtkAllocation *allocation);
 static gboolean ui_skinned_horizontal_slider_expose         (GtkWidget *widget, GdkEventExpose *event);
@@ -96,6 +99,9 @@
     object_class->destroy = ui_skinned_horizontal_slider_destroy;
 
     widget_class->realize = ui_skinned_horizontal_slider_realize;
+    widget_class->unrealize = ui_skinned_horizontal_slider_unrealize;
+    widget_class->map = ui_skinned_horizontal_slider_map;
+    widget_class->unmap = ui_skinned_horizontal_slider_unmap; 
     widget_class->expose_event = ui_skinned_horizontal_slider_expose;
     widget_class->size_request = ui_skinned_horizontal_slider_size_request;
     widget_class->size_allocate = ui_skinned_horizontal_slider_size_allocate;
@@ -127,6 +133,9 @@
 
 static void ui_skinned_horizontal_slider_init(UiSkinnedHorizontalSlider *horizontal_slider) {
     horizontal_slider->pressed = FALSE;
+
+    horizontal_slider->event_window = NULL;
+    GTK_WIDGET_SET_FLAGS(horizontal_slider, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_horizontal_slider_new(GtkWidget *fixed, gint x, gint y, gint w, gint h, gint knx, gint kny,
@@ -181,26 +190,60 @@
     g_return_if_fail (widget != NULL);
     g_return_if_fail (UI_SKINNED_IS_HORIZONTAL_SLIDER(widget));
 
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); 
     horizontal_slider = UI_SKINNED_HORIZONTAL_SLIDER(widget);
 
     attributes.x = widget->allocation.x;
     attributes.y = widget->allocation.y;
     attributes.width = widget->allocation.width;
     attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.wclass = GDK_INPUT_ONLY;
     attributes.window_type = GDK_WINDOW_CHILD;
     attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
+    attributes.event_mask |= GDK_BUTTON_PRESS_MASK | 
                              GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    horizontal_slider->event_window = gdk_window_new(widget->window, &attributes, attributes_mask);
+
+    gdk_window_set_user_data(horizontal_slider->event_window, widget);
+}
+
+static void ui_skinned_horizontal_slider_unrealize(GtkWidget *widget) {
+    UiSkinnedHorizontalSlider *horizontal_slider = UI_SKINNED_HORIZONTAL_SLIDER(widget);
+
+   if ( horizontal_slider->event_window != NULL )
+    {
+        gdk_window_set_user_data( horizontal_slider->event_window , NULL );
+        gdk_window_destroy( horizontal_slider->event_window );
+        horizontal_slider->event_window = NULL;
+    }
 
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
+    if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+        (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void ui_skinned_horizontal_slider_map (GtkWidget *widget)
+{
+    UiSkinnedHorizontalSlider *horizontal_slider = UI_SKINNED_HORIZONTAL_SLIDER(widget);
+
+    if (horizontal_slider->event_window != NULL)
+        gdk_window_show (horizontal_slider->event_window);
 
-    widget->style = gtk_style_attach(widget->style, widget->window);
-    gdk_window_set_user_data(widget->window, widget);
+    if (GTK_WIDGET_CLASS (parent_class)->map)
+        (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+}
+
+static void ui_skinned_horizontal_slider_unmap (GtkWidget *widget)
+{
+    UiSkinnedHorizontalSlider *horizontal_slider = UI_SKINNED_HORIZONTAL_SLIDER(widget);
+
+    if (horizontal_slider->event_window != NULL)
+        gdk_window_hide (horizontal_slider->event_window);
+
+    if (GTK_WIDGET_CLASS (parent_class)->unmap)
+        (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
 }
 
 static void ui_skinned_horizontal_slider_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -224,7 +267,8 @@
     priv->height = ceil(allocation->height/(priv->scaled ? config.scale_factor : 1));
 
     if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
+        if (horizontal_slider->event_window)
+            gdk_window_move_resize(horizontal_slider->event_window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     horizontal_slider->x = ceil(widget->allocation.x/(priv->scaled ? config.scale_factor : 1));
     horizontal_slider->y = ceil(widget->allocation.y/(priv->scaled ? config.scale_factor : 1));
@@ -263,7 +307,10 @@
                          ((priv->height - priv->knob_height) / 2),
                          priv->knob_width, priv->knob_height);
 
-    ui_skinned_widget_draw(widget, obj, priv->width, priv->height, priv->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, priv->width, priv->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            priv->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_horizontal_slider.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_horizontal_slider.h	Tue Aug 12 20:40:31 2008 +0300
@@ -43,6 +43,7 @@
 
 struct _UiSkinnedHorizontalSlider {
     GtkWidget   widget;
+    GdkWindow   *event_window;
     gboolean    pressed;
     gint        x, y;
     gint        knob_nx, knob_ny, knob_px, knob_py;
--- a/src/skins/ui_skinned_menurow.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_menurow.c	Tue Aug 12 20:40:31 2008 +0300
@@ -39,6 +39,9 @@
 static void ui_skinned_menurow_init               (UiSkinnedMenurow *menurow);
 static void ui_skinned_menurow_destroy            (GtkObject *object);
 static void ui_skinned_menurow_realize            (GtkWidget *widget);
+static void ui_skinned_menurow_unrealize          (GtkWidget *widget);
+static void ui_skinned_menurow_map                (GtkWidget *widget);
+static void ui_skinned_menurow_unmap              (GtkWidget *widget);
 static void ui_skinned_menurow_size_request       (GtkWidget *widget, GtkRequisition *requisition);
 static void ui_skinned_menurow_size_allocate      (GtkWidget *widget, GtkAllocation *allocation);
 static gboolean ui_skinned_menurow_expose         (GtkWidget *widget, GdkEventExpose *event);
@@ -84,6 +87,9 @@
     object_class->destroy = ui_skinned_menurow_destroy;
 
     widget_class->realize = ui_skinned_menurow_realize;
+    widget_class->unrealize = ui_skinned_menurow_unrealize;
+    widget_class->map = ui_skinned_menurow_map;
+    widget_class->unmap = ui_skinned_menurow_unmap;
     widget_class->expose_event = ui_skinned_menurow_expose;
     widget_class->size_request = ui_skinned_menurow_size_request;
     widget_class->size_allocate = ui_skinned_menurow_size_allocate;
@@ -116,6 +122,9 @@
 static void ui_skinned_menurow_init(UiSkinnedMenurow *menurow) {
     menurow->scale_selected = config.scaled;
     menurow->always_selected = config.always_on_top;
+
+    menurow->event_window = NULL;
+    GTK_WIDGET_SET_FLAGS(menurow, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_menurow_new(GtkWidget *fixed, gint x, gint y, gint nx, gint ny, gint sx, gint sy, SkinPixmapId si) {
@@ -160,27 +169,60 @@
     g_return_if_fail (widget != NULL);
     g_return_if_fail (UI_SKINNED_IS_MENUROW(widget));
 
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
     menurow = UI_SKINNED_MENUROW(widget);
 
     attributes.x = widget->allocation.x;
     attributes.y = widget->allocation.y;
     attributes.width = widget->allocation.width;
     attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.wclass = GDK_INPUT_ONLY;
     attributes.window_type = GDK_WINDOW_CHILD;
     attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
+    attributes.event_mask |= GDK_BUTTON_PRESS_MASK |
                              GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    menurow->event_window = gdk_window_new(widget->window, &attributes, attributes_mask);
+
+    gdk_window_set_user_data(menurow->event_window, widget);
+}
+
+static void ui_skinned_menurow_unrealize(GtkWidget *widget) {
+    UiSkinnedMenurow *menurow = UI_SKINNED_MENUROW(widget);
+
+    if ( menurow->event_window != NULL )
+    {
+        gdk_window_set_user_data( menurow->event_window , NULL );
+        gdk_window_destroy( menurow->event_window );
+        menurow->event_window = NULL;
+    }
 
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
+    if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+        (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void ui_skinned_menurow_map (GtkWidget *widget)
+{
+    UiSkinnedMenurow *menurow = UI_SKINNED_MENUROW(widget);
+
+    if (menurow->event_window != NULL)
+        gdk_window_show (menurow->event_window);
 
-    widget->style = gtk_style_attach(widget->style, widget->window);
+    if (GTK_WIDGET_CLASS (parent_class)->map)
+        (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+}
 
-    gdk_window_set_user_data(widget->window, widget);
+static void ui_skinned_menurow_unmap (GtkWidget *widget)
+{
+    UiSkinnedMenurow *menurow = UI_SKINNED_MENUROW(widget);
+
+    if (menurow->event_window != NULL)
+        gdk_window_hide (menurow->event_window);
+
+    if (GTK_WIDGET_CLASS (parent_class)->unmap)
+        (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
 }
 
 static void ui_skinned_menurow_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -197,7 +239,8 @@
     widget->allocation.x *= (menurow->scaled ? config.scale_factor : 1);
     widget->allocation.y *= (menurow->scaled ? config.scale_factor : 1);
     if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
+        if (menurow->event_window)
+            gdk_window_move_resize(menurow->event_window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     menurow->x = widget->allocation.x/(menurow->scaled ? config.scale_factor : 1);
     menurow->y = widget->allocation.y/(menurow->scaled ? config.scale_factor : 1);
@@ -236,7 +279,10 @@
                              menurow->sx + 24, menurow->sy + 26, 0, 26, 8, 8);
     }
 
-    ui_skinned_widget_draw(widget, obj, menurow->width, menurow->height, menurow->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, menurow->width, menurow->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            menurow->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_menurow.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_menurow.h	Tue Aug 12 20:40:31 2008 +0300
@@ -49,6 +49,7 @@
 struct _UiSkinnedMenurow {
     GtkWidget        widget;
 
+    GdkWindow        *event_window;
     gint             x, y, width, height;
     gboolean         scaled;
     gint             nx, ny;
--- a/src/skins/ui_skinned_monostereo.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_monostereo.c	Tue Aug 12 20:40:31 2008 +0300
@@ -93,6 +93,8 @@
 static void ui_skinned_monostereo_init(UiSkinnedMonoStereo *monostereo) {
     monostereo->width = 56;
     monostereo->height = 12;
+
+    GTK_WIDGET_SET_FLAGS(monostereo, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_monostereo_new(GtkWidget *fixed, gint x, gint y, SkinPixmapId si) {
@@ -121,33 +123,8 @@
 }
 
 static void ui_skinned_monostereo_realize(GtkWidget *widget) {
-    UiSkinnedMonoStereo *monostereo;
-    GdkWindowAttr attributes;
-    gint attributes_mask;
-
-    g_return_if_fail (widget != NULL);
-    g_return_if_fail (UI_SKINNED_IS_MONOSTEREO(widget));
-
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
-    monostereo = UI_SKINNED_MONOSTEREO(widget);
-
-    attributes.x = widget->allocation.x;
-    attributes.y = widget->allocation.y;
-    attributes.width = widget->allocation.width;
-    attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
-    attributes.window_type = GDK_WINDOW_CHILD;
-    attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
-
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
-
-    widget->style = gtk_style_attach(widget->style, widget->window);
-
-    gdk_window_set_user_data(widget->window, widget);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); 
 }
 
 static void ui_skinned_monostereo_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -163,8 +140,6 @@
     widget->allocation = *allocation;
     widget->allocation.x *= (monostereo->scaled ? config.scale_factor : 1);
     widget->allocation.y *= (monostereo->scaled ? config.scale_factor : 1);
-    if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     monostereo->x = widget->allocation.x/(monostereo->scaled ? config.scale_factor : 1);
     monostereo->y = widget->allocation.y/(monostereo->scaled ? config.scale_factor : 1);
@@ -197,7 +172,10 @@
         break;
     }
 
-    ui_skinned_widget_draw(widget, obj, monostereo->width, monostereo->height, monostereo->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, monostereo->width, monostereo->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y, 
+                                            monostereo->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_number.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_number.c	Tue Aug 12 20:40:31 2008 +0300
@@ -43,6 +43,9 @@
 static void ui_skinned_number_init               (UiSkinnedNumber *number);
 static void ui_skinned_number_destroy            (GtkObject *object);
 static void ui_skinned_number_realize            (GtkWidget *widget);
+static void ui_skinned_number_unrealize          (GtkWidget *widget);
+static void ui_skinned_number_map                (GtkWidget *widget);
+static void ui_skinned_number_unmap              (GtkWidget *widget); 
 static void ui_skinned_number_size_request       (GtkWidget *widget, GtkRequisition *requisition);
 static void ui_skinned_number_size_allocate      (GtkWidget *widget, GtkAllocation *allocation);
 static gboolean ui_skinned_number_expose         (GtkWidget *widget, GdkEventExpose *event);
@@ -82,6 +85,9 @@
     object_class->destroy = ui_skinned_number_destroy;
 
     widget_class->realize = ui_skinned_number_realize;
+    widget_class->unrealize = ui_skinned_number_unrealize;
+    widget_class->map = ui_skinned_number_map;
+    widget_class->unmap = ui_skinned_number_unmap; 
     widget_class->expose_event = ui_skinned_number_expose;
     widget_class->size_request = ui_skinned_number_size_request;
     widget_class->size_allocate = ui_skinned_number_size_allocate;
@@ -97,6 +103,9 @@
 static void ui_skinned_number_init(UiSkinnedNumber *number) {
     number->width = 9;
     number->height = 13;
+
+    number->event_window = NULL;
+    GTK_WIDGET_SET_FLAGS(number, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_number_new(GtkWidget *fixed, gint x, gint y, SkinPixmapId si) {
@@ -134,26 +143,59 @@
     g_return_if_fail (widget != NULL);
     g_return_if_fail (UI_SKINNED_IS_NUMBER(widget));
 
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); 
     number = UI_SKINNED_NUMBER(widget);
 
     attributes.x = widget->allocation.x;
     attributes.y = widget->allocation.y;
     attributes.width = widget->allocation.width;
     attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.wclass = GDK_INPUT_ONLY;
     attributes.window_type = GDK_WINDOW_CHILD;
     attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
+    attributes.event_mask |= GDK_BUTTON_PRESS_MASK;
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    number->event_window = gdk_window_new (widget->window, &attributes, attributes_mask); 
+
+    gdk_window_set_user_data(number->event_window, widget);
+}
+
+static void ui_skinned_number_unrealize(GtkWidget *widget) {
+    UiSkinnedNumber *number = UI_SKINNED_NUMBER(widget);
+
+    if ( number->event_window != NULL )
+    {
+        gdk_window_set_user_data( number->event_window , NULL );
+        gdk_window_destroy( number->event_window );
+        number->event_window = NULL;
+    }
 
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
+    if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+        (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void ui_skinned_number_map (GtkWidget *widget)
+{
+    UiSkinnedNumber *number = UI_SKINNED_NUMBER (widget);
+
+    if (number->event_window != NULL)
+        gdk_window_show (number->event_window);
 
-    widget->style = gtk_style_attach(widget->style, widget->window);
+    if (GTK_WIDGET_CLASS (parent_class)->map)
+        (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+}
 
-    gdk_window_set_user_data(widget->window, widget);
+static void ui_skinned_number_unmap (GtkWidget *widget)
+{
+    UiSkinnedNumber *number = UI_SKINNED_NUMBER (widget);
+
+    if (number->event_window != NULL)
+        gdk_window_hide (number->event_window);
+
+    if (GTK_WIDGET_CLASS (parent_class)->unmap)
+        (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
 }
 
 static void ui_skinned_number_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -170,7 +212,8 @@
     widget->allocation.x *= (number->scaled ? config.scale_factor: 1 );
     widget->allocation.y *= (number->scaled ? config.scale_factor: 1 );
     if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
+        if (number->event_window)
+            gdk_window_move_resize(number->event_window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     number->x = widget->allocation.x/(number->scaled ? config.scale_factor : 1);
     number->y = widget->allocation.y/(number->scaled ? config.scale_factor : 1);
@@ -194,7 +237,10 @@
                      number->skin_index, number->num * 9, 0,
                      0, 0, number->width, number->height);
 
-    ui_skinned_widget_draw(widget, obj, number->width, number->height, number->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, number->width, number->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            number->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_number.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_number.h	Tue Aug 12 20:40:31 2008 +0300
@@ -38,6 +38,7 @@
 struct _UiSkinnedNumber {
     GtkWidget        widget;
 
+    GdkWindow        *event_window;
     gint             x, y, width, height;
     gint             num;
     gboolean         scaled;
--- a/src/skins/ui_skinned_playstatus.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_playstatus.c	Tue Aug 12 20:40:31 2008 +0300
@@ -95,6 +95,8 @@
 static void ui_skinned_playstatus_init(UiSkinnedPlaystatus *playstatus) {
     playstatus->width = 11;
     playstatus->height = 9;
+
+    GTK_WIDGET_SET_FLAGS(playstatus, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_playstatus_new(GtkWidget *fixed, gint x, gint y) {
@@ -123,33 +125,8 @@
 }
 
 static void ui_skinned_playstatus_realize(GtkWidget *widget) {
-    UiSkinnedPlaystatus *playstatus;
-    GdkWindowAttr attributes;
-    gint attributes_mask;
-
-    g_return_if_fail (widget != NULL);
-    g_return_if_fail (UI_SKINNED_IS_PLAYSTATUS(widget));
-
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
-    playstatus = UI_SKINNED_PLAYSTATUS(widget);
-
-    attributes.x = widget->allocation.x;
-    attributes.y = widget->allocation.y;
-    attributes.width = widget->allocation.width;
-    attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
-    attributes.window_type = GDK_WINDOW_CHILD;
-    attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
-
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
-
-    widget->style = gtk_style_attach(widget->style, widget->window);
-
-    gdk_window_set_user_data(widget->window, widget);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
 }
 
 static void ui_skinned_playstatus_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -165,8 +142,6 @@
     widget->allocation = *allocation;
     widget->allocation.x *= (playstatus->scaled ? config.scale_factor : 1);
     widget->allocation.y *= (playstatus->scaled ? config.scale_factor : 1);
-    if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     playstatus->x = widget->allocation.x/(playstatus->scaled ? config.scale_factor : 1);
     playstatus->y = widget->allocation.y/(playstatus->scaled ? config.scale_factor : 1);
@@ -203,7 +178,10 @@
         break;
     }
 
-    ui_skinned_widget_draw(widget, obj, playstatus->width, playstatus->height, playstatus->scaled);
+    ui_skinned_widget_draw_with_coordinates(widget, obj, playstatus->width, playstatus->height,
+                                            widget->allocation.x,
+                                            widget->allocation.y,
+                                            playstatus->scaled);
 
     g_object_unref(obj);
 
--- a/src/skins/ui_skinned_textbox.c	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_textbox.c	Tue Aug 12 20:40:31 2008 +0300
@@ -69,6 +69,9 @@
 static void ui_skinned_textbox_init               (UiSkinnedTextbox *textbox);
 static void ui_skinned_textbox_destroy            (GtkObject *object);
 static void ui_skinned_textbox_realize            (GtkWidget *widget);
+static void ui_skinned_textbox_unrealize          (GtkWidget *widget);
+static void ui_skinned_textbox_map                (GtkWidget *widget);
+static void ui_skinned_textbox_unmap              (GtkWidget *widget);
 static void ui_skinned_textbox_size_request       (GtkWidget *widget, GtkRequisition *requisition);
 static void ui_skinned_textbox_size_allocate      (GtkWidget *widget, GtkAllocation *allocation);
 static gboolean ui_skinned_textbox_expose         (GtkWidget *widget, GdkEventExpose *event);
@@ -118,6 +121,9 @@
     object_class->destroy = ui_skinned_textbox_destroy;
 
     widget_class->realize = ui_skinned_textbox_realize;
+    widget_class->unrealize = ui_skinned_textbox_unrealize;
+    widget_class->map = ui_skinned_textbox_map;
+    widget_class->unmap = ui_skinned_textbox_unmap;
     widget_class->expose_event = ui_skinned_textbox_expose;
     widget_class->size_request = ui_skinned_textbox_size_request;
     widget_class->size_allocate = ui_skinned_textbox_size_allocate;
@@ -157,6 +163,9 @@
     UiSkinnedTextboxPrivate *priv = UI_SKINNED_TEXTBOX_GET_PRIVATE(textbox);
     priv->move_x = 0;
     priv->move_y = 0;
+
+    textbox->event_window = NULL;
+    GTK_WIDGET_SET_FLAGS (textbox, GTK_NO_WINDOW);
 }
 
 GtkWidget* ui_skinned_textbox_new(GtkWidget *fixed, gint x, gint y, gint w, gboolean allow_scroll, SkinPixmapId si) {
@@ -210,28 +219,64 @@
     g_return_if_fail (widget != NULL);
     g_return_if_fail (UI_SKINNED_IS_TEXTBOX(widget));
 
-    GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+    if (GTK_WIDGET_CLASS (parent_class)->realize)
+        (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
     textbox = UI_SKINNED_TEXTBOX(widget);
 
     attributes.x = widget->allocation.x;
     attributes.y = widget->allocation.y;
     attributes.width = widget->allocation.width;
     attributes.height = widget->allocation.height;
-    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.wclass = GDK_INPUT_ONLY;
     attributes.window_type = GDK_WINDOW_CHILD;
     attributes.event_mask = gtk_widget_get_events(widget);
-    attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
+    attributes.event_mask |= GDK_BUTTON_PRESS_MASK |
                              GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
                              GDK_POINTER_MOTION_HINT_MASK;
-    attributes.visual = gtk_widget_get_visual(widget);
-    attributes.colormap = gtk_widget_get_colormap(widget);
 
-    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-    widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask);
+    attributes_mask = GDK_WA_X | GDK_WA_Y;
+    textbox->event_window = gdk_window_new (widget->window, &attributes, attributes_mask);
 
     widget->style = gtk_style_attach(widget->style, widget->window);
 
-    gdk_window_set_user_data(widget->window, widget);
+    gdk_window_set_user_data(textbox->event_window, widget);
+}
+
+static void ui_skinned_textbox_unrealize(GtkWidget *widget) {
+    UiSkinnedTextbox *textbox = UI_SKINNED_TEXTBOX(widget);
+
+    if ( textbox->event_window != NULL )
+    {
+      gdk_window_set_user_data( textbox->event_window , NULL );
+      gdk_window_destroy( textbox->event_window );
+      textbox->event_window = NULL;
+    }
+
+    if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+        (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void ui_skinned_textbox_map (GtkWidget *widget)
+{
+    UiSkinnedTextbox *textbox = UI_SKINNED_TEXTBOX (widget);
+
+    if (textbox->event_window != NULL)
+      gdk_window_show (textbox->event_window);
+
+    if (GTK_WIDGET_CLASS (parent_class)->map)
+      (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+}
+
+static void ui_skinned_textbox_unmap (GtkWidget *widget)
+{
+    UiSkinnedTextbox *textbox = UI_SKINNED_TEXTBOX (widget);
+
+    if (textbox->event_window != NULL)
+      gdk_window_hide (textbox->event_window);
+
+    if (GTK_WIDGET_CLASS (parent_class)->unmap)
+      (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
 }
 
 static void ui_skinned_textbox_size_request(GtkWidget *widget, GtkRequisition *requisition) {
@@ -250,7 +295,8 @@
     widget->allocation.x *= (priv->scaled ? config.scale_factor : 1);
     widget->allocation.y *= (priv->scaled ? config.scale_factor : 1);
     if (GTK_WIDGET_REALIZED (widget))
-        gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
+        if (textbox->event_window)
+            gdk_window_move_resize(textbox->event_window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
 
     if (textbox->x + priv->move_x - widget->allocation.x/(priv->scaled ? config.scale_factor : 1) <3);
         priv->move_x = 0;
@@ -317,7 +363,10 @@
             }
         }
 
-        ui_skinned_widget_draw(widget, obj, textbox->width, textbox->height, priv->scaled);
+        ui_skinned_widget_draw_with_coordinates(widget, obj, textbox->width, textbox->height,
+                                                widget->allocation.x,
+                                                widget->allocation.y,
+                                                priv->scaled);
 
         g_object_unref(obj);
     }
--- a/src/skins/ui_skinned_textbox.h	Tue Aug 12 20:29:49 2008 +0300
+++ b/src/skins/ui_skinned_textbox.h	Tue Aug 12 20:40:31 2008 +0300
@@ -44,6 +44,7 @@
 struct _UiSkinnedTextbox {
     GtkWidget        widget;
 
+    GdkWindow        *event_window;
     gint             x, y, width, height;
     gchar            *text;
 };