changeset 3270:30ed2878807f trunk

merged with master
author Ben Tucker <ben.tucker@gmail.com>
date Tue, 07 Aug 2007 18:07:37 -0700
parents 91dd21cce4a5 (current diff) b26dc3482ce7 (diff)
children 5f40f7d2887f
files src/audacious/Makefile src/audacious/dbus.h src/audacious/widgets/Makefile src/audacious/widgets/skin.c src/audacious/widgets/skin.h src/audacious/widgets/widgetcore.h
diffstat 51 files changed, 2449 insertions(+), 2578 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/g15_audacious.py	Sat Aug 04 01:15:07 2007 -0700
+++ b/contrib/g15_audacious.py	Tue Aug 07 18:07:37 2007 -0700
@@ -10,6 +10,7 @@
 - Every second update should skip the D-Bus calls. They are the biggest CPU drain.
   (I also only use a half-second update interval for the scroller. Feel free to 
    turn it off and use a 1-second interval.
+- Wipe and redraw the entire screen at songchange. I'm not sure why yet, but some songs can cause mess-ups.
 - Clean up this quick hack of a script.
 
 Notes for people hacking this script:
@@ -34,6 +35,11 @@
 "0110000" +
 "0100000" )
 
+# 3x5 "Characters" (Icon glyphs sized to match the Small font)
+CHAR_S_NOTE = "011010010110110"
+CHAR_S_HALFTONE = "101010101010101"
+CHAR_S_CROSS = "000010111010000"
+
 # I prefer no icon when it's playing, so overwrite the play icon with a blank.
 ICN_PLAY = '0' * ICON_DIMS[0] * ICON_DIMS[1]
 
@@ -109,6 +115,11 @@
 			msg_handle.write('PB 0 9 160 14 0 1 1\n') # Wipe away any remnants of the old title that wouldn't be overwritten.
 			msg_handle.write('TO 0 9 0 0 "%s"\n' % titleString)
 
+			# Uncomment to place a note in the gap where the scroller wraps around
+			#notePos = (len(titleString) - scrollPivot - 1) * 4
+			#if len(titleString) > 40 and notePos <= 156:
+			#	msg_handle.write('PO %d 9 3 5 "%s"\n' % (notePos, CHAR_S_NOTE))
+
 			# Volume bar
 			msg_handle.write('DB 29 28 159 29 1 %d 100 1\n' % ((volume[0] + volume[1])/2))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/lap.py	Tue Aug 07 18:07:37 2007 -0700
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+"""Locate and Play
+Author: Stephan Sokolow (deitarion/SSokolow)
+License: GNU GPL-2
+Version: 1.0
+
+Description:
+- A quick wrapper to make playing songs via the local command quick and easy.
+- Works with any player which implements the MPRIS standard for remote control via D-Bus.
+- Accepts multiple space- and/or comma-separated choices after presenting the results.
+- Can enqueue or enqueue and play.
+- Can show full paths or just filenames.
+- Will behave in a sane fashion when asked to enqueue and play multiple files.
+
+TODO: 
+ - Complete the list of extensions for ModPlug, Embedded MPlayer (plugins-ugly), and UADE (3rd-party)
+ - Support sticking a 'q' in the result to choose enqueue on the fly
+ - Support an "all" keyword and an alternative to Ctrl+C for cancelling. (maybe 0)
+"""
+
+ADLIB_EXTS    = ['.a2m', '.adl',  '.adlib', '.amd', '.bam', '.cff', '.cmf', '.d00', '.dfm',  '.dmo', '.dro', '.dtm', '.hsc', '.hsp',
+                 '.jbm', '.ksm',  '.laa',   '.lds', '.m',   '.mad', '.mkj', '.msc', '.mtk',  '.rad', '.raw', '.rix', '.rol', '.sat', 
+                 '.sa2', '.sci',  '.sng',   '.imf', '.wlf', '.xad', '.xsm']
+CONSOLE_EXTS  = ['.adx', '.ay',   '.gbs',   '.gym', '.hes', '.kss', '.minipsf',     '.nsf', '.nsfe', '.psf', '.sap', '.sid', '.spc', 
+                 '.vgm', '.vgz',  '.vtx',   '.ym']
+MIDI_EXTS     = ['.mid', '.midi', '.rmi']
+MODULE_EXTS   = [ '.it', ',mod',  '.s3m',   '.stm', '.xm']
+PLAYLIST_EXTS = ['.cue', '.m3u',  '.pls',   '.xspf']
+WAVEFORM_EXTS = ['.aac', '.aif',  '.aiff',  '.au', '.flac', '.m4a', '.mp2', '.mp3', '.mpc', '.ogg', '.snd', '.tta', '.voc', '.wav', 
+                 '.wma', '.wv']
+
+# Edit these lines to choose the kind of files to be filtered for. By default, playlist extensions are excluded.
+OK_EXTS = WAVEFORM_EXTS + MODULE_EXTS + CONSOLE_EXTS + MIDI_EXTS + ADLIB_EXTS
+# If you want true format filtering, YOU write the mimetype cache.
+USE_PAGER = False  # Should we page output if it's more than a screenful?
+
+locate_command = ['locate', '-i']
+
+# ========== Configuration Ends ==========
+
+import fnmatch, optparse, os, subprocess
+from dbus import Bus, DBusException
+
+# Use readline if available but don't depend on it
+try: import readline
+except ImportError: pass
+
+# connect to DBus
+bus = Bus(Bus.TYPE_SESSION)
+
+def get_results(query):
+	"""Given a query or series of queries for the locate command, run them."""
+	results, cmd = [], locate_command + (isinstance(query, basestring) and [query] or query)
+	for line in subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout:
+		result = line.strip()
+		if os.path.splitext(result)[1] in OK_EXTS:
+			results.append(result)
+	results.sort()
+	return results
+
+def filter(results, filters):
+	for filter in filters:
+		results = [x for x in results if fnmatch.fnmatch(x.lower(), '*%s*' % filter.lower())]
+	return results
+
+def makeMenu(results, strip_path=True):
+	for pos, val in enumerate(results):
+		val = strip_path and os.path.split(val)[1] or val
+		print "%3d) %s" % (pos+1, val)
+
+def addTrack(path, play=False):
+	try:
+		mp = bus.get_object('org.freedesktop.MediaPlayer', '/TrackList')
+		mp.AddTrack('file://' + path, play)
+	except DBusException:
+		print "ERROR: Unable to contact media player."
+
+def parseChoice(inString):
+	try:
+		return [int(inString)]
+	except ValueError:
+		choices = []
+		for x in inString.replace(',',' ').split():
+			try: choices.append(int(x))
+			except ValueError: print "Not an integer: %s" % x
+		return choices
+
+if __name__ == '__main__':
+    try:
+	op = optparse.OptionParser()
+	op.add_option("-q", "--enqueue", action="store_true", dest="enqueue", default=False,
+	               help="Don't start the song playing after enqueueing it.")
+	op.add_option("-p", "--show_path", action="store_true", dest="show_path", default=False,
+	               help="Show the full path to each result.")
+
+	(opts, args) = op.parse_args()
+	
+	results = (len(args) > 0) and get_results(args.pop(0)) or []
+	results = filter(results, args)
+
+	def takeChoice(index, play=False):
+		index = index - 1
+		if index >= 0 and index < len(results):
+			addTrack(results[index], play)
+		else:
+			print "Invalid result index: %s" % (index + 1)
+
+	if len(results):
+		makeMenu(results, not opts.show_path)
+		choices = parseChoice(raw_input("Choice(s) (Ctrl+C to cancel): "))
+
+		if len(choices):
+			takeChoice(choices.pop(0), not opts.enqueue)
+		for item in choices:
+			takeChoice(item, False) # This ensures proper behaviour with no --enqueue and multiple choices.
+	else:
+		print "No Results"
+    except KeyboardInterrupt:
+	pass
--- a/src/audacious/Makefile	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/Makefile	Tue Aug 07 18:07:37 2007 -0700
@@ -2,7 +2,7 @@
 include ../../mk/init.mk
 include ../../mk/objective.mk
 
-SUBDIRS = $(INTL_OBJECTIVE) widgets glade images ui
+SUBDIRS = $(INTL_OBJECTIVE) glade images ui
 
 OBJECTIVE_BINS = audacious
 
@@ -17,8 +17,7 @@
 	$(MOWGLI_LIBS) \
 	$(LIBMCS_LIBS) \
 	$(LIBGLADE_LIBS) \
-	$(REGEX_LIBS) \
-	./widgets/libwidgets.a
+	$(REGEX_LIBS)
 
 CFLAGS += \
 	$(MOWGLI_CFLAGS) \
@@ -97,6 +96,7 @@
 	signals.c \
 	strings.c \
 	titlestring.c \
+	skin.c \
 	ui_about.c \
 	ui_albumart.c \
 	ui_credits.c \
@@ -137,7 +137,7 @@
 	visualization.c \
 	xconvert.c
 
-LIBDEP = widgets/libwidgets.a ../libguess/libguess.a
+LIBDEP = ../libguess/libguess.a
 
 ifdef USE_DBUS
 SOURCES += dbus.c
--- a/src/audacious/auddrct.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/auddrct.c	Tue Aug 07 18:07:37 2007 -0700
@@ -31,7 +31,7 @@
 #include "ui_jumptotrack.h"
 #include "auddrct.h"
 #include "playlist.h"
-
+#include "skin.h"
 
 /* player */
 
--- a/src/audacious/input.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/input.c	Tue Aug 07 18:07:37 2007 -0700
@@ -43,7 +43,6 @@
 #include "ui_main.h"
 #include "util.h"
 #include "visualization.h"
-#include "widgets/widgetcore.h"
 #include "ui_skinned_playstatus.h"
 #include "hook.h"
 
--- a/src/audacious/main.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/main.c	Tue Aug 07 18:07:37 2007 -0700
@@ -55,6 +55,7 @@
 #  include "audctrl.h"
 #endif
 
+#include "skin.h"
 #include "auddrct.h"
 #include "dnd.h"
 #include "effect.h"
--- a/src/audacious/main.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/main.h	Tue Aug 07 18:07:37 2007 -0700
@@ -27,7 +27,6 @@
 #define AUD_MAIN_H
 
 #ifdef _AUDACIOUS_CORE
-# include "widgets/widgetcore.h"
 # include "ui_main.h"
 #endif
 
--- a/src/audacious/playback.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/playback.c	Tue Aug 07 18:07:37 2007 -0700
@@ -54,6 +54,7 @@
 #include "ui_skinned_playstatus.h"
 #include "util.h"
 #include "visualization.h"
+#include "skin.h"
 
 #include "playback.h"
 #include "playback_evlisteners.h"
@@ -179,12 +180,16 @@
 playback_stop(void)
 {
     InputPlayback *playback;
+    
+    if ((playback = get_current_input_playback()) == NULL)
+        return;
 
-    if (ip_data.playing && (playback = get_current_input_playback()) != NULL)
+    if (ip_data.playing)
     {
         if (playback_get_paused() == TRUE)
         {
-            output_flush(get_written_time()); /* to avoid noise */
+            if (get_written_time() > 0)
+              output_flush(get_written_time()); /* to avoid noise */
             playback_pause();
         }
 
@@ -236,21 +241,9 @@
 static gpointer
 playback_monitor_thread(gpointer data)
 {
-    PlaylistEntry *entry = (PlaylistEntry *) data;
-    InputPlayback *playback;
-
-    playback = g_new0(InputPlayback, 1);
-    
-    entry->decoder->output = &psuedo_output_plugin;
+    InputPlayback *playback = (InputPlayback *) data;
 
-    playback->plugin = entry->decoder;
-    playback->output = &psuedo_output_plugin;
-    playback->filename = g_strdup(entry->filename);
-    playback->thread = g_thread_self();
-    
-    set_current_input_playback(playback);
-
-    entry->decoder->play_file(playback);
+    playback->plugin->play_file(playback);
 
     if (!playback->error && ip_data.playing)
         playback_eof();
@@ -265,6 +258,8 @@
 gboolean
 playback_play_file(PlaylistEntry *entry)
 {
+    InputPlayback *playback;
+
     g_return_val_if_fail(entry != NULL, FALSE);
 
     if (!get_current_output_plugin()) {
@@ -297,7 +292,19 @@
     }
 
     ip_data.playing = TRUE;
-    g_thread_create(playback_monitor_thread, entry, TRUE, NULL);
+
+    playback = g_new0(InputPlayback, 1);
+    
+    entry->decoder->output = &psuedo_output_plugin;
+
+    playback->plugin = entry->decoder;
+    playback->output = &psuedo_output_plugin;
+    playback->filename = g_strdup(entry->filename);
+    playback->thread = g_thread_self();
+    
+    set_current_input_playback(playback);
+
+    g_thread_create(playback_monitor_thread, playback, TRUE, NULL);
 
     return TRUE;
 }
--- a/src/audacious/playlist.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/playlist.c	Tue Aug 07 18:07:37 2007 -0700
@@ -1175,9 +1175,8 @@
 
     if (restart_playing)
         playback_initiate();
-    else {
-        playlistwin_update_list(playlist);
-    }
+
+    playlistwin_update_list(playlist);
 }
 
 void
@@ -1411,7 +1410,7 @@
         /* Shuffling and this is our first manual jump. */
         playlist_position_before_jump = playlist->position;
     }
-		
+
     playlist->position = node->data;
     PLAYLIST_UNLOCK(playlist->mutex);
     playlist_check_pos_current(playlist);
@@ -1443,7 +1442,7 @@
         playlist->position = playlist_position_before_jump;
         playlist_position_before_jump = NULL;
     }
-		
+
     plist_pos_list = find_playlist_position_list(playlist);
 
     if (cfg.no_playlist_advance) {
--- a/src/audacious/pluginenum.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/pluginenum.c	Tue Aug 07 18:07:37 2007 -0700
@@ -232,7 +232,7 @@
     vsnprintf(buf, 4096, str, va);
     va_end(va);
 
-    g_print("*** %s\n", buf);
+    g_message("*** %s\n", buf);
     g_module_close(module);
 }
 
@@ -266,7 +266,6 @@
         for (ip_iter = header->ip_list; *ip_iter != NULL; ip_iter++)
         {
             PLUGIN(*ip_iter)->filename = g_strdup(filename);
-            g_print("plugin2 '%s' provides InputPlugin <%p>\n", filename, *ip_iter);
             input_plugin_init(PLUGIN(*ip_iter));
         }
     }
@@ -276,7 +275,6 @@
         for (op_iter = header->op_list; *op_iter != NULL; op_iter++)
         {
             PLUGIN(*op_iter)->filename = g_strdup(filename);
-            g_print("plugin2 '%s' provides OutputPlugin <%p>\n", filename, *op_iter);
             output_plugin_init(PLUGIN(*op_iter));
         }
     }
@@ -286,7 +284,6 @@
         for (ep_iter = header->ep_list; *ep_iter != NULL; ep_iter++)
         {
             PLUGIN(*ep_iter)->filename = g_strdup(filename);
-            g_print("plugin2 '%s' provides EffectPlugin <%p>\n", filename, *ep_iter);
             effect_plugin_init(PLUGIN(*ep_iter));
         }
     }
@@ -296,7 +293,6 @@
         for (gp_iter = header->gp_list; *gp_iter != NULL; gp_iter++)
         {
             PLUGIN(*gp_iter)->filename = g_strdup(filename);
-            g_print("plugin2 '%s' provides GeneralPlugin <%p>\n", filename, *gp_iter);
             general_plugin_init(PLUGIN(*gp_iter));
         }
     }
@@ -306,7 +302,6 @@
         for (vp_iter = header->vp_list; *vp_iter != NULL; vp_iter++)
         {
             PLUGIN(*vp_iter)->filename = g_strdup(filename);
-            g_print("plugin2 '%s' provides VisPlugin <%p>\n", filename, *vp_iter);
             vis_plugin_init(PLUGIN(*vp_iter));
         }
     }
@@ -316,11 +311,9 @@
         for (dp_iter = header->dp_list; *dp_iter != NULL; dp_iter++)
         {
             PLUGIN(*dp_iter)->filename = g_strdup(filename);
-            g_print("plugin2 '%s' provides DiscoveryPlugin <%p>\n", filename, *dp_iter);
             discovery_plugin_init(PLUGIN(*dp_iter));
         }
     }
-
 }
 
 void
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/skin.c	Tue Aug 07 18:07:37 2007 -0700
@@ -0,0 +1,1900 @@
+/*  Audacious
+ *  Copyright (C) 2005-2007  Audacious development team.
+ *
+ *  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; under version 3 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ *  The Audacious team does not consider modular code linking to
+ *  Audacious or using our public API to be a derived work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+/* TODO: enforce default sizes! */
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "skin.h"
+#include "ui_equalizer.h"
+#include "main.h"
+#include "ui_playlist.h"
+#include "ui_skinselector.h"
+#include "util.h"
+
+#include "debug.h"
+
+#include "platform/smartinclude.h"
+#include "vfs.h"
+
+#include "ui_skinned_window.h"
+
+#define EXTENSION_TARGETS 7
+
+static gchar *ext_targets[EXTENSION_TARGETS] =
+{ "bmp", "xpm", "png", "svg", "gif", "jpg", "jpeg" };
+
+struct _SkinPixmapIdMapping {
+    SkinPixmapId id;
+    const gchar *name;
+    const gchar *alt_name;
+    gint width, height;
+};
+
+struct _SkinMaskInfo {
+    gint width, height;
+    gchar *inistr;
+};
+
+typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping;
+typedef struct _SkinMaskInfo SkinMaskInfo;
+
+
+Skin *bmp_active_skin = NULL;
+
+static gint skin_current_num;
+
+static SkinMaskInfo skin_mask_info[] = {
+    {275, 116, "Normal"},
+    {275, 16,  "WindowShade"},
+    {275, 116, "Equalizer"},
+    {275, 16,  "EqualizerWS"}
+};
+
+static SkinPixmapIdMapping skin_pixmap_id_map[] = {
+    {SKIN_MAIN, "main", NULL, 0, 0},
+    {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0},
+    {SKIN_SHUFREP, "shufrep", NULL, 0, 0},
+    {SKIN_TEXT, "text", NULL, 0, 0},
+    {SKIN_TITLEBAR, "titlebar", NULL, 0, 0},
+    {SKIN_VOLUME, "volume", NULL, 0, 0},
+    {SKIN_BALANCE, "balance", "volume", 0, 0},
+    {SKIN_MONOSTEREO, "monoster", NULL, 0, 0},
+    {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0},
+    {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0},
+    {SKIN_POSBAR, "posbar", NULL, 0, 0},
+    {SKIN_EQMAIN, "eqmain", NULL, 0, 0},
+    {SKIN_PLEDIT, "pledit", NULL, 0, 0},
+    {SKIN_EQ_EX, "eq_ex", NULL, 0, 0}
+};
+
+static guint skin_pixmap_id_map_size = G_N_ELEMENTS(skin_pixmap_id_map);
+
+static const guchar skin_default_viscolor[24][3] = {
+    {9, 34, 53},
+    {10, 18, 26},
+    {0, 54, 108},
+    {0, 58, 116},
+    {0, 62, 124},
+    {0, 66, 132},
+    {0, 70, 140},
+    {0, 74, 148},
+    {0, 78, 156},
+    {0, 82, 164},
+    {0, 86, 172},
+    {0, 92, 184},
+    {0, 98, 196},
+    {0, 104, 208},
+    {0, 110, 220},
+    {0, 116, 232},
+    {0, 122, 244},
+    {0, 128, 255},
+    {0, 128, 255},
+    {0, 104, 208},
+    {0, 80, 160},
+    {0, 56, 112},
+    {0, 32, 64},
+    {200, 200, 200}
+};
+
+static GdkBitmap *skin_create_transparent_mask(const gchar *,
+                                               const gchar *,
+                                               const gchar *,
+                                               GdkWindow *,
+                                               gint, gint, gboolean);
+
+static void skin_setup_masks(Skin * skin);
+
+static void skin_set_default_vis_color(Skin * skin);
+
+void
+skin_lock(Skin * skin)
+{
+    g_mutex_lock(skin->lock);
+}
+
+void
+skin_unlock(Skin * skin)
+{
+    g_mutex_unlock(skin->lock);
+}
+
+gboolean
+bmp_active_skin_reload(void) 
+{
+    return bmp_active_skin_load(bmp_active_skin->path); 
+}
+
+gboolean
+bmp_active_skin_load(const gchar * path)
+{
+    g_return_val_if_fail(bmp_active_skin != NULL, FALSE);
+
+    memset(&bmp_active_skin->properties, 0, sizeof(SkinProperties));
+
+    if (!skin_load(bmp_active_skin, path))
+        return FALSE;
+
+    skin_setup_masks(bmp_active_skin);
+
+    ui_skinned_window_draw_all(mainwin);
+    ui_skinned_window_draw_all(equalizerwin);
+    ui_skinned_window_draw_all(playlistwin);
+
+    playlistwin_update_list(playlist_get_active());
+
+    return TRUE;
+}
+
+void
+skin_pixmap_free(SkinPixmap * p)
+{
+    g_return_if_fail(p != NULL);
+    g_return_if_fail(p->pixmap != NULL);
+
+    g_object_unref(p->pixmap);
+    p->pixmap = NULL;
+}
+
+Skin *
+skin_new(void)
+{
+    Skin *skin;
+    skin = g_new0(Skin, 1);
+    skin->lock = g_mutex_new();
+    return skin;
+}
+
+void
+skin_free(Skin * skin)
+{
+    gint i;
+
+    g_return_if_fail(skin != NULL);
+
+    skin_lock(skin);
+
+    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
+        skin_pixmap_free(&skin->pixmaps[i]);
+
+    for (i = 0; i < SKIN_PIXMAP_COUNT; i++) {
+        if (skin->masks[i])
+            g_object_unref(skin->masks[i]);
+        if (skin->ds_masks[i])
+            g_object_unref(skin->ds_masks[i]);
+
+        skin->masks[i] = NULL;
+        skin->ds_masks[i] = NULL;
+    }
+
+    skin_set_default_vis_color(skin);
+    skin_unlock(skin);
+}
+
+void
+skin_destroy(Skin * skin)
+{
+    g_return_if_fail(skin != NULL);
+    skin_free(skin);
+    g_mutex_free(skin->lock);
+    g_free(skin);
+}
+
+const SkinPixmapIdMapping *
+skin_pixmap_id_lookup(guint id)
+{
+    guint i;
+
+    for (i = 0; i < skin_pixmap_id_map_size; i++) {
+        if (id == skin_pixmap_id_map[i].id) {
+            return &skin_pixmap_id_map[i];
+        }
+    }
+
+    return NULL;
+}
+
+const gchar *
+skin_pixmap_id_to_name(SkinPixmapId id)
+{
+    guint i;
+
+    for (i = 0; i < skin_pixmap_id_map_size; i++) {
+        if (id == skin_pixmap_id_map[i].id)
+            return skin_pixmap_id_map[i].name;
+    }
+    return NULL;
+}
+
+static void
+skin_set_default_vis_color(Skin * skin)
+{
+    memcpy(skin->vis_color, skin_default_viscolor,
+           sizeof(skin_default_viscolor));
+}
+
+/*
+ * I have rewritten this to take an array of possible targets,
+ * once we find a matching target we now return, instead of loop
+ * recursively. This allows for us to support many possible format
+ * targets for our skinning engine than just the original winamp 
+ * formats.
+ *
+ *    -- nenolod, 16 January 2006
+ */
+gchar *
+skin_pixmap_locate(const gchar * dirname, gchar ** basenames)
+{
+    gchar *filename;
+    gint i;
+
+    for (i = 0; basenames[i]; i++)
+    if (!(filename = find_path_recursively(dirname, basenames[i]))) 
+        g_free(filename);
+    else
+        return filename;
+
+    /* can't find any targets -- sorry */
+    return NULL;
+}
+
+/* FIXME: this function is temporary. It will be removed when the skinning system
+   uses GdkPixbuf in place of GdkPixmap */
+
+static GdkPixmap *
+pixmap_new_from_file(const gchar * filename)
+{
+    GdkPixbuf *pixbuf, *pixbuf2;
+    GdkPixmap *pixmap;
+    gint width, height;
+
+    if (!(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
+        return NULL;
+
+    width = gdk_pixbuf_get_width(pixbuf);
+    height = gdk_pixbuf_get_height(pixbuf);
+
+    /* create the windows if they haven't been created yet, needed for bootstrapping */
+    if (mainwin == NULL)
+    {
+        mainwin_create();
+        equalizerwin_create();
+        playlistwin_create();
+    }
+
+    if (!(pixmap = gdk_pixmap_new(mainwin->window, width, height,
+                                  gdk_rgb_get_visual()->depth))) {
+        g_object_unref(pixbuf);
+        return NULL;
+    }
+
+    pixbuf2 = audacious_create_colorized_pixbuf(pixbuf, cfg.colorize_r, cfg.colorize_g, cfg.colorize_b);
+    g_object_unref(pixbuf);
+
+    GdkGC *gc;
+    gc = gdk_gc_new(pixmap);
+    gdk_draw_pixbuf(pixmap, gc, pixbuf2, 0, 0, 0, 0, width, height, GDK_RGB_DITHER_MAX, 0, 0);
+    g_object_unref(gc);
+    g_object_unref(pixbuf2);
+
+    return pixmap;
+}
+
+static gboolean
+skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const gchar * path_p)
+{
+    const gchar *path;
+    gchar *filename;
+    gint width, height;
+    const SkinPixmapIdMapping *pixmap_id_mapping;
+    GdkPixmap *gpm;
+    SkinPixmap *pm = NULL;
+    gchar *basenames[EXTENSION_TARGETS * 2 + 1]; /* alternate basenames */
+    gint i, y;
+
+    g_return_val_if_fail(skin != NULL, FALSE);
+    g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE);
+
+    pixmap_id_mapping = skin_pixmap_id_lookup(id);
+    g_return_val_if_fail(pixmap_id_mapping != NULL, FALSE);
+
+    memset(&basenames, 0, sizeof(basenames));
+
+    for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++)
+    {
+        basenames[y] =
+            g_strdup_printf("%s.%s", pixmap_id_mapping->name, ext_targets[i]);
+
+        if (pixmap_id_mapping->alt_name)
+            basenames[++y] =
+                g_strdup_printf("%s.%s", pixmap_id_mapping->alt_name,
+                                ext_targets[i]);
+    }
+
+    path = path_p ? path_p : skin->path;
+    filename = skin_pixmap_locate(path, basenames);
+
+    for (i = 0; basenames[i] != NULL; i++)
+    {
+         g_free(basenames[i]);
+         basenames[i] = NULL;
+    }
+
+    if (!(gpm = pixmap_new_from_file(filename))) {
+        g_warning("loading of %s failed", filename);
+        g_free(filename);
+        return FALSE;
+    }
+
+    g_free(filename);
+
+    gdk_drawable_get_size(GDK_DRAWABLE(gpm), &width, &height);
+    pm = &skin->pixmaps[id];
+    pm->pixmap = gpm;
+    pm->width = width;
+    pm->height = height;
+    pm->current_width = width;
+    pm->current_height = height;
+
+    return TRUE;
+}
+
+void
+skin_mask_create(Skin * skin,
+                 const gchar * path,
+                 gint id,
+                 GdkWindow * window)
+{
+    skin->masks[id] =
+        skin_create_transparent_mask(path, "region.txt",
+                                     skin_mask_info[id].inistr, window,
+                                     skin_mask_info[id].width,
+                                     skin_mask_info[id].height, FALSE);
+
+    skin->ds_masks[id] =
+        skin_create_transparent_mask(path, "region.txt",
+                                     skin_mask_info[id].inistr, window,
+                                     skin_mask_info[id].width * 2,
+                                     skin_mask_info[id].height * 2, TRUE);
+}
+
+static void
+skin_setup_masks(Skin * skin)
+{
+    GdkBitmap *mask;
+
+    if (cfg.show_wm_decorations)
+        return;
+
+    if (cfg.player_visible) {
+        mask = skin_get_mask(skin, SKIN_MASK_MAIN + cfg.player_shaded);
+        gtk_widget_shape_combine_mask(mainwin, mask, 0, 0);
+    }
+
+    mask = skin_get_mask(skin, SKIN_MASK_EQ + cfg.equalizer_shaded);
+    gtk_widget_shape_combine_mask(equalizerwin, mask, 0, 0);
+}
+
+static GdkBitmap *
+create_default_mask(GdkWindow * parent, gint w, gint h)
+{
+    GdkBitmap *ret;
+    GdkGC *gc;
+    GdkColor pattern;
+
+    ret = gdk_pixmap_new(parent, w, h, 1);
+    gc = gdk_gc_new(ret);
+    pattern.pixel = 1;
+    gdk_gc_set_foreground(gc, &pattern);
+    gdk_draw_rectangle(ret, gc, TRUE, 0, 0, w, h);
+    g_object_unref(gc);
+
+    return ret;
+}
+
+static void
+skin_query_color(GdkColormap * cm, GdkColor * c)
+{
+#ifdef GDK_WINDOWING_X11
+    XColor xc = { 0,0,0,0,0,0 };
+
+    xc.pixel = c->pixel;
+    XQueryColor(GDK_COLORMAP_XDISPLAY(cm), GDK_COLORMAP_XCOLORMAP(cm), &xc);
+    c->red = xc.red;
+    c->green = xc.green;
+    c->blue = xc.blue;
+#else
+    /* do nothing. see what breaks? */
+#endif
+}
+
+static glong
+skin_calc_luminance(GdkColor * c)
+{
+    return (0.212671 * c->red + 0.715160 * c->green + 0.072169 * c->blue);
+}
+
+static void
+skin_get_textcolors(GdkPixmap * text, GdkColor * bgc, GdkColor * fgc)
+{
+    /*
+     * Try to extract reasonable background and foreground colors
+     * from the font pixmap
+     */
+
+    GdkImage *gi;
+    GdkColormap *cm;
+    gint i;
+
+    g_return_if_fail(text != NULL);
+    g_return_if_fail(GDK_IS_WINDOW(playlistwin->window));
+
+    /* Get the first line of text */
+    gi = gdk_drawable_get_image(text, 0, 0, 152, 6);
+    cm = gdk_drawable_get_colormap(playlistwin->window);
+
+    for (i = 0; i < 6; i++) {
+        GdkColor c;
+        gint x;
+        glong d, max_d;
+
+        /* Get a pixel from the middle of the space character */
+        bgc[i].pixel = gdk_image_get_pixel(gi, 151, i);
+        skin_query_color(cm, &bgc[i]);
+
+        max_d = 0;
+        for (x = 1; x < 150; x++) {
+            c.pixel = gdk_image_get_pixel(gi, x, i);
+            skin_query_color(cm, &c);
+
+            d = labs(skin_calc_luminance(&c) - skin_calc_luminance(&bgc[i]));
+            if (d > max_d) {
+                memcpy(&fgc[i], &c, sizeof(GdkColor));
+                max_d = d;
+            }
+        }
+    }
+    g_object_unref(gi);
+}
+
+gboolean
+init_skins(const gchar * path)
+{
+    bmp_active_skin = skin_new();
+
+    if (!bmp_active_skin_load(path)) {
+        /* FIXME: Oddly, g_message() causes a crash if path is NULL on
+         * Solaris (see bug #165) */
+        if (path) 
+            g_message("Unable to load skin (%s), trying default...", path);
+
+        /* can't load configured skin, retry with default */
+        if (!bmp_active_skin_load(BMP_DEFAULT_SKIN_PATH)) {
+            g_message("Unable to load default skin (%s)! Giving up.",
+                      BMP_DEFAULT_SKIN_PATH);
+            return FALSE;
+        }
+    }
+
+    if (cfg.random_skin_on_play)
+        skinlist_update();
+
+    return TRUE;
+}
+
+/*
+ * Opens and parses a skin's hints file.
+ * Hints files are somewhat like "scripts" in Winamp3/5.
+ * We'll probably add scripts to it next.
+ */
+void
+skin_parse_hints(Skin * skin, gchar *path_p)
+{
+    gchar *filename, *tmp;
+    INIFile *inifile;
+
+    path_p = path_p ? path_p : skin->path;
+
+    skin->properties.mainwin_othertext = FALSE;
+    skin->properties.mainwin_vis_x = 24;
+    skin->properties.mainwin_vis_y = 43;
+    skin->properties.mainwin_vis_width = 76;
+    skin->properties.mainwin_text_x = 112;
+    skin->properties.mainwin_text_y = 27;
+    skin->properties.mainwin_text_width = 153;
+    skin->properties.mainwin_infobar_x = 112;
+    skin->properties.mainwin_infobar_y = 43;
+    skin->properties.mainwin_number_0_x = 36;
+    skin->properties.mainwin_number_0_y = 26;
+    skin->properties.mainwin_number_1_x = 48;
+    skin->properties.mainwin_number_1_y = 26;
+    skin->properties.mainwin_number_2_x = 60;
+    skin->properties.mainwin_number_2_y = 26;
+    skin->properties.mainwin_number_3_x = 78;
+    skin->properties.mainwin_number_3_y = 26;
+    skin->properties.mainwin_number_4_x = 90;
+    skin->properties.mainwin_number_4_y = 26;
+    skin->properties.mainwin_playstatus_x = 24;
+    skin->properties.mainwin_playstatus_y = 28;
+    skin->properties.mainwin_menurow_visible = TRUE;
+    skin->properties.mainwin_volume_x = 107;
+    skin->properties.mainwin_volume_y = 57;
+    skin->properties.mainwin_balance_x = 177;
+    skin->properties.mainwin_balance_y = 57;
+    skin->properties.mainwin_position_x = 16;
+    skin->properties.mainwin_position_y = 72;
+    skin->properties.mainwin_othertext_is_status = FALSE;
+    skin->properties.mainwin_othertext_visible = skin->properties.mainwin_othertext;
+    skin->properties.mainwin_text_visible = TRUE;
+    skin->properties.mainwin_vis_visible = TRUE;
+    skin->properties.mainwin_previous_x = 16;
+    skin->properties.mainwin_previous_y = 88;
+    skin->properties.mainwin_play_x = 39;
+    skin->properties.mainwin_play_y = 88;
+    skin->properties.mainwin_pause_x = 62;
+    skin->properties.mainwin_pause_y = 88;
+    skin->properties.mainwin_stop_x = 85;
+    skin->properties.mainwin_stop_y = 88;
+    skin->properties.mainwin_next_x = 108;
+    skin->properties.mainwin_next_y = 88;
+    skin->properties.mainwin_eject_x = 136;
+    skin->properties.mainwin_eject_y = 89;
+    skin->properties.mainwin_width = 275;
+    skin_mask_info[0].width = skin->properties.mainwin_width;
+    skin->properties.mainwin_height = 116;
+    skin_mask_info[0].height = skin->properties.mainwin_height;
+    skin->properties.mainwin_about_x = 247;
+    skin->properties.mainwin_about_y = 83;
+    skin->properties.mainwin_shuffle_x = 164;
+    skin->properties.mainwin_shuffle_y = 89;
+    skin->properties.mainwin_repeat_x = 210;
+    skin->properties.mainwin_repeat_y = 89;
+    skin->properties.mainwin_eqbutton_x = 219;
+    skin->properties.mainwin_eqbutton_y = 58;
+    skin->properties.mainwin_plbutton_x = 242;
+    skin->properties.mainwin_plbutton_y = 58;
+    skin->properties.textbox_bitmap_font_width = 5;
+    skin->properties.textbox_bitmap_font_height = 6;
+    skin->properties.mainwin_minimize_x = 244;
+    skin->properties.mainwin_minimize_y = 3;
+    skin->properties.mainwin_shade_x = 254;
+    skin->properties.mainwin_shade_y = 3;
+    skin->properties.mainwin_close_x = 264;
+    skin->properties.mainwin_close_y = 3;
+
+    filename = find_file_recursively(path_p, "skin.hints");
+
+    if (filename == NULL)
+        return;
+
+    inifile = open_ini_file(filename);
+
+    tmp = read_ini_string(inifile, "skin", "mainwinOthertext");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_othertext = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinVisX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_vis_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinVisY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_vis_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinVisWidth");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_vis_width = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinTextX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_text_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinTextY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_text_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinTextWidth");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_text_width = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinInfoBarX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_infobar_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinInfoBarY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_infobar_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber0X");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_0_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber0Y");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_0_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber1X");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_1_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber1Y");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_1_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber2X");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_2_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber2Y");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_2_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber3X");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_3_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber3Y");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_3_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber4X");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_4_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber4Y");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_number_4_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_playstatus_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_playstatus_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinMenurowVisible");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_menurow_visible = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinVolumeX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_volume_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinVolumeY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_volume_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinBalanceX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_balance_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinBalanceY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_balance_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPositionX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_position_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPositionY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_position_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinOthertextIsStatus");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_othertext_is_status = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinOthertextVisible");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_othertext_visible = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinTextVisible");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_text_visible = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinVisVisible");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_vis_visible = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPreviousX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_previous_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPreviousY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_previous_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_play_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_play_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPauseX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_pause_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPauseY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_pause_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinStopX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_stop_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinStopY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_stop_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNextX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_next_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinNextY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_next_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinEjectX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_eject_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinEjectY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_eject_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinWidth");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_width = atoi(tmp);
+        g_free(tmp);
+    }
+
+    skin_mask_info[0].width = skin->properties.mainwin_width;
+
+    tmp = read_ini_string(inifile, "skin", "mainwinHeight");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_height = atoi(tmp);
+        g_free(tmp);
+    }
+
+    skin_mask_info[0].height = skin->properties.mainwin_height;
+
+    tmp = read_ini_string(inifile, "skin", "mainwinAboutX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_about_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinAboutY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_about_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinShuffleX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_shuffle_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinShuffleY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_shuffle_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinRepeatX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_repeat_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinRepeatY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_repeat_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinEQButtonX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_eqbutton_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinEQButtonY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_eqbutton_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPLButtonX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_plbutton_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinPLButtonY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_plbutton_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "textboxBitmapFontWidth");
+
+    if (tmp != NULL)
+    {
+        skin->properties.textbox_bitmap_font_width = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "textboxBitmapFontHeight");
+
+    if (tmp != NULL)
+    {
+        skin->properties.textbox_bitmap_font_height = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinMinimizeX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_minimize_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinMinimizeY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_minimize_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinShadeX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_shade_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinShadeY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_shade_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinCloseX");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_close_x = atoi(tmp);
+        g_free(tmp);
+    }
+
+    tmp = read_ini_string(inifile, "skin", "mainwinCloseY");
+
+    if (tmp != NULL)
+    {
+        skin->properties.mainwin_close_y = atoi(tmp);
+        g_free(tmp);
+    }
+
+    if (filename != NULL)
+        g_free(filename);
+
+    close_ini_file(inifile);
+}
+
+static guint
+hex_chars_to_int(gchar hi, gchar lo)
+{
+    /*
+     * Converts a value in the range 0x00-0xFF
+     * to a integer in the range 0-65535
+     */
+    gchar str[3];
+
+    str[0] = hi;
+    str[1] = lo;
+    str[2] = 0;
+
+    return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8);
+}
+
+static GdkColor *
+skin_load_color(INIFile *inifile,
+                const gchar * section, const gchar * key,
+                gchar * default_hex)
+{
+    gchar *value;
+    GdkColor *color = NULL;
+
+    if (inifile || default_hex) {
+        if (inifile) {
+            value = g_strdup(read_ini_string(inifile, section, key));
+            if (value == NULL) {
+                value = g_strdup(default_hex);
+            }
+        } else {
+            value = g_strdup(default_hex);
+        }
+        if (value) {
+            gchar *ptr = value;
+            gint len;
+
+            color = g_new0(GdkColor, 1);
+            g_strstrip(value);
+
+            if (value[0] == '#')
+                ptr++;
+            len = strlen(ptr);
+            /*
+             * The handling of incomplete values is done this way
+             * to maximize winamp compatibility
+             */
+            if (len >= 6) {
+                color->red = hex_chars_to_int(*ptr, *(ptr + 1));
+                ptr += 2;
+            }
+            if (len >= 4) {
+                color->green = hex_chars_to_int(*ptr, *(ptr + 1));
+                ptr += 2;
+            }
+            if (len >= 2)
+                color->blue = hex_chars_to_int(*ptr, *(ptr + 1));
+
+            gdk_colormap_alloc_color(gdk_drawable_get_colormap(playlistwin->window),
+                            color, TRUE, TRUE);
+            g_free(value);
+        }
+    }
+    return color;
+}
+
+
+
+GdkBitmap *
+skin_create_transparent_mask(const gchar * path,
+                             const gchar * file,
+                             const gchar * section,
+                             GdkWindow * window,
+                             gint width,
+                             gint height, gboolean doublesize)
+{
+    GdkBitmap *mask = NULL;
+    GdkGC *gc = NULL;
+    GdkColor pattern;
+    GdkPoint *gpoints;
+
+    gchar *filename = NULL;
+    INIFile *inifile = NULL;
+    gboolean created_mask = FALSE;
+    GArray *num, *point;
+    guint i, j;
+    gint k;
+
+    if (path)
+        filename = find_file_recursively(path, file);
+
+    /* filename will be null if path wasn't set */
+    if (!filename)
+        return create_default_mask(window, width, height);
+
+    inifile = open_ini_file(filename);
+
+    if ((num = read_ini_array(inifile, section, "NumPoints")) == NULL) {
+        g_free(filename);
+        close_ini_file(inifile);
+        return NULL;
+    }
+
+    if ((point = read_ini_array(inifile, section, "PointList")) == NULL) {
+        g_array_free(num, TRUE);
+        g_free(filename);
+        close_ini_file(inifile);
+        return NULL;
+    }
+
+    close_ini_file(inifile);
+
+    mask = gdk_pixmap_new(window, width, height, 1);
+    gc = gdk_gc_new(mask);
+
+    pattern.pixel = 0;
+    gdk_gc_set_foreground(gc, &pattern);
+    gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
+    pattern.pixel = 1;
+    gdk_gc_set_foreground(gc, &pattern);
+
+    j = 0;
+    for (i = 0; i < num->len; i++) {
+        if ((int)(point->len - j) >= (g_array_index(num, gint, i) * 2)) {
+            created_mask = TRUE;
+            gpoints = g_new(GdkPoint, g_array_index(num, gint, i));
+            for (k = 0; k < g_array_index(num, gint, i); k++) {
+                gpoints[k].x =
+                    g_array_index(point, gint, j + k * 2) * (1 + doublesize);
+                gpoints[k].y =
+                    g_array_index(point, gint,
+                                  j + k * 2 + 1) * (1 + doublesize);
+            }
+            j += k * 2;
+            gdk_draw_polygon(mask, gc, TRUE, gpoints,
+                             g_array_index(num, gint, i));
+            g_free(gpoints);
+        }
+    }
+    g_array_free(num, TRUE);
+    g_array_free(point, TRUE);
+    g_free(filename);
+
+    if (!created_mask)
+        gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
+
+    g_object_unref(gc);
+
+    return mask;
+}
+
+void
+skin_load_viscolor(Skin * skin, const gchar * path, const gchar * basename)
+{
+    VFSFile *file;
+    gint i, c;
+    gchar line[256], *filename;
+    GArray *a;
+
+    g_return_if_fail(skin != NULL);
+    g_return_if_fail(path != NULL);
+    g_return_if_fail(basename != NULL);
+
+    skin_set_default_vis_color(skin);
+
+    filename = find_file_recursively(path, basename);
+    if (!filename)
+        return;
+
+    if (!(file = vfs_fopen(filename, "r"))) {
+        g_free(filename);
+        return;
+    }
+
+    g_free(filename);
+
+    for (i = 0; i < 24; i++) {
+        if (vfs_fgets(line, 255, file)) {
+            a = string_to_garray(line);
+            if (a->len > 2) {
+                for (c = 0; c < 3; c++)
+                    skin->vis_color[i][c] = g_array_index(a, gint, c);
+            }
+            g_array_free(a, TRUE);
+        }
+        else
+            break;
+    }
+
+    vfs_fclose(file);
+}
+
+#if 0
+static void
+skin_numbers_generate_dash(Skin * skin)
+{
+    GdkGC *gc;
+    GdkPixmap *pixmap;
+    SkinPixmap *numbers;
+
+    g_return_if_fail(skin != NULL);
+
+    numbers = &skin->pixmaps[SKIN_NUMBERS];
+    if (!numbers->pixmap || numbers->current_width < 99)
+        return;
+
+    gc = gdk_gc_new(numbers->pixmap);
+    pixmap = gdk_pixmap_new(mainwin->window, 108,
+                            numbers->current_height,
+                            -1);
+
+    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 0, 0, 0, 0, 99, 13);
+    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 90, 0, 99, 0, 9, 13);
+    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 20, 6, 101, 6, 5, 1);
+
+    g_object_unref(numbers->pixmap);
+    g_object_unref(gc);
+
+    numbers->pixmap = pixmap;
+    numbers->current_width = 108;
+}
+#endif
+
+static void
+skin_load_cursor(Skin * skin, const gchar * dirname)
+{
+    const gchar * basename = "normal.cur";
+    gchar * filename = NULL;
+    GdkPixbuf * cursor_pixbuf = NULL;
+    GdkPixbufAnimation * cursor_animated = NULL;
+    GdkCursor * cursor_gdk = NULL;
+    GError * error = NULL;
+ 
+    filename = find_file_recursively(dirname, basename);
+
+    if (filename && cfg.custom_cursors)
+        cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
+
+    if (cursor_animated) {
+        cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated);
+        cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
+                                                cursor_pixbuf, 0, 0);
+    }
+    else
+        cursor_gdk = gdk_cursor_new(GDK_LEFT_PTR);
+
+    gdk_window_set_cursor(mainwin->window, cursor_gdk);
+    gdk_window_set_cursor(playlistwin->window, cursor_gdk);
+    gdk_window_set_cursor(equalizerwin->window, cursor_gdk);
+    gdk_cursor_unref(cursor_gdk);
+}
+
+static void
+skin_load_pixmaps(Skin * skin, const gchar * path)
+{
+    GdkPixmap *text_pm;
+    guint i;
+    gchar *filename;
+    INIFile *inifile;
+
+    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
+        skin_load_pixmap_id(skin, i, path);
+
+    text_pm = skin->pixmaps[SKIN_TEXT].pixmap;
+
+    if (text_pm)
+        skin_get_textcolors(text_pm, skin->textbg, skin->textfg);
+
+#if 0
+    if (skin->pixmaps[SKIN_NUMBERS].pixmap)
+        skin_numbers_generate_dash(skin);
+#endif
+
+    filename = find_file_recursively(path, "pledit.txt");
+    inifile = open_ini_file(filename);
+
+    skin->colors[SKIN_PLEDIT_NORMAL] =
+        skin_load_color(inifile, "Text", "Normal", "#2499ff");
+    skin->colors[SKIN_PLEDIT_CURRENT] =
+        skin_load_color(inifile, "Text", "Current", "#ffeeff");
+    skin->colors[SKIN_PLEDIT_NORMALBG] =
+        skin_load_color(inifile, "Text", "NormalBG", "#0a120a");
+    skin->colors[SKIN_PLEDIT_SELECTEDBG] =
+        skin_load_color(inifile, "Text", "SelectedBG", "#0a124a");
+
+    if (filename)
+        g_free(filename);
+    close_ini_file(inifile);
+
+    skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window);
+    skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window);
+
+    skin_mask_create(skin, path, SKIN_MASK_EQ, equalizerwin->window);
+    skin_mask_create(skin, path, SKIN_MASK_EQ_SHADE, equalizerwin->window);
+
+    skin_load_viscolor(skin, path, "viscolor.txt");
+}
+
+static gboolean
+skin_load_nolock(Skin * skin, const gchar * path, gboolean force)
+{
+    gchar *cpath;
+
+    g_return_val_if_fail(skin != NULL, FALSE);
+    g_return_val_if_fail(path != NULL, FALSE);
+    REQUIRE_LOCK(skin->lock);
+
+    if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR))
+        return FALSE;
+   
+    if (!force) {
+        if (skin->path)
+            if (!strcmp(skin->path, path))
+                return FALSE;
+    }
+      
+    skin_current_num++;
+
+    skin->path = g_strdup(path);
+
+    if (!file_is_archive(path)) {
+        /* Parse the hints for this skin. */
+        skin_parse_hints(skin, NULL);
+
+        skin_load_pixmaps(skin, path);
+        skin_load_cursor(skin, path);
+
+        return TRUE;
+    }
+
+    if (!(cpath = archive_decompress(path))) {
+        g_message("Unable to extract skin archive (%s)", path);
+        return FALSE;
+    }
+
+    /* Parse the hints for this skin. */
+    skin_parse_hints(skin, cpath);
+
+    skin_load_pixmaps(skin, cpath);
+    skin_load_cursor(skin, cpath);
+
+    del_directory(cpath);
+    g_free(cpath);
+
+    return TRUE;
+}
+
+void
+skin_install_skin(const gchar * path)
+{
+    gchar *command;
+
+    g_return_if_fail(path != NULL);
+
+    command = g_strdup_printf("cp %s %s",
+                              path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
+    if (system(command)) {
+        g_message("Unable to install skin (%s) into user directory (%s)",
+                  path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
+    }
+    g_free(command);
+}
+
+
+gboolean
+skin_load(Skin * skin, const gchar * path)
+{
+    gboolean error;
+
+    g_return_val_if_fail(skin != NULL, FALSE);
+
+    if (!path)
+        return FALSE;
+
+    skin_lock(skin);
+    error = skin_load_nolock(skin, path, FALSE);
+    skin_unlock(skin);
+    
+    return error;
+}
+
+gboolean
+skin_reload_forced(void) 
+{
+   gboolean error;
+
+   skin_lock(bmp_active_skin);
+   error = skin_load_nolock(bmp_active_skin, bmp_active_skin->path, TRUE);
+   skin_unlock(bmp_active_skin);
+
+   return error;
+}
+
+void
+skin_reload(Skin * skin)
+{
+    g_return_if_fail(skin != NULL);
+    skin_load_nolock(skin, skin->path, TRUE);
+}
+
+
+static SkinPixmap *
+skin_get_pixmap(Skin * skin, SkinPixmapId map_id)
+{
+    g_return_val_if_fail(skin != NULL, NULL);
+    g_return_val_if_fail(map_id < SKIN_PIXMAP_COUNT, NULL);
+
+    return &skin->pixmaps[map_id];
+}
+
+GdkBitmap *
+skin_get_mask(Skin * skin, SkinMaskId mi)
+{
+    GdkBitmap **masks;
+
+    g_return_val_if_fail(skin != NULL, NULL);
+    g_return_val_if_fail(mi < SKIN_PIXMAP_COUNT, NULL);
+
+    masks = cfg.doublesize ? skin->ds_masks : skin->masks;
+    return masks[mi];
+}
+
+GdkColor *
+skin_get_color(Skin * skin, SkinColorId color_id)
+{
+    GdkColor *ret = NULL;
+
+    g_return_val_if_fail(skin != NULL, NULL);
+
+    switch (color_id) {
+    case SKIN_TEXTBG:
+        if (skin->pixmaps[SKIN_TEXT].pixmap)
+            ret = skin->textbg;
+        else
+            ret = skin->def_textbg;
+        break;
+    case SKIN_TEXTFG:
+        if (skin->pixmaps[SKIN_TEXT].pixmap)
+            ret = skin->textfg;
+        else
+            ret = skin->def_textfg;
+        break;
+    default:
+        if (color_id < SKIN_COLOR_COUNT)
+            ret = skin->colors[color_id];
+        break;
+    }
+    return ret;
+}
+
+void
+skin_get_viscolor(Skin * skin, guchar vis_color[24][3])
+{
+    gint i;
+
+    g_return_if_fail(skin != NULL);
+
+    for (i = 0; i < 24; i++) {
+        vis_color[i][0] = skin->vis_color[i][0];
+        vis_color[i][1] = skin->vis_color[i][1];
+        vis_color[i][2] = skin->vis_color[i][2];
+    }
+}
+
+gint
+skin_get_id(void)
+{
+    return skin_current_num;
+}
+
+void
+skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
+                 SkinPixmapId pixmap_id,
+                 gint xsrc, gint ysrc, gint xdest, gint ydest,
+                 gint width, gint height)
+{
+    SkinPixmap *pixmap;
+
+    g_return_if_fail(skin != NULL);
+
+    pixmap = skin_get_pixmap(skin, pixmap_id);
+    g_return_if_fail(pixmap != NULL);
+    g_return_if_fail(pixmap->pixmap != NULL);
+
+    if (xsrc+width > pixmap->width || ysrc+height > pixmap->height) {
+        if (pixmap_id == SKIN_NUMBERS)
+            xsrc = 90;
+        else if (pixmap_id == SKIN_VOLUME) {
+            /* some winamp skins have too strait SKIN_VOLUME, so let's copy what's remain from SKIN_MAIN */
+            gdk_draw_drawable(drawable, gc, skin_get_pixmap(bmp_active_skin, SKIN_MAIN)->pixmap,
+                              skin->properties.mainwin_volume_x, skin->properties.mainwin_volume_y,
+                              pixmap->width, ydest, width - pixmap->width, height);
+            width = pixmap->width;
+        } else if (pixmap_id == SKIN_MONOSTEREO) {
+            /* XMMS skins seems to have SKIN_MONOSTEREO with size 58x20 instead of 58x24 */
+            gdk_draw_drawable(drawable, gc, skin_get_pixmap(bmp_active_skin, SKIN_MAIN)->pixmap,
+                              212 + xdest, 41, xdest, ydest, width, height);
+            height = pixmap->height/2;
+        } else
+            return;
+    }
+
+    width = MIN(width, pixmap->width - xsrc);
+    height = MIN(height, pixmap->height - ysrc);
+    gdk_draw_drawable(drawable, gc, pixmap->pixmap, xsrc, ysrc,
+                      xdest, ydest, width, height);
+}
+
+void
+skin_get_eq_spline_colors(Skin * skin, guint32 colors[19])
+{
+    gint i;
+    GdkPixmap *pixmap;
+    GdkImage *img;
+    SkinPixmap *eqmainpm;
+
+    g_return_if_fail(skin != NULL);
+
+    eqmainpm = &skin->pixmaps[SKIN_EQMAIN];
+    if (eqmainpm->pixmap &&
+        eqmainpm->current_width >= 116 && eqmainpm->current_height >= 313)
+        pixmap = eqmainpm->pixmap;
+    else
+        return;
+
+    if (!GDK_IS_DRAWABLE(pixmap))
+        return;
+
+    if (!(img = gdk_drawable_get_image(pixmap, 115, 294, 1, 19)))
+        return;
+
+    for (i = 0; i < 19; i++)
+        colors[i] = gdk_image_get_pixel(img, 0, i);
+
+    g_object_unref(img);
+}
+
+
+static void
+skin_draw_playlistwin_frame_top(Skin * skin,
+                                GdkDrawable * drawable,
+                                GdkGC * gc,
+                                gint width, gint height, gboolean focus)
+{
+    /* The title bar skin consists of 2 sets of 4 images, 1 set
+     * for focused state and the other for unfocused. The 4 images
+     * are: 
+     *
+     * a. right corner (25,20)
+     * b. left corner  (25,20)
+     * c. tiler        (25,20)
+     * d. title        (100,20)
+     * 
+     * min allowed width = 100+25+25 = 150
+     */
+
+    gint i, y, c;
+
+    /* get y offset of the pixmap set to use */
+    if (focus)
+        y = 0;
+    else
+        y = 21;
+
+    /* left corner */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, y, 0, 0, 25, 20);
+
+    /* titlebar title */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 26, y,
+                     (width - 100) / 2, 0, 100, 20);
+
+    /* titlebar right corner  */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 153, y,
+                     width - 25, 0, 25, 20);
+
+    /* tile draw the remaining frame */
+
+    /* compute tile count */
+    c = (width - (100 + 25 + 25)) / 25;
+
+    for (i = 0; i < c / 2; i++) {
+        /* left of title */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         25 + i * 25, 0, 25, 20);
+
+        /* right of title */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         (width + 100) / 2 + i * 25, 0, 25, 20);
+    }
+
+    if (c & 1) {
+        /* Odd tile count, so one remaining to draw. Here we split
+         * it into two and draw half on either side of the title */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         ((c / 2) * 25) + 25, 0, 12, 20);
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20);
+    }
+}
+
+static void
+skin_draw_playlistwin_frame_bottom(Skin * skin,
+                                   GdkDrawable * drawable,
+                                   GdkGC * gc,
+                                   gint width, gint height, gboolean focus)
+{
+    /* The bottom frame skin consists of 1 set of 4 images. The 4
+     * images are:
+     *
+     * a. left corner with menu buttons (125,38)
+     * b. visualization window (75,38)
+     * c. right corner with play buttons (150,38)
+     * d. frame tile (25,38)
+     * 
+     * (min allowed width = 125+150+25=300
+     */
+
+    gint i, c;
+
+    /* bottom left corner (menu buttons) */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 72,
+                     0, height - 38, 125, 38);
+
+    c = (width - 275) / 25;
+
+    /* draw visualization window, if width allows */
+    if (c >= 3) {
+        c -= 3;
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 205, 0,
+                         width - (150 + 75), height - 38, 75, 38);
+    }
+
+    /* Bottom right corner (playbuttons etc) */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT,
+                     126, 72, width - 150, height - 38, 150, 38);
+
+    /* Tile draw the remaining undrawn portions */
+    for (i = 0; i < c; i++)
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 179, 0,
+                         125 + i * 25, height - 38, 25, 38);
+}
+
+static void
+skin_draw_playlistwin_frame_sides(Skin * skin,
+                                  GdkDrawable * drawable,
+                                  GdkGC * gc,
+                                  gint width, gint height, gboolean focus)
+{
+    /* The side frames consist of 2 tile images. 1 for the left, 1 for
+     * the right. 
+     * a. left  (12,29)
+     * b. right (19,29)
+     */
+
+    gint i;
+
+    /* frame sides */
+    for (i = 0; i < (height - (20 + 38)) / 29; i++) {
+        /* left */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 42,
+                         0, 20 + i * 29, 12, 29);
+
+        /* right */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 32, 42,
+                         width - 19, 20 + i * 29, 19, 29);
+    }
+}
+
+
+void
+skin_draw_playlistwin_frame(Skin * skin,
+                            GdkDrawable * drawable, GdkGC * gc,
+                            gint width, gint height, gboolean focus)
+{
+    skin_draw_playlistwin_frame_top(skin, drawable, gc, width, height, focus);
+    skin_draw_playlistwin_frame_bottom(skin, drawable, gc, width, height,
+                                       focus);
+    skin_draw_playlistwin_frame_sides(skin, drawable, gc, width, height,
+                                      focus);
+}
+
+
+void
+skin_draw_playlistwin_shaded(Skin * skin,
+                             GdkDrawable * drawable, GdkGC * gc,
+                             gint width, gboolean focus)
+{
+    /* The shade mode titlebar skin consists of 4 images:
+     * a) left corner               offset (72,42) size (25,14)
+     * b) right corner, focused     offset (99,57) size (50,14)
+     * c) right corner, unfocused   offset (99,42) size (50,14)
+     * d) bar tile                  offset (72,57) size (25,14)
+     */
+
+    gint i;
+
+    /* left corner */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14);
+
+    /* bar tile */
+    for (i = 0; i < (width - 75) / 25; i++)
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 57,
+                         (i * 25) + 25, 0, 25, 14);
+
+    /* right corner */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 99, focus ? 42 : 57,
+                     width - 50, 0, 50, 14);
+}
+
+
+void
+skin_draw_mainwin_titlebar(Skin * skin,
+                           GdkDrawable * drawable, GdkGC * gc,
+                           gboolean shaded, gboolean focus)
+{
+    /* The titlebar skin consists of 2 sets of 2 images, one for for
+     * shaded and the other for unshaded mode, giving a total of 4.
+     * The images are exactly 275x14 pixels, aligned and arranged
+     * vertically on each other in the pixmap in the following order:
+     * 
+     * a) unshaded, focused      offset (27, 0)
+     * b) unshaded, unfocused    offset (27, 15)
+     * c) shaded, focused        offset (27, 29)
+     * d) shaded, unfocused      offset (27, 42)
+     */
+
+    gint y_offset;
+
+    if (shaded) {
+        if (focus)
+            y_offset = 29;
+        else
+            y_offset = 42;
+    }
+    else {
+        if (focus)
+            y_offset = 0;
+        else
+            y_offset = 15;
+    }
+
+    skin_draw_pixmap(skin, drawable, gc, SKIN_TITLEBAR, 27, y_offset,
+                     0, 0, bmp_active_skin->properties.mainwin_width, MAINWIN_TITLEBAR_HEIGHT);
+}
+
+
+void
+skin_set_random_skin(void)
+{
+    SkinNode *node;
+    guint32 randval;
+
+    /* Get a random value to select the skin to use */
+    randval = g_random_int_range(0, g_list_length(skinlist));
+    node = g_list_nth(skinlist, randval)->data;
+    bmp_active_skin_load(node->path);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/skin.h	Tue Aug 07 18:07:37 2007 -0700
@@ -0,0 +1,246 @@
+/*  Audacious
+ *  Copyright (C) 2005-2007  Audacious development team.
+ *
+ *  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; under version 3 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ *  The Audacious team does not consider modular code linking to
+ *  Audacious or using our public API to be a derived work.
+ */
+
+#ifndef SKIN_H
+#define SKIN_H
+
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+
+#define BMP_DEFAULT_SKIN_PATH \
+  DATA_DIR G_DIR_SEPARATOR_S "Skins" G_DIR_SEPARATOR_S "Default"
+
+
+typedef enum {
+    SKIN_MAIN = 0,
+    SKIN_CBUTTONS,
+    SKIN_TITLEBAR,
+    SKIN_SHUFREP,
+    SKIN_TEXT,
+    SKIN_VOLUME,
+    SKIN_BALANCE,
+    SKIN_MONOSTEREO,
+    SKIN_PLAYPAUSE,
+    SKIN_NUMBERS,
+    SKIN_POSBAR,
+    SKIN_PLEDIT,
+    SKIN_EQMAIN,
+    SKIN_EQ_EX,
+    SKIN_PIXMAP_COUNT
+} SkinPixmapId;
+
+typedef enum {
+    SKIN_MASK_MAIN = 0,
+    SKIN_MASK_MAIN_SHADE,
+    SKIN_MASK_EQ,
+    SKIN_MASK_EQ_SHADE,
+    SKIN_MASK_COUNT
+} SkinMaskId;
+
+typedef enum {
+    SKIN_PLEDIT_NORMAL = 0,
+    SKIN_PLEDIT_CURRENT,
+    SKIN_PLEDIT_NORMALBG,
+    SKIN_PLEDIT_SELECTEDBG,
+    SKIN_TEXTBG,
+    SKIN_TEXTFG,
+    SKIN_COLOR_COUNT
+} SkinColorId;
+
+typedef struct _SkinProperties {
+	/* this enables the othertext engine, not it's visibility -nenolod */
+	gboolean mainwin_othertext;
+
+	/* Vis properties */
+	gint mainwin_vis_x;
+	gint mainwin_vis_y;
+	gint mainwin_vis_width;
+	gboolean mainwin_vis_visible;
+
+	/* Text properties */
+	gint mainwin_text_x;
+	gint mainwin_text_y;
+	gint mainwin_text_width;
+	gboolean mainwin_text_visible;
+
+	/* Infobar properties */
+	gint mainwin_infobar_x;
+	gint mainwin_infobar_y;
+	gboolean mainwin_othertext_visible;
+
+	gint mainwin_number_0_x;
+	gint mainwin_number_0_y;
+
+	gint mainwin_number_1_x;
+	gint mainwin_number_1_y;
+
+	gint mainwin_number_2_x;
+	gint mainwin_number_2_y;
+
+	gint mainwin_number_3_x;
+	gint mainwin_number_3_y;
+
+	gint mainwin_number_4_x;
+	gint mainwin_number_4_y;
+
+	gint mainwin_playstatus_x;
+	gint mainwin_playstatus_y;
+
+	gint mainwin_volume_x;
+	gint mainwin_volume_y;	
+
+	gint mainwin_balance_x;
+	gint mainwin_balance_y;	
+
+	gint mainwin_position_x;
+	gint mainwin_position_y;
+
+	gint mainwin_previous_x;
+	gint mainwin_previous_y;
+
+	gint mainwin_play_x;
+	gint mainwin_play_y;
+
+	gint mainwin_pause_x;
+	gint mainwin_pause_y;
+
+	gint mainwin_stop_x;
+	gint mainwin_stop_y;
+
+	gint mainwin_next_x;
+	gint mainwin_next_y;
+
+	gint mainwin_eject_x;
+	gint mainwin_eject_y;
+
+	gint mainwin_eqbutton_x;
+	gint mainwin_eqbutton_y;
+
+	gint mainwin_plbutton_x;
+	gint mainwin_plbutton_y;
+
+	gint mainwin_shuffle_x;
+	gint mainwin_shuffle_y;
+
+	gint mainwin_repeat_x;
+	gint mainwin_repeat_y;
+
+	gint mainwin_about_x;
+	gint mainwin_about_y;
+
+	gint mainwin_minimize_x;
+	gint mainwin_minimize_y;
+
+	gint mainwin_shade_x;
+	gint mainwin_shade_y;
+
+	gint mainwin_close_x;
+	gint mainwin_close_y;
+
+	gint mainwin_width;
+	gint mainwin_height;
+
+	gboolean mainwin_menurow_visible;
+	gboolean mainwin_othertext_is_status;
+
+	gint textbox_bitmap_font_width;
+	gint textbox_bitmap_font_height;
+} SkinProperties;
+
+#define SKIN_PIXMAP(x)  ((SkinPixmap *)(x))
+typedef struct _SkinPixmap {
+    GdkPixmap *pixmap;
+    /* GdkPixmap *def_pixmap; */
+
+    /* The real size of the pixmap */
+    gint width, height;
+
+    /* The size of the pixmap from the current skin,
+       which might be smaller */
+    gint current_width, current_height;
+} SkinPixmap;
+
+
+#define SKIN(x)  ((Skin *)(x))
+typedef struct _Skin {
+    GMutex *lock;
+    gchar *path;
+    gchar *def_path;
+    SkinPixmap pixmaps[SKIN_PIXMAP_COUNT];
+    GdkColor textbg[6], def_textbg[6];
+    GdkColor textfg[6], def_textfg[6];
+    GdkColor *colors[SKIN_COLOR_COUNT];
+    guchar vis_color[24][3];
+    GdkBitmap *masks[SKIN_MASK_COUNT];
+    GdkBitmap *ds_masks[SKIN_MASK_COUNT];
+    SkinProperties properties;
+} Skin;
+
+extern Skin *bmp_active_skin;
+
+gboolean init_skins(const gchar * path);
+void cleanup_skins(void);
+
+gboolean bmp_active_skin_load(const gchar * path);
+gboolean bmp_active_skin_reload(void);
+
+Skin *skin_new(void);
+gboolean skin_load(Skin * skin, const gchar * path);
+gboolean skin_reload_forced(void);
+void skin_reload(Skin * skin);
+void skin_free(Skin * skin);
+
+GdkBitmap *skin_get_mask(Skin * skin, SkinMaskId mi);
+GdkColor *skin_get_color(Skin * skin, SkinColorId color_id);
+
+void skin_get_viscolor(Skin * skin, guchar vis_color[24][3]);
+gint skin_get_id(void);
+void skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
+                      SkinPixmapId pixmap_id,
+                      gint xsrc, gint ysrc, gint xdest, gint ydest,
+                      gint width, gint height);
+void skin_get_eq_spline_colors(Skin * skin, guint32 colors[19]);
+void skin_install_skin(const gchar * path);
+
+void skin_draw_playlistwin_shaded(Skin * skin,
+                                  GdkDrawable * drawable, GdkGC * gc,
+                                  gint width, gboolean focus);
+void skin_draw_playlistwin_frame(Skin * skin,
+                                 GdkDrawable * drawable, GdkGC * gc,
+                                 gint width, gint height, gboolean focus);
+
+void skin_draw_mainwin_titlebar(Skin * skin,
+                                GdkDrawable * drawable, GdkGC * gc,
+                                gboolean shaded, gboolean focus);
+
+
+void skin_parse_hints(Skin * skin, gchar *path_p);
+
+
+void skin_set_random_skin(void);
+
+#endif
--- a/src/audacious/ui_equalizer.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_equalizer.c	Tue Aug 07 18:07:37 2007 -0700
@@ -37,7 +37,7 @@
 #include <string.h>
 
 #include "platform/smartinclude.h"
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "dock.h"
 #include "hints.h"
 #include "input.h"
@@ -84,8 +84,6 @@
 static GtkWidget *equalizerwin_delete_window = NULL;
 static GtkWidget *equalizerwin_delete_auto_window = NULL;
 
-static GdkPixmap *equalizerwin_bg, *equalizerwin_bg_x2;
-
 static GtkWidget *equalizerwin_on, *equalizerwin_auto;
 
 static GtkWidget *equalizerwin_close, *equalizerwin_presets, *equalizerwin_shade;
@@ -142,12 +140,8 @@
 
     if (ds) {
         dock_window_resize(GTK_WINDOW(equalizerwin), 550, height * 2, 550, height * 2);
-        gdk_window_set_back_pixmap(equalizerwin->window, equalizerwin_bg_x2,
-                                   0);
-    }
-    else {
+    } else {
         dock_window_resize(GTK_WINDOW(equalizerwin), 275, height, 275, height);
-        gdk_window_set_back_pixmap(equalizerwin->window, equalizerwin_bg, 0);
     }
 
     GList *iter;
@@ -253,16 +247,6 @@
 equalizerwin_press(GtkWidget * widget, GdkEventButton * event,
                    gpointer callback_data)
 {
-    gint mx, my;
-    gboolean grab = TRUE;
-
-    mx = event->x;
-    my = event->y;
-    if (cfg.doublesize && cfg.eq_doublesize_linked) {
-        event->x /= 2;
-        event->y /= 2;
-    }
-
     if (event->button == 1 && event->type == GDK_BUTTON_PRESS &&
         (cfg.easy_move || cfg.equalizer_shaded || event->y < 14)) {
          equalizerwin_raise();
@@ -282,14 +266,8 @@
          */
        ui_manager_popup_menu_show(GTK_MENU(mainwin_general_menu), event->x_root,
                                 event->y_root + 2, 3, event->time);
-        grab = FALSE;
     }
 
-    if (grab)
-        gdk_pointer_grab(GDK_WINDOW(equalizerwin->window), FALSE,
-                         GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
-                         NULL, NULL, GDK_CURRENT_TIME);
-
     return FALSE;
 }
 
@@ -297,13 +275,6 @@
 equalizerwin_release(GtkWidget * widget,
                      GdkEventButton * event, gpointer callback_data)
 {
-    gdk_pointer_ungrab(GDK_CURRENT_TIME);
-    gdk_flush();
-
-    if (cfg.doublesize && cfg.eq_doublesize_linked) {
-        event->x /= 2;
-        event->y /= 2;
-    }
     if (dock_is_moving(GTK_WINDOW(equalizerwin))) {
         dock_move_release(GTK_WINDOW(equalizerwin));
     }
@@ -352,17 +323,6 @@
 }
 
 static void
-equalizerwin_set_back_pixmap(void)
-{
-    if (cfg.doublesize && cfg.eq_doublesize_linked)
-        gdk_window_set_back_pixmap(equalizerwin->window, equalizerwin_bg_x2,
-                                   0);
-    else
-        gdk_window_set_back_pixmap(equalizerwin->window, equalizerwin_bg, 0);
-    gdk_window_clear(equalizerwin->window);
-}
-
-static void
 equalizerwin_close_cb(void)
 {
     equalizerwin_show(FALSE);
@@ -614,8 +574,6 @@
                      G_CALLBACK(equalizerwin_release), NULL);
     g_signal_connect(equalizerwin, "configure_event",
                      G_CALLBACK(equalizerwin_configure), NULL);
-    g_signal_connect(equalizerwin, "style_set",
-                     G_CALLBACK(equalizerwin_set_back_pixmap), NULL);
     g_signal_connect(equalizerwin, "key_press_event",
                      G_CALLBACK(equalizerwin_keypress), NULL);
 }
@@ -630,10 +588,6 @@
 
     gtk_window_add_accel_group( GTK_WINDOW(equalizerwin) , ui_manager_get_accel_group() );
 
-    equalizerwin_bg = gdk_pixmap_new(equalizerwin->window, 275, 116, -1);
-    equalizerwin_bg_x2 = gdk_pixmap_new(equalizerwin->window, 550, 232, -1);
-
-    equalizerwin_set_back_pixmap();
     equalizerwin_create_widgets();
 }
 
--- a/src/audacious/ui_equalizer.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_equalizer.h	Tue Aug 07 18:07:37 2007 -0700
@@ -29,8 +29,6 @@
 #include <glib.h>
 #include <gtk/gtk.h>
 
-#include "widgets/widgetcore.h"
-
 #define EQUALIZER_DOUBLESIZE     (cfg.doublesize && cfg.eq_doublesize_linked)
 #define EQUALIZER_HEIGHT         ((cfg.equalizer_shaded ? 14 : 116) * (EQUALIZER_DOUBLESIZE + 1))
 #define EQUALIZER_WIDTH          (275 * (EQUALIZER_DOUBLESIZE + 1))
--- a/src/audacious/ui_jumptotrack.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_jumptotrack.c	Tue Aug 07 18:07:37 2007 -0700
@@ -53,7 +53,6 @@
   #include <regex.h>
 #endif
 
-#include "widgets/widgetcore.h"
 #include "ui_main.h"
 #include "icons-stock.h"
 
--- a/src/audacious/ui_main.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_main.c	Tue Aug 07 18:07:37 2007 -0700
@@ -53,7 +53,6 @@
   #include <regex.h>
 #endif
 
-#include "widgets/widgetcore.h"
 #include "ui_main.h"
 #include "icons-stock.h"
 
@@ -81,6 +80,7 @@
 #include "util.h"
 #include "visualization.h"
 
+#include "skin.h"
 #include "ui_skinned_window.h"
 #include "ui_skinned_button.h"
 #include "ui_skinned_textbox.h"
@@ -172,7 +172,7 @@
 
 static PlaybackInfo playback_info = { NULL, 0, 0, 0 };
 
-
+static void mainwin_refresh_visible(void);
 static gint mainwin_idle_func(gpointer data);
 
 static void set_timer_mode_menu_cb(TimerMode mode);
@@ -262,78 +262,17 @@
     cfg.player_shaded = shaded;
 
     mainwin_set_shape_mask();
-
     if (shaded) {
         dock_shade(dock_window_list, GTK_WINDOW(mainwin),
                    MAINWIN_SHADED_HEIGHT * (cfg.doublesize + 1));
-
-        gtk_widget_show(mainwin_svis);
-        ui_svis_clear_data(mainwin_svis);
-        if (cfg.vis_type != VIS_OFF)
-            ui_svis_set_visible(mainwin_svis, TRUE);
-        else
-            ui_svis_set_visible(mainwin_svis, FALSE);
-
-        gtk_widget_show(mainwin_srew);
-        gtk_widget_show(mainwin_splay);
-        gtk_widget_show(mainwin_spause);
-        gtk_widget_show(mainwin_sstop);
-        gtk_widget_show(mainwin_sfwd);
-        gtk_widget_show(mainwin_seject);
-
-        ui_skinned_textbox_set_scroll(mainwin_info, FALSE);
-        if (playback_get_playing())
-    {
-            gtk_widget_show(mainwin_sposition);
-            gtk_widget_show(mainwin_stime_min);
-            gtk_widget_show(mainwin_stime_sec);
-    }
-    else
-    {
-            gtk_widget_hide(mainwin_sposition);
-            gtk_widget_hide(mainwin_stime_min);
-            gtk_widget_hide(mainwin_stime_sec);
-    }
-
-    }
-    else {
-    gint height = !bmp_active_skin->properties.mainwin_height ? MAINWIN_HEIGHT :
-                     bmp_active_skin->properties.mainwin_height;
+    } else {
+        gint height = !bmp_active_skin->properties.mainwin_height ? MAINWIN_HEIGHT :
+                       bmp_active_skin->properties.mainwin_height;
 
         dock_shade(dock_window_list, GTK_WINDOW(mainwin), height * (cfg.doublesize + 1));
-
-        gtk_widget_hide(mainwin_svis);
-        ui_svis_clear_data(mainwin_svis);
-
-        gtk_widget_show(mainwin_vis);
-        if (cfg.vis_type != VIS_OFF)
-            ui_vis_set_visible(mainwin_vis, TRUE);
-        else
-            ui_vis_set_visible(mainwin_vis, FALSE);
-
-        gtk_widget_hide(mainwin_srew);
-        gtk_widget_hide(mainwin_splay);
-        gtk_widget_hide(mainwin_spause);
-        gtk_widget_hide(mainwin_sstop);
-        gtk_widget_hide(mainwin_sfwd);
-        gtk_widget_hide(mainwin_seject);
-
-        gtk_widget_hide(mainwin_stime_min);
-        gtk_widget_hide(mainwin_stime_sec);
-        gtk_widget_hide(mainwin_sposition);
-
-        if (playback_get_playing()) {
-            gtk_widget_show(mainwin_minus_num);
-            gtk_widget_show(mainwin_10min_num);
-            gtk_widget_show(mainwin_min_num);
-            gtk_widget_show(mainwin_10sec_num);
-            gtk_widget_show(mainwin_sec_num);
-            gtk_widget_show(mainwin_position);
-        }
-
-        ui_skinned_textbox_set_scroll(mainwin_info, cfg.autoscroll);
     }
 
+    mainwin_refresh_visible();
     ui_skinned_set_push_button_data(mainwin_shade, 0, cfg.player_shaded ? 27 : 18, 9, cfg.player_shaded ? 27 : 18);
 }
 
@@ -581,35 +520,88 @@
     gtk_window_set_title(GTK_WINDOW(mainwin), mainwin_title_text);
 }
 
+static void
+mainwin_refresh_visible(void)
+{
+    if (!bmp_active_skin)
+        return;
+
+    gtk_widget_show_all(mainwin);
+
+    if (!bmp_active_skin->properties.mainwin_text_visible)
+        gtk_widget_hide(mainwin_info);
+
+    if (!bmp_active_skin->properties.mainwin_vis_visible)
+        gtk_widget_hide(mainwin_vis);
+
+    if (!bmp_active_skin->properties.mainwin_menurow_visible)
+        gtk_widget_hide(mainwin_menurow);
+
+    if (bmp_active_skin->properties.mainwin_othertext) {
+        gtk_widget_hide(mainwin_rate_text);
+        gtk_widget_hide(mainwin_freq_text);
+        gtk_widget_hide(mainwin_monostereo);
+
+        if (!bmp_active_skin->properties.mainwin_othertext_visible)
+            gtk_widget_hide(mainwin_othertext);
+    } else {
+        gtk_widget_hide(mainwin_othertext);
+    }
+
+    if (!bmp_active_skin->properties.mainwin_vis_visible)
+        gtk_widget_hide(mainwin_vis);
+
+    if (!playback_get_playing()) {
+        gtk_widget_hide(mainwin_minus_num);
+        gtk_widget_hide(mainwin_10min_num);
+        gtk_widget_hide(mainwin_min_num);
+        gtk_widget_hide(mainwin_10sec_num);
+        gtk_widget_hide(mainwin_sec_num);
+
+        gtk_widget_hide(mainwin_stime_min);
+        gtk_widget_hide(mainwin_stime_sec);
+
+        gtk_widget_hide(mainwin_position);
+        gtk_widget_hide(mainwin_sposition);
+    }
+
+    if (cfg.player_shaded) {
+        ui_svis_clear_data(mainwin_svis);
+        if (cfg.vis_type != VIS_OFF)
+            ui_svis_set_visible(mainwin_svis, TRUE);
+        else
+            ui_svis_set_visible(mainwin_svis, FALSE);
+
+        ui_skinned_textbox_set_scroll(mainwin_info, FALSE);
+        if (!playback_get_playing()) {
+            gtk_widget_hide(mainwin_sposition);
+            gtk_widget_hide(mainwin_stime_min);
+            gtk_widget_hide(mainwin_stime_sec);
+        }
+    } else {
+        gtk_widget_hide(mainwin_srew);
+        gtk_widget_hide(mainwin_splay);
+        gtk_widget_hide(mainwin_spause);
+        gtk_widget_hide(mainwin_sstop);
+        gtk_widget_hide(mainwin_sfwd);
+        gtk_widget_hide(mainwin_seject);
+        gtk_widget_hide(mainwin_stime_min);
+        gtk_widget_hide(mainwin_stime_sec);
+        gtk_widget_hide(mainwin_svis);
+        gtk_widget_hide(mainwin_sposition);
+        ui_vis_clear_data(mainwin_vis);
+        if (cfg.vis_type != VIS_OFF)
+            ui_vis_set_visible(mainwin_vis, TRUE);
+        else
+            ui_vis_set_visible(mainwin_vis, FALSE);
+
+        ui_skinned_textbox_set_scroll(mainwin_info, cfg.autoscroll);
+    }
+}
+
 void
 mainwin_refresh_hints(void)
 {
-    if (bmp_active_skin && bmp_active_skin->properties.mainwin_othertext
-    == TRUE)
-    {
-    gtk_widget_hide(mainwin_rate_text);
-    gtk_widget_hide(mainwin_freq_text);
-    gtk_widget_hide(mainwin_monostereo);
-
-    if (bmp_active_skin->properties.mainwin_othertext_visible)
-        gtk_widget_show(mainwin_othertext);
-    else
-        if (GTK_WIDGET_VISIBLE(mainwin_othertext))
-            gtk_widget_hide(mainwin_othertext);
-    }
-    else
-    {
-    gtk_widget_show(mainwin_rate_text);
-    gtk_widget_show(mainwin_freq_text);
-    gtk_widget_show(mainwin_monostereo);
-    gtk_widget_hide(mainwin_othertext);
-    }
-
-    if (bmp_active_skin->properties.mainwin_vis_visible)
-        gtk_widget_show(mainwin_vis);
-    else
-        gtk_widget_hide(mainwin_vis);
-
     /* positioning and size attributes */
     if (bmp_active_skin->properties.mainwin_vis_x && bmp_active_skin->properties.mainwin_vis_y)
     gtk_fixed_move(GTK_FIXED(SKINNED_WINDOW(mainwin)->fixed), GTK_WIDGET(mainwin_vis), bmp_active_skin->properties.mainwin_vis_x,
@@ -723,12 +715,7 @@
     gtk_fixed_move(GTK_FIXED(SKINNED_WINDOW(mainwin)->fixed), GTK_WIDGET(mainwin_close), cfg.player_shaded ? 264 : bmp_active_skin->properties.mainwin_close_x,
         cfg.player_shaded ? 3 : bmp_active_skin->properties.mainwin_close_y);
 
-    /* visibility attributes */
-    if (bmp_active_skin->properties.mainwin_menurow_visible)
-        gtk_widget_show(mainwin_menurow);
-    else
-        gtk_widget_hide(mainwin_menurow);
-
+    mainwin_refresh_visible();
     /* window size, mainwinWidth && mainwinHeight properties */
     if (bmp_active_skin->properties.mainwin_height && bmp_active_skin->properties.mainwin_width)
     {
@@ -787,8 +774,7 @@
     if (!playback_get_paused() && mainwin_playstatus != NULL)
         ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PLAY);
 
-    if (bmp_active_skin && bmp_active_skin->properties.mainwin_othertext
-    == TRUE)
+    if (bmp_active_skin && bmp_active_skin->properties.mainwin_othertext)
     {
         if (bitrate != -1)
             text = g_strdup_printf("%d kbps, %0.1f kHz, %s",
@@ -801,12 +787,6 @@
             (n_channels > 1) ? _("stereo") : _("mono"));
 
         ui_skinned_textbox_set_text(mainwin_othertext, text);
-
-        gtk_widget_hide(mainwin_monostereo);
-    }
-    else
-    {
-        gtk_widget_show(mainwin_monostereo);
     }
 
     title = playlist_get_info_text(playlist);
@@ -838,20 +818,7 @@
     if (mainwin_playstatus != NULL)
         ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_STOP);
 
-    /* hide playback time */
-    gtk_widget_hide(mainwin_minus_num);
-    gtk_widget_hide(mainwin_10min_num);
-    gtk_widget_hide(mainwin_min_num);
-    gtk_widget_hide(mainwin_10sec_num);
-    gtk_widget_hide(mainwin_sec_num);
-
-    gtk_widget_hide(mainwin_stime_min);
-    gtk_widget_hide(mainwin_stime_sec);
-
-    gtk_widget_hide(mainwin_position);
-    gtk_widget_hide(mainwin_sposition);
-
-    gtk_widget_hide(mainwin_othertext);
+    mainwin_refresh_visible();
 
     playlistwin_hide_timer();
     ui_vis_clear_data(mainwin_vis);
@@ -873,16 +840,6 @@
                              GdkEventButton * event,
                              gpointer callback_data)
 {
-    gdk_pointer_ungrab(GDK_CURRENT_TIME);
-
-    /*
-     * The gdk_flush() is just for making sure that the pointer really
-     * gets ungrabbed before calling any button callbacks
-     *
-     */
-
-    gdk_flush();
-
     if (dock_is_moving(GTK_WINDOW(mainwin))) {
         dock_move_release(GTK_WINDOW(mainwin));
     }
@@ -890,41 +847,6 @@
     return FALSE;
 }
 
-static gboolean
-mainwin_motion(GtkWidget * widget,
-               GdkEventMotion * event,
-               gpointer callback_data)
-{
-    int x, y;
-    GdkModifierType state;
-
-    /* If it's a hint, we had to query X, so override the
-     * information we we're given... it's probably useless... --nenolod
-     */
-    if (event->is_hint != FALSE)
-    {
-        gdk_window_get_pointer(GDK_WINDOW(mainwin->window), &x, &y, &state);
-
-        event->x = x;
-        event->y = y;
-        event->state = state;
-    }
-    else
-    {
-        x = event->x;
-        y = event->y;
-        state = event->state;
-    }
-    if (cfg.doublesize) {
-        event->x /= 2;
-        event->y /= 2;
-    }
-
-    gdk_flush();
-
-    return FALSE;
-}
-
 void
 mainwin_scrolled(GtkWidget *widget, GdkEventScroll *event,
     gpointer callback_data)
@@ -956,9 +878,6 @@
                            GdkEventButton * event,
                            gpointer callback_data)
 {
-
-    gboolean grab = TRUE;
-
     if (cfg.doublesize) {
         /*
          * A hack to make doublesize transparent to callbacks.
@@ -988,7 +907,6 @@
             ui_manager_popup_menu_show(GTK_MENU(mainwin_playback_menu),
                                     event->x_root,
                                     event->y_root, 3, event->time);
-            grab = FALSE;
         } else {
             /*
              * Pop up the main menu a few pixels down.
@@ -1002,16 +920,9 @@
             ui_manager_popup_menu_show(GTK_MENU(mainwin_general_menu),
                                     event->x_root,
                                     event->y_root, 3, event->time);
-            grab = FALSE;
         }
     }
 
-    if (grab)
-        gdk_pointer_grab(mainwin->window, FALSE,
-                         GDK_BUTTON_MOTION_MASK |
-                         GDK_BUTTON_RELEASE_MASK,
-                         GDK_WINDOW(GDK_NONE), NULL, GDK_CURRENT_TIME);
-
     return FALSE;
 }
 
@@ -1465,8 +1376,8 @@
 mainwin_stop_pushed(void)
 {
     ip_data.stop = TRUE;
+    playback_stop();
     mainwin_clear_song_info();
-    playback_stop();
     ab_position_a = ab_position_b = -1;
     ip_data.stop = FALSE;
 }
@@ -1780,42 +1691,7 @@
         gtk_window_move(GTK_WINDOW(mainwin), cfg.player_x, cfg.player_y);
 
     gtk_window_present(GTK_WINDOW(mainwin));
-    gtk_widget_show_all(mainwin);
-
-    if (!bmp_active_skin->properties.mainwin_text_visible)
-        gtk_widget_hide(mainwin_info);
-
-    if (!cfg.player_shaded) {
-        gtk_widget_hide(mainwin_srew);
-        gtk_widget_hide(mainwin_splay);
-        gtk_widget_hide(mainwin_spause);
-        gtk_widget_hide(mainwin_sstop);
-        gtk_widget_hide(mainwin_sfwd);
-        gtk_widget_hide(mainwin_seject);
-        gtk_widget_hide(mainwin_stime_min);
-        gtk_widget_hide(mainwin_stime_sec);
-        gtk_widget_hide(mainwin_svis);
-    }
-
-    gtk_widget_hide(mainwin_minus_num);
-    gtk_widget_hide(mainwin_10min_num);
-    gtk_widget_hide(mainwin_min_num);
-    gtk_widget_hide(mainwin_10sec_num);
-    gtk_widget_hide(mainwin_sec_num);
-    gtk_widget_hide(mainwin_othertext);
-
-    gtk_widget_hide(mainwin_position);
-    gtk_widget_hide(mainwin_sposition);
-
-    if (bmp_active_skin->properties.mainwin_vis_visible)
-        gtk_widget_show(mainwin_vis);
-    else
-        gtk_widget_hide(mainwin_vis);
-
-    if (bmp_active_skin->properties.mainwin_menurow_visible)
-        gtk_widget_show(mainwin_menurow);
-    else
-        gtk_widget_hide(mainwin_menurow);
+    mainwin_refresh_hints();
 }
 
 void
@@ -2772,8 +2648,6 @@
                      G_CALLBACK(mainwin_scrolled), NULL);
     g_signal_connect(mainwin, "button_release_event",
                      G_CALLBACK(mainwin_mouse_button_release), NULL);
-    g_signal_connect(mainwin, "motion_notify_event",
-                     G_CALLBACK(mainwin_motion), NULL);
     g_signal_connect(mainwin, "configure_event",
                      G_CALLBACK(mainwin_configure), NULL);
 
--- a/src/audacious/ui_main.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_main.h	Tue Aug 07 18:07:37 2007 -0700
@@ -25,7 +25,6 @@
 
 #include <gtk/gtk.h>
 
-#include "widgets/widgetcore.h"
 #include "ui_vis.h"
 #include "ui_svis.h"
 
--- a/src/audacious/ui_main_evlisteners.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_main_evlisteners.c	Tue Aug 07 18:07:37 2007 -0700
@@ -27,6 +27,7 @@
 
 #include "ui_main.h"
 #include "ui_skinned_textbox.h"
+#include "ui_playlist.h"
 
 static void
 ui_main_evlistener_title_change(gpointer hook_data, gpointer user_data)
@@ -34,7 +35,7 @@
     gchar *text = (gchar *) hook_data;
 
     ui_skinned_textbox_set_text(mainwin_info, text);
-
+    playlistwin_update_list(playlist_get_active());
     g_free(text);
 }
 
--- a/src/audacious/ui_manager.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_manager.c	Tue Aug 07 18:07:37 2007 -0700
@@ -29,8 +29,6 @@
 /* TODO ui_main.h is only included because ui_manager.c needs the values of
    TimerMode enum; move that enum elsewhere so we can get rid of this include */
 #include "ui_main.h"
-/* we need this to define values of visualization radio-actions */
-#include "widgets/widgetcore.h"
 
 #include "icons-stock.h"
 
--- a/src/audacious/ui_playlist.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_playlist.c	Tue Aug 07 18:07:37 2007 -0700
@@ -71,7 +71,6 @@
 GtkWidget *playlistwin_list = NULL;
 GtkWidget *playlistwin_shade, *playlistwin_close;
 
-static GdkPixmap *playlistwin_bg;
 static GdkBitmap *playlistwin_mask = NULL;
 
 static gboolean playlistwin_hint_flag = FALSE;
@@ -276,10 +275,10 @@
     /* this can happen early on. just bail gracefully. */
     g_return_if_fail(playlistwin_list);
 
+    playlistwin_update_info(playlist);
+    playlistwin_update_sinfo(playlist);
     gtk_widget_queue_draw(playlistwin_list);
     gtk_widget_queue_draw(playlistwin_slider);
-    playlistwin_update_info(playlist);
-    playlistwin_update_sinfo(playlist);
 }
 
 static void
@@ -417,9 +416,7 @@
     if (event->button == 3)
         return;
 
-    gdk_pointer_ungrab(GDK_CURRENT_TIME);
     playlistwin_resizing = FALSE;
-    gdk_flush();
 
     if (dock_is_moving(GTK_WINDOW(playlistwin)))
        dock_move_release(GTK_WINDOW(playlistwin));
@@ -664,7 +661,6 @@
     ui_skinned_playlist_slider_move_relative(playlistwin_slider, dx);
     ui_skinned_playlist_slider_resize_relative(playlistwin_slider, dy);
 
-    ui_skinned_textbox_resize_relative(playlistwin_sinfo, dx);
     playlistwin_update_sinfo(playlist_get_active());
 
     ui_skinned_button_move_relative(playlistwin_shade, dx, 0);
@@ -681,10 +677,10 @@
     ui_skinned_button_move_relative(playlistwin_sscroll_up, dx, dy);
     ui_skinned_button_move_relative(playlistwin_sscroll_down, dx, dy);
 
-    g_object_unref(playlistwin_bg);
-    playlistwin_bg = gdk_pixmap_new(playlistwin->window, width, height, -1);
     playlistwin_set_mask();
 
+    gtk_widget_set_size_request(playlistwin_sinfo, playlistwin_get_width() - 35,
+                                bmp_active_skin->properties.textbox_bitmap_font_height);
     GList *iter;
     for (iter = GTK_FIXED (SKINNED_WINDOW(playlistwin)->fixed)->children; iter; iter = g_list_next (iter)) {
          GtkFixedChild *child_data = (GtkFixedChild *) iter->data;
@@ -1001,7 +997,8 @@
     if (event->direction == GDK_SCROLL_UP)
         playlistwin_scroll(-cfg.scroll_pl_by);
 
-    g_cond_signal(cond_scan);
+    // deactivating this fixed a gui freeze when scrolling. -- mf0102
+    //g_cond_signal(cond_scan);
 
 }
 
@@ -1010,7 +1007,6 @@
                   GdkEventButton * event,
                   gpointer callback_data)
 {
-    gboolean grab = TRUE;
     gint xpos, ypos;
     GtkRequisition req;
     Playlist *playlist = playlist_get_active();
@@ -1041,7 +1037,6 @@
                    (ypos + playlistwin_get_height()) - 8 - req.height,
                    event->button,
                    event->time);
-        grab = FALSE;
     }
     else if (event->button == 1 && REGION_L(41, 66, 29, 11)) {
         /* SUB button menu */
@@ -1051,7 +1046,6 @@
                    (ypos + playlistwin_get_height()) - 8 - req.height,
                    event->button,
                    event->time);
-        grab = FALSE;
     }
     else if (event->button == 1 && REGION_L(70, 95, 29, 11)) {
         /* SEL button menu */
@@ -1061,7 +1055,6 @@
                    (ypos + playlistwin_get_height()) - 8 - req.height,
                    event->button,
                    event->time);
-        grab = FALSE;
     }
     else if (event->button == 1 && REGION_L(99, 124, 29, 11)) {
         /* MISC button menu */
@@ -1071,7 +1064,6 @@
                    (ypos + playlistwin_get_height()) - 8 - req.height,
                    event->button,
                    event->time);
-        grab = FALSE;
     }
     else if (event->button == 1 && REGION_R(46, 23, 29, 11)) {
         /* LIST button menu */
@@ -1081,7 +1073,6 @@
                    (ypos + playlistwin_get_height()) - 8 - req.height,
                    event->button,
                    event->time);
-        grab = FALSE;
     }
     else if (event->button == 1 && REGION_R(82, 54, 15, 9)) {
         if (cfg.timer_mode == TIMER_ELAPSED)
@@ -1119,7 +1110,6 @@
          */
         ui_manager_popup_menu_show(GTK_MENU(mainwin_general_menu), event->x_root,
                                 event->y_root + 2, 3, event->time);
-        grab = FALSE;
     }
     else if (event->button == 1 && (event->state & GDK_MOD1_MASK))
     {
@@ -1132,17 +1122,8 @@
             idx = GPOINTER_TO_INT(playlist_get_selected(playlist)->data);
             playlist_queue_position(playlist, idx);
         }
-
-        grab = FALSE;
     }
 
-    if (grab)
-        gdk_pointer_grab(playlistwin->window, FALSE,
-                         GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK |
-                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-                         GDK_BUTTON1_MOTION_MASK, NULL, NULL,
-                         GDK_CURRENT_TIME);
-
     return FALSE;
 }
 
@@ -1260,6 +1241,7 @@
             if (!playback_get_playing())
                 playback_initiate();
         }
+        refresh = TRUE;
         break;
     case GDK_3:
         if (event->state & GDK_CONTROL_MASK)
@@ -1308,7 +1290,8 @@
     }
 
     if (refresh) {
-        g_cond_signal(cond_scan);
+        // fixes keyboard scrolling gui freeze for me. -- mf0102
+        //g_cond_signal(cond_scan);
         playlistwin_update_list(playlist_get_active());
     }
 
--- a/src/audacious/ui_playlist.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_playlist.h	Tue Aug 07 18:07:37 2007 -0700
@@ -26,7 +26,6 @@
 #include <glib.h>
 
 #include "ui_main.h"
-#include "widgets/widgetcore.h"
 #include "playlist.h"
 
 #define PLAYLISTWIN_FRAME_TOP_HEIGHT    20
--- a/src/audacious/ui_preferences.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_preferences.c	Tue Aug 07 18:07:37 2007 -0700
@@ -49,7 +49,6 @@
 #include "visualization.h"
 
 #include "main.h"
-#include "widgets/widgetcore.h"
 #include "ui_skinned_textbox.h"
 #include "strings.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_button.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_button.c	Tue Aug 07 18:07:37 2007 -0700
@@ -18,7 +18,6 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
 #include "ui_skinned_button.h"
 #include "util.h"
 
--- a/src/audacious/ui_skinned_button.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_button.h	Tue Aug 07 18:07:37 2007 -0700
@@ -22,6 +22,7 @@
 #define UISKINNEDBUTTON_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #define UI_SKINNED_BUTTON(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ui_skinned_button_get_type(), UiSkinnedButton))
 #define UI_SKINNED_BUTTON_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  ui_skinned_button_get_type(), UiSkinnedButtonClass))
--- a/src/audacious/ui_skinned_equalizer_graph.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_equalizer_graph.c	Tue Aug 07 18:07:37 2007 -0700
@@ -21,7 +21,7 @@
  * along with this program;  If not, see <http://www.gnu.org/licenses>.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_skinned_equalizer_graph.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_equalizer_graph.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_equalizer_graph.h	Tue Aug 07 18:07:37 2007 -0700
@@ -28,6 +28,7 @@
 #define UISKINNEDEQUALIZERGRAPH_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_equalizer_slider.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_equalizer_slider.c	Tue Aug 07 18:07:37 2007 -0700
@@ -21,7 +21,7 @@
  * along with this program;  If not, see <http://www.gnu.org/licenses>.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_skinned_equalizer_slider.h"
 #include "util.h"
 #include "ui_equalizer.h"
--- a/src/audacious/ui_skinned_equalizer_slider.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_equalizer_slider.h	Tue Aug 07 18:07:37 2007 -0700
@@ -25,6 +25,7 @@
 #define UISKINNEDEQUALIZER_SLIDER_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_horizontal_slider.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_horizontal_slider.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,6 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
 #include "ui_skinned_horizontal_slider.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_horizontal_slider.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_horizontal_slider.h	Tue Aug 07 18:07:37 2007 -0700
@@ -28,6 +28,7 @@
 #define UISKINNEDHORIZONTAL_SLIDER_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_menurow.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_menurow.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,6 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
 #include "ui_skinned_menurow.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_menurow.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_menurow.h	Tue Aug 07 18:07:37 2007 -0700
@@ -28,6 +28,7 @@
 #define UISKINNEDMENUROW_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_monostereo.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_monostereo.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,7 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_skinned_monostereo.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_monostereo.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_monostereo.h	Tue Aug 07 18:07:37 2007 -0700
@@ -28,6 +28,7 @@
 #define UISKINNEDMONOSTEREO_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_number.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_number.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,6 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
 #include "ui_skinned_number.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_number.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_number.h	Tue Aug 07 18:07:37 2007 -0700
@@ -21,9 +21,8 @@
 #ifndef UISKINNEDNUMBER_H
 #define UISKINNEDNUMBER_H
 
-#include <gdk/gdk.h>
-#include <gtk/gtkadjustment.h>
-#include <gtk/gtkwidget.h>
+#include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_playlist.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_playlist.c	Tue Aug 07 18:07:37 2007 -0700
@@ -39,7 +39,7 @@
  */
 
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_skinned_playlist.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/ui_skinned_playlist.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_playlist.h	Tue Aug 07 18:07:37 2007 -0700
@@ -28,6 +28,7 @@
 #define UISKINNEDPLAYLIST_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/audacious/ui_skinned_playlist_slider.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_playlist_slider.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,7 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_skinned_playlist_slider.h"
 #include "main.h"
 #include "util.h"
@@ -296,7 +296,6 @@
         }
         gtk_widget_queue_draw(widget);
     }
-
     return TRUE;
 }
 
--- a/src/audacious/ui_skinned_playstatus.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_playstatus.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,12 +24,10 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_skinned_playstatus.h"
 #include "main.h"
 #include "util.h"
-#include <gtk/gtkmain.h>
-#include <gtk/gtkmarshal.h>
 
 #define UI_TYPE_SKINNED_PLAYSTATUS           (ui_skinned_playstatus_get_type())
 
--- a/src/audacious/ui_skinned_textbox.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_textbox.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,6 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
 #include "ui_skinned_textbox.h"
 #include "main.h"
 #include "util.h"
@@ -64,7 +63,6 @@
     GdkPixmap        *pixmap;
     gboolean         scroll_allowed, scroll_enabled;
     gint             scroll_dummy;
-    gint             resize_width;
     gint             move_x, move_y;
 };
 
@@ -165,7 +163,6 @@
 
 static void ui_skinned_textbox_init(UiSkinnedTextbox *textbox) {
     UiSkinnedTextboxPrivate *priv = UI_SKINNED_TEXTBOX_GET_PRIVATE(textbox);
-    priv->resize_width = 0;
     priv->move_x = 0;
     priv->move_y = 0;
 }
@@ -265,16 +262,12 @@
     textbox->y = widget->allocation.y/(priv->double_size ? 2 : 1);
 
     if (textbox->width != widget->allocation.width/(priv->double_size ? 2 : 1)) {
-        if (textbox->width + priv->resize_width == widget->allocation.width/(priv->double_size ? 2 : 1)) {
-            textbox->width += priv->resize_width;
-            priv->resize_width = 0;
+            textbox->width = widget->allocation.width/(priv->double_size ? 2 : 1);
             if (priv->pixmap_text) g_free(priv->pixmap_text);
             priv->pixmap_text = NULL;
             priv->offset = 0;
             gtk_widget_set_size_request(widget, textbox->width, textbox->height);
             gtk_widget_queue_draw(GTK_WIDGET(textbox));
-        } else if (priv->resize_width == 0)
-            textbox->width = widget->allocation.width/(priv->double_size ? 2 : 1);
     }
 }
 
@@ -435,10 +428,6 @@
 static void ui_skinned_textbox_redraw(UiSkinnedTextbox *textbox) {
     UiSkinnedTextboxPrivate *priv = UI_SKINNED_TEXTBOX_GET_PRIVATE(textbox);
 
-    if (priv->resize_width)
-        gtk_widget_set_size_request(GTK_WIDGET(textbox),
-                                   (textbox->width+priv->resize_width)*(1+priv->double_size),
-                                   (textbox->height)*(1+priv->double_size));
     if (priv->move_x || priv->move_y)
         gtk_fixed_move(GTK_FIXED(priv->fixed), GTK_WIDGET(textbox), textbox->x+priv->move_x, textbox->y+priv->move_y);
 
@@ -890,8 +879,3 @@
     priv->move_x += x;
     priv->move_y += y;
 }
-
-void ui_skinned_textbox_resize_relative(GtkWidget *widget, gint w) {
-    UiSkinnedTextboxPrivate *priv = UI_SKINNED_TEXTBOX_GET_PRIVATE(widget);
-    priv->resize_width += w;
-}
--- a/src/audacious/ui_skinned_textbox.h	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_textbox.h	Tue Aug 07 18:07:37 2007 -0700
@@ -28,6 +28,7 @@
 #define UISKINNEDTEXTBOX_H
 
 #include <gtk/gtk.h>
+#include "skin.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -62,7 +63,6 @@
 void ui_skinned_textbox_set_text(GtkWidget *widget, const gchar *text);
 void ui_skinned_textbox_set_scroll(GtkWidget *widget, gboolean scroll);
 void ui_skinned_textbox_move_relative(GtkWidget *widget, gint x, gint y);
-void ui_skinned_textbox_resize_relative(GtkWidget *widget, gint w);
 
 #ifdef __cplusplus
 }
--- a/src/audacious/ui_skinned_window.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinned_window.c	Tue Aug 07 18:07:37 2007 -0700
@@ -19,7 +19,7 @@
  */
 
 #include "platform/smartinclude.h"
-#include "widgets/widgetcore.h"
+#include "skin.h"
 
 #include <gtk/gtkmain.h>
 #include <glib-object.h>
@@ -102,6 +102,18 @@
     return FALSE;
 }
 
+static gboolean ui_skinned_window_focus_in(GtkWidget *widget, GdkEventFocus *focus) {
+    gboolean val = GTK_WIDGET_CLASS (parent)->focus_in_event (widget, focus);
+    gtk_widget_queue_draw(widget);
+    return val;
+}
+
+static gboolean ui_skinned_window_focus_out(GtkWidget *widget, GdkEventFocus *focus) {
+    gboolean val = GTK_WIDGET_CLASS (parent)->focus_out_event (widget, focus);
+    gtk_widget_queue_draw(widget);
+    return val;
+}
+
 static gboolean ui_skinned_window_expose(GtkWidget *widget, GdkEventExpose *event) {
     SkinnedWindow *window = SKINNED_WINDOW(widget);
 
@@ -187,6 +199,8 @@
     widget_class->configure_event = ui_skinned_window_configure;
     widget_class->motion_notify_event = ui_skinned_window_motion_notify_event;
     widget_class->expose_event = ui_skinned_window_expose;
+    widget_class->focus_in_event = ui_skinned_window_focus_in;
+    widget_class->focus_out_event = ui_skinned_window_focus_out;
 }
 
 void
--- a/src/audacious/ui_skinselector.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_skinselector.c	Tue Aug 07 18:07:37 2007 -0700
@@ -36,7 +36,7 @@
 #include <string.h>
 
 #include "main.h"
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "util.h"
 
 #define EXTENSION_TARGETS 7
--- a/src/audacious/ui_svis.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_svis.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,7 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_svis.h"
 #include "ui_vis.h"
 #include "main.h"
--- a/src/audacious/ui_vis.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/ui_vis.c	Tue Aug 07 18:07:37 2007 -0700
@@ -24,7 +24,7 @@
  * Audacious or using our public API to be a derived work.
  */
 
-#include "widgets/widgetcore.h"
+#include "skin.h"
 #include "ui_vis.h"
 #include "main.h"
 #include "util.h"
--- a/src/audacious/visualization.c	Sat Aug 04 01:15:07 2007 -0700
+++ b/src/audacious/visualization.c	Tue Aug 07 18:07:37 2007 -0700
@@ -36,7 +36,6 @@
 #include "playback.h"
 #include "plugin.h"
 #include "ui_preferences.h"
-#include "widgets/widgetcore.h"
 
 VisPluginData vp_data = {
     NULL,
--- a/src/audacious/widgets/Makefile	Sat Aug 04 01:15:07 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-include ../../../mk/rules.mk
-include ../../../mk/init.mk
-
-OBJECTIVE_LIBS_NOINST = libwidgets.a
-
-LDFLAGS += -Wl,-export-dynamic
-
-CFLAGS += \
-	$(GTK_CFLAGS)      \
-	$(DBUS_CFLAGS)     \
-	$(MOWGLI_CFLAGS)   \
-	$(LIBGLADE_CFLAGS) \
-	$(BEEP_DEFINES)    \
-	$(ARCH_DEFINES)    \
-	-D_AUDACIOUS_CORE  \
-	-I../../.. \
-	-I../..    \
-	-I..	   \
-	-I../../intl
-
-SOURCES = \
-	skin.c
-
-OBJECTS = ${SOURCES:.c=.o}
-
-include ../../../mk/objective.mk
--- a/src/audacious/widgets/skin.c	Sat Aug 04 01:15:07 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1901 +0,0 @@
-/*  Audacious
- *  Copyright (C) 2005-2007  Audacious development team.
- *
- *  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; under version 3 of the License.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses>.
- *
- *  The Audacious team does not consider modular code linking to
- *  Audacious or using our public API to be a derived work.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-/* TODO: enforce default sizes! */
-
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "widgetcore.h"
-
-#include "ui_equalizer.h"
-#include "main.h"
-#include "ui_playlist.h"
-#include "ui_skinselector.h"
-#include "util.h"
-
-#include "debug.h"
-
-#include "platform/smartinclude.h"
-#include "vfs.h"
-
-#include "ui_skinned_window.h"
-
-#define EXTENSION_TARGETS 7
-
-static gchar *ext_targets[EXTENSION_TARGETS] =
-{ "bmp", "xpm", "png", "svg", "gif", "jpg", "jpeg" };
-
-struct _SkinPixmapIdMapping {
-    SkinPixmapId id;
-    const gchar *name;
-    const gchar *alt_name;
-    gint width, height;
-};
-
-struct _SkinMaskInfo {
-    gint width, height;
-    gchar *inistr;
-};
-
-typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping;
-typedef struct _SkinMaskInfo SkinMaskInfo;
-
-
-Skin *bmp_active_skin = NULL;
-
-static gint skin_current_num;
-
-static SkinMaskInfo skin_mask_info[] = {
-    {275, 116, "Normal"},
-    {275, 16,  "WindowShade"},
-    {275, 116, "Equalizer"},
-    {275, 16,  "EqualizerWS"}
-};
-
-static SkinPixmapIdMapping skin_pixmap_id_map[] = {
-    {SKIN_MAIN, "main", NULL, 0, 0},
-    {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0},
-    {SKIN_SHUFREP, "shufrep", NULL, 0, 0},
-    {SKIN_TEXT, "text", NULL, 0, 0},
-    {SKIN_TITLEBAR, "titlebar", NULL, 0, 0},
-    {SKIN_VOLUME, "volume", NULL, 0, 0},
-    {SKIN_BALANCE, "balance", "volume", 0, 0},
-    {SKIN_MONOSTEREO, "monoster", NULL, 0, 0},
-    {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0},
-    {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0},
-    {SKIN_POSBAR, "posbar", NULL, 0, 0},
-    {SKIN_EQMAIN, "eqmain", NULL, 0, 0},
-    {SKIN_PLEDIT, "pledit", NULL, 0, 0},
-    {SKIN_EQ_EX, "eq_ex", NULL, 0, 0}
-};
-
-static guint skin_pixmap_id_map_size = G_N_ELEMENTS(skin_pixmap_id_map);
-
-static const guchar skin_default_viscolor[24][3] = {
-    {9, 34, 53},
-    {10, 18, 26},
-    {0, 54, 108},
-    {0, 58, 116},
-    {0, 62, 124},
-    {0, 66, 132},
-    {0, 70, 140},
-    {0, 74, 148},
-    {0, 78, 156},
-    {0, 82, 164},
-    {0, 86, 172},
-    {0, 92, 184},
-    {0, 98, 196},
-    {0, 104, 208},
-    {0, 110, 220},
-    {0, 116, 232},
-    {0, 122, 244},
-    {0, 128, 255},
-    {0, 128, 255},
-    {0, 104, 208},
-    {0, 80, 160},
-    {0, 56, 112},
-    {0, 32, 64},
-    {200, 200, 200}
-};
-
-static GdkBitmap *skin_create_transparent_mask(const gchar *,
-                                               const gchar *,
-                                               const gchar *,
-                                               GdkWindow *,
-                                               gint, gint, gboolean);
-
-static void skin_setup_masks(Skin * skin);
-
-static void skin_set_default_vis_color(Skin * skin);
-
-void
-skin_lock(Skin * skin)
-{
-    g_mutex_lock(skin->lock);
-}
-
-void
-skin_unlock(Skin * skin)
-{
-    g_mutex_unlock(skin->lock);
-}
-
-gboolean
-bmp_active_skin_reload(void) 
-{
-    return bmp_active_skin_load(bmp_active_skin->path); 
-}
-
-gboolean
-bmp_active_skin_load(const gchar * path)
-{
-    g_return_val_if_fail(bmp_active_skin != NULL, FALSE);
-
-    memset(&bmp_active_skin->properties, 0, sizeof(SkinProperties));
-
-    if (!skin_load(bmp_active_skin, path))
-        return FALSE;
-
-    skin_setup_masks(bmp_active_skin);
-
-    ui_skinned_window_draw_all(mainwin);
-    ui_skinned_window_draw_all(equalizerwin);
-    ui_skinned_window_draw_all(playlistwin);
-
-    playlistwin_update_list(playlist_get_active());
-
-    return TRUE;
-}
-
-void
-skin_pixmap_free(SkinPixmap * p)
-{
-    g_return_if_fail(p != NULL);
-    g_return_if_fail(p->pixmap != NULL);
-
-    g_object_unref(p->pixmap);
-    p->pixmap = NULL;
-}
-
-Skin *
-skin_new(void)
-{
-    Skin *skin;
-    skin = g_new0(Skin, 1);
-    skin->lock = g_mutex_new();
-    return skin;
-}
-
-void
-skin_free(Skin * skin)
-{
-    gint i;
-
-    g_return_if_fail(skin != NULL);
-
-    skin_lock(skin);
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
-        skin_pixmap_free(&skin->pixmaps[i]);
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++) {
-        if (skin->masks[i])
-            g_object_unref(skin->masks[i]);
-        if (skin->ds_masks[i])
-            g_object_unref(skin->ds_masks[i]);
-
-        skin->masks[i] = NULL;
-        skin->ds_masks[i] = NULL;
-    }
-
-    skin_set_default_vis_color(skin);
-    skin_unlock(skin);
-}
-
-void
-skin_destroy(Skin * skin)
-{
-    g_return_if_fail(skin != NULL);
-    skin_free(skin);
-    g_mutex_free(skin->lock);
-    g_free(skin);
-}
-
-const SkinPixmapIdMapping *
-skin_pixmap_id_lookup(guint id)
-{
-    guint i;
-
-    for (i = 0; i < skin_pixmap_id_map_size; i++) {
-        if (id == skin_pixmap_id_map[i].id) {
-            return &skin_pixmap_id_map[i];
-        }
-    }
-
-    return NULL;
-}
-
-const gchar *
-skin_pixmap_id_to_name(SkinPixmapId id)
-{
-    guint i;
-
-    for (i = 0; i < skin_pixmap_id_map_size; i++) {
-        if (id == skin_pixmap_id_map[i].id)
-            return skin_pixmap_id_map[i].name;
-    }
-    return NULL;
-}
-
-static void
-skin_set_default_vis_color(Skin * skin)
-{
-    memcpy(skin->vis_color, skin_default_viscolor,
-           sizeof(skin_default_viscolor));
-}
-
-/*
- * I have rewritten this to take an array of possible targets,
- * once we find a matching target we now return, instead of loop
- * recursively. This allows for us to support many possible format
- * targets for our skinning engine than just the original winamp 
- * formats.
- *
- *    -- nenolod, 16 January 2006
- */
-gchar *
-skin_pixmap_locate(const gchar * dirname, gchar ** basenames)
-{
-    gchar *filename;
-    gint i;
-
-    for (i = 0; basenames[i]; i++)
-    if (!(filename = find_path_recursively(dirname, basenames[i]))) 
-        g_free(filename);
-    else
-        return filename;
-
-    /* can't find any targets -- sorry */
-    return NULL;
-}
-
-/* FIXME: this function is temporary. It will be removed when the skinning system
-   uses GdkPixbuf in place of GdkPixmap */
-
-static GdkPixmap *
-pixmap_new_from_file(const gchar * filename)
-{
-    GdkPixbuf *pixbuf, *pixbuf2;
-    GdkPixmap *pixmap;
-    gint width, height;
-
-    if (!(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
-        return NULL;
-
-    width = gdk_pixbuf_get_width(pixbuf);
-    height = gdk_pixbuf_get_height(pixbuf);
-
-    /* create the windows if they haven't been created yet, needed for bootstrapping */
-    if (mainwin == NULL)
-    {
-        mainwin_create();
-        equalizerwin_create();
-        playlistwin_create();
-    }
-
-    if (!(pixmap = gdk_pixmap_new(mainwin->window, width, height,
-                                  gdk_rgb_get_visual()->depth))) {
-        g_object_unref(pixbuf);
-        return NULL;
-    }
-
-    pixbuf2 = audacious_create_colorized_pixbuf(pixbuf, cfg.colorize_r, cfg.colorize_g, cfg.colorize_b);
-    g_object_unref(pixbuf);
-
-    GdkGC *gc;
-    gc = gdk_gc_new(pixmap);
-    gdk_draw_pixbuf(pixmap, gc, pixbuf2, 0, 0, 0, 0, width, height, GDK_RGB_DITHER_MAX, 0, 0);
-    g_object_unref(gc);
-    g_object_unref(pixbuf2);
-
-    return pixmap;
-}
-
-static gboolean
-skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const gchar * path_p)
-{
-    const gchar *path;
-    gchar *filename;
-    gint width, height;
-    const SkinPixmapIdMapping *pixmap_id_mapping;
-    GdkPixmap *gpm;
-    SkinPixmap *pm = NULL;
-    gchar *basenames[EXTENSION_TARGETS * 2 + 1]; /* alternate basenames */
-    gint i, y;
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-    g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE);
-
-    pixmap_id_mapping = skin_pixmap_id_lookup(id);
-    g_return_val_if_fail(pixmap_id_mapping != NULL, FALSE);
-
-    memset(&basenames, 0, sizeof(basenames));
-
-    for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++)
-    {
-        basenames[y] =
-            g_strdup_printf("%s.%s", pixmap_id_mapping->name, ext_targets[i]);
-
-        if (pixmap_id_mapping->alt_name)
-            basenames[++y] =
-                g_strdup_printf("%s.%s", pixmap_id_mapping->alt_name,
-                                ext_targets[i]);
-    }
-
-    path = path_p ? path_p : skin->path;
-    filename = skin_pixmap_locate(path, basenames);
-
-    for (i = 0; basenames[i] != NULL; i++)
-    {
-         g_free(basenames[i]);
-         basenames[i] = NULL;
-    }
-
-    if (!(gpm = pixmap_new_from_file(filename))) {
-        g_warning("loading of %s failed", filename);
-        g_free(filename);
-        return FALSE;
-    }
-
-    g_free(filename);
-
-    gdk_drawable_get_size(GDK_DRAWABLE(gpm), &width, &height);
-    pm = &skin->pixmaps[id];
-    pm->pixmap = gpm;
-    pm->width = width;
-    pm->height = height;
-    pm->current_width = width;
-    pm->current_height = height;
-
-    return TRUE;
-}
-
-void
-skin_mask_create(Skin * skin,
-                 const gchar * path,
-                 gint id,
-                 GdkWindow * window)
-{
-    skin->masks[id] =
-        skin_create_transparent_mask(path, "region.txt",
-                                     skin_mask_info[id].inistr, window,
-                                     skin_mask_info[id].width,
-                                     skin_mask_info[id].height, FALSE);
-
-    skin->ds_masks[id] =
-        skin_create_transparent_mask(path, "region.txt",
-                                     skin_mask_info[id].inistr, window,
-                                     skin_mask_info[id].width * 2,
-                                     skin_mask_info[id].height * 2, TRUE);
-}
-
-static void
-skin_setup_masks(Skin * skin)
-{
-    GdkBitmap *mask;
-
-    if (cfg.show_wm_decorations)
-        return;
-
-    if (cfg.player_visible) {
-        mask = skin_get_mask(skin, SKIN_MASK_MAIN + cfg.player_shaded);
-        gtk_widget_shape_combine_mask(mainwin, mask, 0, 0);
-    }
-
-    mask = skin_get_mask(skin, SKIN_MASK_EQ + cfg.equalizer_shaded);
-    gtk_widget_shape_combine_mask(equalizerwin, mask, 0, 0);
-}
-
-static GdkBitmap *
-create_default_mask(GdkWindow * parent, gint w, gint h)
-{
-    GdkBitmap *ret;
-    GdkGC *gc;
-    GdkColor pattern;
-
-    ret = gdk_pixmap_new(parent, w, h, 1);
-    gc = gdk_gc_new(ret);
-    pattern.pixel = 1;
-    gdk_gc_set_foreground(gc, &pattern);
-    gdk_draw_rectangle(ret, gc, TRUE, 0, 0, w, h);
-    g_object_unref(gc);
-
-    return ret;
-}
-
-static void
-skin_query_color(GdkColormap * cm, GdkColor * c)
-{
-#ifdef GDK_WINDOWING_X11
-    XColor xc = { 0,0,0,0,0,0 };
-
-    xc.pixel = c->pixel;
-    XQueryColor(GDK_COLORMAP_XDISPLAY(cm), GDK_COLORMAP_XCOLORMAP(cm), &xc);
-    c->red = xc.red;
-    c->green = xc.green;
-    c->blue = xc.blue;
-#else
-    /* do nothing. see what breaks? */
-#endif
-}
-
-static glong
-skin_calc_luminance(GdkColor * c)
-{
-    return (0.212671 * c->red + 0.715160 * c->green + 0.072169 * c->blue);
-}
-
-static void
-skin_get_textcolors(GdkPixmap * text, GdkColor * bgc, GdkColor * fgc)
-{
-    /*
-     * Try to extract reasonable background and foreground colors
-     * from the font pixmap
-     */
-
-    GdkImage *gi;
-    GdkColormap *cm;
-    gint i;
-
-    g_return_if_fail(text != NULL);
-    g_return_if_fail(GDK_IS_WINDOW(playlistwin->window));
-
-    /* Get the first line of text */
-    gi = gdk_drawable_get_image(text, 0, 0, 152, 6);
-    cm = gdk_drawable_get_colormap(playlistwin->window);
-
-    for (i = 0; i < 6; i++) {
-        GdkColor c;
-        gint x;
-        glong d, max_d;
-
-        /* Get a pixel from the middle of the space character */
-        bgc[i].pixel = gdk_image_get_pixel(gi, 151, i);
-        skin_query_color(cm, &bgc[i]);
-
-        max_d = 0;
-        for (x = 1; x < 150; x++) {
-            c.pixel = gdk_image_get_pixel(gi, x, i);
-            skin_query_color(cm, &c);
-
-            d = labs(skin_calc_luminance(&c) - skin_calc_luminance(&bgc[i]));
-            if (d > max_d) {
-                memcpy(&fgc[i], &c, sizeof(GdkColor));
-                max_d = d;
-            }
-        }
-    }
-    g_object_unref(gi);
-}
-
-gboolean
-init_skins(const gchar * path)
-{
-    bmp_active_skin = skin_new();
-
-    if (!bmp_active_skin_load(path)) {
-        /* FIXME: Oddly, g_message() causes a crash if path is NULL on
-         * Solaris (see bug #165) */
-        if (path) 
-            g_message("Unable to load skin (%s), trying default...", path);
-
-        /* can't load configured skin, retry with default */
-        if (!bmp_active_skin_load(BMP_DEFAULT_SKIN_PATH)) {
-            g_message("Unable to load default skin (%s)! Giving up.",
-                      BMP_DEFAULT_SKIN_PATH);
-            return FALSE;
-        }
-    }
-
-    if (cfg.random_skin_on_play)
-        skinlist_update();
-
-    return TRUE;
-}
-
-/*
- * Opens and parses a skin's hints file.
- * Hints files are somewhat like "scripts" in Winamp3/5.
- * We'll probably add scripts to it next.
- */
-void
-skin_parse_hints(Skin * skin, gchar *path_p)
-{
-    gchar *filename, *tmp;
-    INIFile *inifile;
-
-    path_p = path_p ? path_p : skin->path;
-
-    skin->properties.mainwin_othertext = FALSE;
-    skin->properties.mainwin_vis_x = 24;
-    skin->properties.mainwin_vis_y = 43;
-    skin->properties.mainwin_vis_width = 76;
-    skin->properties.mainwin_text_x = 112;
-    skin->properties.mainwin_text_y = 27;
-    skin->properties.mainwin_text_width = 153;
-    skin->properties.mainwin_infobar_x = 112;
-    skin->properties.mainwin_infobar_y = 43;
-    skin->properties.mainwin_number_0_x = 36;
-    skin->properties.mainwin_number_0_y = 26;
-    skin->properties.mainwin_number_1_x = 48;
-    skin->properties.mainwin_number_1_y = 26;
-    skin->properties.mainwin_number_2_x = 60;
-    skin->properties.mainwin_number_2_y = 26;
-    skin->properties.mainwin_number_3_x = 78;
-    skin->properties.mainwin_number_3_y = 26;
-    skin->properties.mainwin_number_4_x = 90;
-    skin->properties.mainwin_number_4_y = 26;
-    skin->properties.mainwin_playstatus_x = 24;
-    skin->properties.mainwin_playstatus_y = 28;
-    skin->properties.mainwin_menurow_visible = TRUE;
-    skin->properties.mainwin_volume_x = 107;
-    skin->properties.mainwin_volume_y = 57;
-    skin->properties.mainwin_balance_x = 177;
-    skin->properties.mainwin_balance_y = 57;
-    skin->properties.mainwin_position_x = 16;
-    skin->properties.mainwin_position_y = 72;
-    skin->properties.mainwin_othertext_is_status = FALSE;
-    skin->properties.mainwin_othertext_visible = skin->properties.mainwin_othertext;
-    skin->properties.mainwin_text_visible = TRUE;
-    skin->properties.mainwin_vis_visible = TRUE;
-    skin->properties.mainwin_previous_x = 16;
-    skin->properties.mainwin_previous_y = 88;
-    skin->properties.mainwin_play_x = 39;
-    skin->properties.mainwin_play_y = 88;
-    skin->properties.mainwin_pause_x = 62;
-    skin->properties.mainwin_pause_y = 88;
-    skin->properties.mainwin_stop_x = 85;
-    skin->properties.mainwin_stop_y = 88;
-    skin->properties.mainwin_next_x = 108;
-    skin->properties.mainwin_next_y = 88;
-    skin->properties.mainwin_eject_x = 136;
-    skin->properties.mainwin_eject_y = 89;
-    skin->properties.mainwin_width = 275;
-    skin_mask_info[0].width = skin->properties.mainwin_width;
-    skin->properties.mainwin_height = 116;
-    skin_mask_info[0].height = skin->properties.mainwin_height;
-    skin->properties.mainwin_about_x = 247;
-    skin->properties.mainwin_about_y = 83;
-    skin->properties.mainwin_shuffle_x = 164;
-    skin->properties.mainwin_shuffle_y = 89;
-    skin->properties.mainwin_repeat_x = 210;
-    skin->properties.mainwin_repeat_y = 89;
-    skin->properties.mainwin_eqbutton_x = 219;
-    skin->properties.mainwin_eqbutton_y = 58;
-    skin->properties.mainwin_plbutton_x = 242;
-    skin->properties.mainwin_plbutton_y = 58;
-    skin->properties.textbox_bitmap_font_width = 5;
-    skin->properties.textbox_bitmap_font_height = 6;
-    skin->properties.mainwin_minimize_x = 244;
-    skin->properties.mainwin_minimize_y = 3;
-    skin->properties.mainwin_shade_x = 254;
-    skin->properties.mainwin_shade_y = 3;
-    skin->properties.mainwin_close_x = 264;
-    skin->properties.mainwin_close_y = 3;
-
-    filename = find_file_recursively(path_p, "skin.hints");
-
-    if (filename == NULL)
-        return;
-
-    inifile = open_ini_file(filename);
-
-    tmp = read_ini_string(inifile, "skin", "mainwinOthertext");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_othertext = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinVisX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_vis_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinVisY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_vis_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinVisWidth");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_vis_width = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinTextX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_text_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinTextY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_text_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinTextWidth");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_text_width = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinInfoBarX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_infobar_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinInfoBarY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_infobar_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber0X");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_0_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber0Y");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_0_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber1X");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_1_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber1Y");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_1_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber2X");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_2_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber2Y");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_2_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber3X");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_3_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber3Y");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_3_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber4X");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_4_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNumber4Y");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_number_4_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_playstatus_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_playstatus_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinMenurowVisible");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_menurow_visible = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinVolumeX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_volume_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinVolumeY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_volume_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinBalanceX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_balance_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinBalanceY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_balance_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPositionX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_position_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPositionY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_position_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinOthertextIsStatus");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_othertext_is_status = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinOthertextVisible");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_othertext_visible = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinTextVisible");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_text_visible = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinVisVisible");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_vis_visible = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPreviousX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_previous_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPreviousY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_previous_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPlayX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_play_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPlayY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_play_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPauseX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_pause_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPauseY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_pause_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinStopX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_stop_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinStopY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_stop_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNextX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_next_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinNextY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_next_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinEjectX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_eject_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinEjectY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_eject_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinWidth");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_width = atoi(tmp);
-        g_free(tmp);
-    }
-
-    skin_mask_info[0].width = skin->properties.mainwin_width;
-
-    tmp = read_ini_string(inifile, "skin", "mainwinHeight");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_height = atoi(tmp);
-        g_free(tmp);
-    }
-
-    skin_mask_info[0].height = skin->properties.mainwin_height;
-
-    tmp = read_ini_string(inifile, "skin", "mainwinAboutX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_about_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinAboutY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_about_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinShuffleX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_shuffle_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinShuffleY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_shuffle_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinRepeatX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_repeat_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinRepeatY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_repeat_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinEQButtonX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_eqbutton_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinEQButtonY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_eqbutton_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPLButtonX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_plbutton_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinPLButtonY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_plbutton_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "textboxBitmapFontWidth");
-
-    if (tmp != NULL)
-    {
-        skin->properties.textbox_bitmap_font_width = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "textboxBitmapFontHeight");
-
-    if (tmp != NULL)
-    {
-        skin->properties.textbox_bitmap_font_height = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinMinimizeX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_minimize_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinMinimizeY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_minimize_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinShadeX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_shade_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinShadeY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_shade_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinCloseX");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_close_x = atoi(tmp);
-        g_free(tmp);
-    }
-
-    tmp = read_ini_string(inifile, "skin", "mainwinCloseY");
-
-    if (tmp != NULL)
-    {
-        skin->properties.mainwin_close_y = atoi(tmp);
-        g_free(tmp);
-    }
-
-    if (filename != NULL)
-        g_free(filename);
-
-    close_ini_file(inifile);
-}
-
-static guint
-hex_chars_to_int(gchar hi, gchar lo)
-{
-    /*
-     * Converts a value in the range 0x00-0xFF
-     * to a integer in the range 0-65535
-     */
-    gchar str[3];
-
-    str[0] = hi;
-    str[1] = lo;
-    str[2] = 0;
-
-    return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8);
-}
-
-static GdkColor *
-skin_load_color(INIFile *inifile,
-                const gchar * section, const gchar * key,
-                gchar * default_hex)
-{
-    gchar *value;
-    GdkColor *color = NULL;
-
-    if (inifile || default_hex) {
-        if (inifile) {
-            value = g_strdup(read_ini_string(inifile, section, key));
-            if (value == NULL) {
-                value = g_strdup(default_hex);
-            }
-        } else {
-            value = g_strdup(default_hex);
-        }
-        if (value) {
-            gchar *ptr = value;
-            gint len;
-
-            color = g_new0(GdkColor, 1);
-            g_strstrip(value);
-
-            if (value[0] == '#')
-                ptr++;
-            len = strlen(ptr);
-            /*
-             * The handling of incomplete values is done this way
-             * to maximize winamp compatibility
-             */
-            if (len >= 6) {
-                color->red = hex_chars_to_int(*ptr, *(ptr + 1));
-                ptr += 2;
-            }
-            if (len >= 4) {
-                color->green = hex_chars_to_int(*ptr, *(ptr + 1));
-                ptr += 2;
-            }
-            if (len >= 2)
-                color->blue = hex_chars_to_int(*ptr, *(ptr + 1));
-
-            gdk_colormap_alloc_color(gdk_drawable_get_colormap(playlistwin->window),
-                            color, TRUE, TRUE);
-            g_free(value);
-        }
-    }
-    return color;
-}
-
-
-
-GdkBitmap *
-skin_create_transparent_mask(const gchar * path,
-                             const gchar * file,
-                             const gchar * section,
-                             GdkWindow * window,
-                             gint width,
-                             gint height, gboolean doublesize)
-{
-    GdkBitmap *mask = NULL;
-    GdkGC *gc = NULL;
-    GdkColor pattern;
-    GdkPoint *gpoints;
-
-    gchar *filename = NULL;
-    INIFile *inifile = NULL;
-    gboolean created_mask = FALSE;
-    GArray *num, *point;
-    guint i, j;
-    gint k;
-
-    if (path)
-        filename = find_file_recursively(path, file);
-
-    /* filename will be null if path wasn't set */
-    if (!filename)
-        return create_default_mask(window, width, height);
-
-    inifile = open_ini_file(filename);
-
-    if ((num = read_ini_array(inifile, section, "NumPoints")) == NULL) {
-        g_free(filename);
-        close_ini_file(inifile);
-        return NULL;
-    }
-
-    if ((point = read_ini_array(inifile, section, "PointList")) == NULL) {
-        g_array_free(num, TRUE);
-        g_free(filename);
-        close_ini_file(inifile);
-        return NULL;
-    }
-
-    close_ini_file(inifile);
-
-    mask = gdk_pixmap_new(window, width, height, 1);
-    gc = gdk_gc_new(mask);
-
-    pattern.pixel = 0;
-    gdk_gc_set_foreground(gc, &pattern);
-    gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
-    pattern.pixel = 1;
-    gdk_gc_set_foreground(gc, &pattern);
-
-    j = 0;
-    for (i = 0; i < num->len; i++) {
-        if ((int)(point->len - j) >= (g_array_index(num, gint, i) * 2)) {
-            created_mask = TRUE;
-            gpoints = g_new(GdkPoint, g_array_index(num, gint, i));
-            for (k = 0; k < g_array_index(num, gint, i); k++) {
-                gpoints[k].x =
-                    g_array_index(point, gint, j + k * 2) * (1 + doublesize);
-                gpoints[k].y =
-                    g_array_index(point, gint,
-                                  j + k * 2 + 1) * (1 + doublesize);
-            }
-            j += k * 2;
-            gdk_draw_polygon(mask, gc, TRUE, gpoints,
-                             g_array_index(num, gint, i));
-            g_free(gpoints);
-        }
-    }
-    g_array_free(num, TRUE);
-    g_array_free(point, TRUE);
-    g_free(filename);
-
-    if (!created_mask)
-        gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
-
-    g_object_unref(gc);
-
-    return mask;
-}
-
-void
-skin_load_viscolor(Skin * skin, const gchar * path, const gchar * basename)
-{
-    VFSFile *file;
-    gint i, c;
-    gchar line[256], *filename;
-    GArray *a;
-
-    g_return_if_fail(skin != NULL);
-    g_return_if_fail(path != NULL);
-    g_return_if_fail(basename != NULL);
-
-    skin_set_default_vis_color(skin);
-
-    filename = find_file_recursively(path, basename);
-    if (!filename)
-        return;
-
-    if (!(file = vfs_fopen(filename, "r"))) {
-        g_free(filename);
-        return;
-    }
-
-    g_free(filename);
-
-    for (i = 0; i < 24; i++) {
-        if (vfs_fgets(line, 255, file)) {
-            a = string_to_garray(line);
-            if (a->len > 2) {
-                for (c = 0; c < 3; c++)
-                    skin->vis_color[i][c] = g_array_index(a, gint, c);
-            }
-            g_array_free(a, TRUE);
-        }
-        else
-            break;
-    }
-
-    vfs_fclose(file);
-}
-
-#if 0
-static void
-skin_numbers_generate_dash(Skin * skin)
-{
-    GdkGC *gc;
-    GdkPixmap *pixmap;
-    SkinPixmap *numbers;
-
-    g_return_if_fail(skin != NULL);
-
-    numbers = &skin->pixmaps[SKIN_NUMBERS];
-    if (!numbers->pixmap || numbers->current_width < 99)
-        return;
-
-    gc = gdk_gc_new(numbers->pixmap);
-    pixmap = gdk_pixmap_new(mainwin->window, 108,
-                            numbers->current_height,
-                            -1);
-
-    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 0, 0, 0, 0, 99, 13);
-    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 90, 0, 99, 0, 9, 13);
-    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 20, 6, 101, 6, 5, 1);
-
-    g_object_unref(numbers->pixmap);
-    g_object_unref(gc);
-
-    numbers->pixmap = pixmap;
-    numbers->current_width = 108;
-}
-#endif
-
-static void
-skin_load_cursor(Skin * skin, const gchar * dirname)
-{
-    const gchar * basename = "normal.cur";
-    gchar * filename = NULL;
-    GdkPixbuf * cursor_pixbuf = NULL;
-    GdkPixbufAnimation * cursor_animated = NULL;
-    GdkCursor * cursor_gdk = NULL;
-    GError * error = NULL;
- 
-    filename = find_file_recursively(dirname, basename);
-
-    if (filename && cfg.custom_cursors)
-        cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
-
-    if (cursor_animated) {
-        cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated);
-        cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
-                                                cursor_pixbuf, 0, 0);
-    }
-    else
-        cursor_gdk = gdk_cursor_new(GDK_LEFT_PTR);
-
-    gdk_window_set_cursor(mainwin->window, cursor_gdk);
-    gdk_window_set_cursor(playlistwin->window, cursor_gdk);
-    gdk_window_set_cursor(equalizerwin->window, cursor_gdk);
-    gdk_cursor_unref(cursor_gdk);
-}
-
-static void
-skin_load_pixmaps(Skin * skin, const gchar * path)
-{
-    GdkPixmap *text_pm;
-    guint i;
-    gchar *filename;
-    INIFile *inifile;
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
-        skin_load_pixmap_id(skin, i, path);
-
-    text_pm = skin->pixmaps[SKIN_TEXT].pixmap;
-
-    if (text_pm)
-        skin_get_textcolors(text_pm, skin->textbg, skin->textfg);
-
-#if 0
-    if (skin->pixmaps[SKIN_NUMBERS].pixmap)
-        skin_numbers_generate_dash(skin);
-#endif
-
-    filename = find_file_recursively(path, "pledit.txt");
-    inifile = open_ini_file(filename);
-
-    skin->colors[SKIN_PLEDIT_NORMAL] =
-        skin_load_color(inifile, "Text", "Normal", "#2499ff");
-    skin->colors[SKIN_PLEDIT_CURRENT] =
-        skin_load_color(inifile, "Text", "Current", "#ffeeff");
-    skin->colors[SKIN_PLEDIT_NORMALBG] =
-        skin_load_color(inifile, "Text", "NormalBG", "#0a120a");
-    skin->colors[SKIN_PLEDIT_SELECTEDBG] =
-        skin_load_color(inifile, "Text", "SelectedBG", "#0a124a");
-
-    if (filename)
-        g_free(filename);
-    close_ini_file(inifile);
-
-    skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window);
-    skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window);
-
-    skin_mask_create(skin, path, SKIN_MASK_EQ, equalizerwin->window);
-    skin_mask_create(skin, path, SKIN_MASK_EQ_SHADE, equalizerwin->window);
-
-    skin_load_viscolor(skin, path, "viscolor.txt");
-}
-
-static gboolean
-skin_load_nolock(Skin * skin, const gchar * path, gboolean force)
-{
-    gchar *cpath;
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-    g_return_val_if_fail(path != NULL, FALSE);
-    REQUIRE_LOCK(skin->lock);
-
-    if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR))
-        return FALSE;
-   
-    if (!force) {
-        if (skin->path)
-            if (!strcmp(skin->path, path))
-                return FALSE;
-    }
-      
-    skin_current_num++;
-
-    skin->path = g_strdup(path);
-
-    if (!file_is_archive(path)) {
-        /* Parse the hints for this skin. */
-        skin_parse_hints(skin, NULL);
-
-        skin_load_pixmaps(skin, path);
-        skin_load_cursor(skin, path);
-
-        return TRUE;
-    }
-
-    if (!(cpath = archive_decompress(path))) {
-        g_message("Unable to extract skin archive (%s)", path);
-        return FALSE;
-    }
-
-    /* Parse the hints for this skin. */
-    skin_parse_hints(skin, cpath);
-
-    skin_load_pixmaps(skin, cpath);
-    skin_load_cursor(skin, cpath);
-
-    del_directory(cpath);
-    g_free(cpath);
-
-    return TRUE;
-}
-
-void
-skin_install_skin(const gchar * path)
-{
-    gchar *command;
-
-    g_return_if_fail(path != NULL);
-
-    command = g_strdup_printf("cp %s %s",
-                              path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
-    if (system(command)) {
-        g_message("Unable to install skin (%s) into user directory (%s)",
-                  path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
-    }
-    g_free(command);
-}
-
-
-gboolean
-skin_load(Skin * skin, const gchar * path)
-{
-    gboolean error;
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-
-    if (!path)
-        return FALSE;
-
-    skin_lock(skin);
-    error = skin_load_nolock(skin, path, FALSE);
-    skin_unlock(skin);
-    
-    return error;
-}
-
-gboolean
-skin_reload_forced(void) 
-{
-   gboolean error;
-
-   skin_lock(bmp_active_skin);
-   error = skin_load_nolock(bmp_active_skin, bmp_active_skin->path, TRUE);
-   skin_unlock(bmp_active_skin);
-
-   return error;
-}
-
-void
-skin_reload(Skin * skin)
-{
-    g_return_if_fail(skin != NULL);
-    skin_load_nolock(skin, skin->path, TRUE);
-}
-
-
-static SkinPixmap *
-skin_get_pixmap(Skin * skin, SkinPixmapId map_id)
-{
-    g_return_val_if_fail(skin != NULL, NULL);
-    g_return_val_if_fail(map_id < SKIN_PIXMAP_COUNT, NULL);
-
-    return &skin->pixmaps[map_id];
-}
-
-GdkBitmap *
-skin_get_mask(Skin * skin, SkinMaskId mi)
-{
-    GdkBitmap **masks;
-
-    g_return_val_if_fail(skin != NULL, NULL);
-    g_return_val_if_fail(mi < SKIN_PIXMAP_COUNT, NULL);
-
-    masks = cfg.doublesize ? skin->ds_masks : skin->masks;
-    return masks[mi];
-}
-
-GdkColor *
-skin_get_color(Skin * skin, SkinColorId color_id)
-{
-    GdkColor *ret = NULL;
-
-    g_return_val_if_fail(skin != NULL, NULL);
-
-    switch (color_id) {
-    case SKIN_TEXTBG:
-        if (skin->pixmaps[SKIN_TEXT].pixmap)
-            ret = skin->textbg;
-        else
-            ret = skin->def_textbg;
-        break;
-    case SKIN_TEXTFG:
-        if (skin->pixmaps[SKIN_TEXT].pixmap)
-            ret = skin->textfg;
-        else
-            ret = skin->def_textfg;
-        break;
-    default:
-        if (color_id < SKIN_COLOR_COUNT)
-            ret = skin->colors[color_id];
-        break;
-    }
-    return ret;
-}
-
-void
-skin_get_viscolor(Skin * skin, guchar vis_color[24][3])
-{
-    gint i;
-
-    g_return_if_fail(skin != NULL);
-
-    for (i = 0; i < 24; i++) {
-        vis_color[i][0] = skin->vis_color[i][0];
-        vis_color[i][1] = skin->vis_color[i][1];
-        vis_color[i][2] = skin->vis_color[i][2];
-    }
-}
-
-gint
-skin_get_id(void)
-{
-    return skin_current_num;
-}
-
-void
-skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
-                 SkinPixmapId pixmap_id,
-                 gint xsrc, gint ysrc, gint xdest, gint ydest,
-                 gint width, gint height)
-{
-    SkinPixmap *pixmap;
-
-    g_return_if_fail(skin != NULL);
-
-    pixmap = skin_get_pixmap(skin, pixmap_id);
-    g_return_if_fail(pixmap != NULL);
-    g_return_if_fail(pixmap->pixmap != NULL);
-
-    if (xsrc+width > pixmap->width || ysrc+height > pixmap->height) {
-        if (pixmap_id == SKIN_NUMBERS)
-            xsrc = 90;
-        else if (pixmap_id == SKIN_VOLUME) {
-            /* some winamp skins have too strait SKIN_VOLUME, so let's copy what's remain from SKIN_MAIN */
-            gdk_draw_drawable(drawable, gc, skin_get_pixmap(bmp_active_skin, SKIN_MAIN)->pixmap,
-                              skin->properties.mainwin_volume_x, skin->properties.mainwin_volume_y,
-                              pixmap->width, ydest, width - pixmap->width, height);
-            width = pixmap->width;
-        } else if (pixmap_id == SKIN_MONOSTEREO) {
-            /* XMMS skins seems to have SKIN_MONOSTEREO with size 58x20 instead of 58x24 */
-            gdk_draw_drawable(drawable, gc, skin_get_pixmap(bmp_active_skin, SKIN_MAIN)->pixmap,
-                              212 + xdest, 41, xdest, ydest, width, height);
-            height = pixmap->height/2;
-        } else
-            return;
-    }
-
-    width = MIN(width, pixmap->width - xsrc);
-    height = MIN(height, pixmap->height - ysrc);
-    gdk_draw_drawable(drawable, gc, pixmap->pixmap, xsrc, ysrc,
-                      xdest, ydest, width, height);
-}
-
-void
-skin_get_eq_spline_colors(Skin * skin, guint32 colors[19])
-{
-    gint i;
-    GdkPixmap *pixmap;
-    GdkImage *img;
-    SkinPixmap *eqmainpm;
-
-    g_return_if_fail(skin != NULL);
-
-    eqmainpm = &skin->pixmaps[SKIN_EQMAIN];
-    if (eqmainpm->pixmap &&
-        eqmainpm->current_width >= 116 && eqmainpm->current_height >= 313)
-        pixmap = eqmainpm->pixmap;
-    else
-        return;
-
-    if (!GDK_IS_DRAWABLE(pixmap))
-        return;
-
-    if (!(img = gdk_drawable_get_image(pixmap, 115, 294, 1, 19)))
-        return;
-
-    for (i = 0; i < 19; i++)
-        colors[i] = gdk_image_get_pixel(img, 0, i);
-
-    g_object_unref(img);
-}
-
-
-static void
-skin_draw_playlistwin_frame_top(Skin * skin,
-                                GdkDrawable * drawable,
-                                GdkGC * gc,
-                                gint width, gint height, gboolean focus)
-{
-    /* The title bar skin consists of 2 sets of 4 images, 1 set
-     * for focused state and the other for unfocused. The 4 images
-     * are: 
-     *
-     * a. right corner (25,20)
-     * b. left corner  (25,20)
-     * c. tiler        (25,20)
-     * d. title        (100,20)
-     * 
-     * min allowed width = 100+25+25 = 150
-     */
-
-    gint i, y, c;
-
-    /* get y offset of the pixmap set to use */
-    if (focus)
-        y = 0;
-    else
-        y = 21;
-
-    /* left corner */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, y, 0, 0, 25, 20);
-
-    /* titlebar title */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 26, y,
-                     (width - 100) / 2, 0, 100, 20);
-
-    /* titlebar right corner  */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 153, y,
-                     width - 25, 0, 25, 20);
-
-    /* tile draw the remaining frame */
-
-    /* compute tile count */
-    c = (width - (100 + 25 + 25)) / 25;
-
-    for (i = 0; i < c / 2; i++) {
-        /* left of title */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         25 + i * 25, 0, 25, 20);
-
-        /* right of title */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         (width + 100) / 2 + i * 25, 0, 25, 20);
-    }
-
-    if (c & 1) {
-        /* Odd tile count, so one remaining to draw. Here we split
-         * it into two and draw half on either side of the title */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         ((c / 2) * 25) + 25, 0, 12, 20);
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20);
-    }
-}
-
-static void
-skin_draw_playlistwin_frame_bottom(Skin * skin,
-                                   GdkDrawable * drawable,
-                                   GdkGC * gc,
-                                   gint width, gint height, gboolean focus)
-{
-    /* The bottom frame skin consists of 1 set of 4 images. The 4
-     * images are:
-     *
-     * a. left corner with menu buttons (125,38)
-     * b. visualization window (75,38)
-     * c. right corner with play buttons (150,38)
-     * d. frame tile (25,38)
-     * 
-     * (min allowed width = 125+150+25=300
-     */
-
-    gint i, c;
-
-    /* bottom left corner (menu buttons) */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 72,
-                     0, height - 38, 125, 38);
-
-    c = (width - 275) / 25;
-
-    /* draw visualization window, if width allows */
-    if (c >= 3) {
-        c -= 3;
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 205, 0,
-                         width - (150 + 75), height - 38, 75, 38);
-    }
-
-    /* Bottom right corner (playbuttons etc) */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT,
-                     126, 72, width - 150, height - 38, 150, 38);
-
-    /* Tile draw the remaining undrawn portions */
-    for (i = 0; i < c; i++)
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 179, 0,
-                         125 + i * 25, height - 38, 25, 38);
-}
-
-static void
-skin_draw_playlistwin_frame_sides(Skin * skin,
-                                  GdkDrawable * drawable,
-                                  GdkGC * gc,
-                                  gint width, gint height, gboolean focus)
-{
-    /* The side frames consist of 2 tile images. 1 for the left, 1 for
-     * the right. 
-     * a. left  (12,29)
-     * b. right (19,29)
-     */
-
-    gint i;
-
-    /* frame sides */
-    for (i = 0; i < (height - (20 + 38)) / 29; i++) {
-        /* left */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 42,
-                         0, 20 + i * 29, 12, 29);
-
-        /* right */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 32, 42,
-                         width - 19, 20 + i * 29, 19, 29);
-    }
-}
-
-
-void
-skin_draw_playlistwin_frame(Skin * skin,
-                            GdkDrawable * drawable, GdkGC * gc,
-                            gint width, gint height, gboolean focus)
-{
-    skin_draw_playlistwin_frame_top(skin, drawable, gc, width, height, focus);
-    skin_draw_playlistwin_frame_bottom(skin, drawable, gc, width, height,
-                                       focus);
-    skin_draw_playlistwin_frame_sides(skin, drawable, gc, width, height,
-                                      focus);
-}
-
-
-void
-skin_draw_playlistwin_shaded(Skin * skin,
-                             GdkDrawable * drawable, GdkGC * gc,
-                             gint width, gboolean focus)
-{
-    /* The shade mode titlebar skin consists of 4 images:
-     * a) left corner               offset (72,42) size (25,14)
-     * b) right corner, focused     offset (99,57) size (50,14)
-     * c) right corner, unfocused   offset (99,42) size (50,14)
-     * d) bar tile                  offset (72,57) size (25,14)
-     */
-
-    gint i;
-
-    /* left corner */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14);
-
-    /* bar tile */
-    for (i = 0; i < (width - 75) / 25; i++)
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 57,
-                         (i * 25) + 25, 0, 25, 14);
-
-    /* right corner */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 99, focus ? 42 : 57,
-                     width - 50, 0, 50, 14);
-}
-
-
-void
-skin_draw_mainwin_titlebar(Skin * skin,
-                           GdkDrawable * drawable, GdkGC * gc,
-                           gboolean shaded, gboolean focus)
-{
-    /* The titlebar skin consists of 2 sets of 2 images, one for for
-     * shaded and the other for unshaded mode, giving a total of 4.
-     * The images are exactly 275x14 pixels, aligned and arranged
-     * vertically on each other in the pixmap in the following order:
-     * 
-     * a) unshaded, focused      offset (27, 0)
-     * b) unshaded, unfocused    offset (27, 15)
-     * c) shaded, focused        offset (27, 29)
-     * d) shaded, unfocused      offset (27, 42)
-     */
-
-    gint y_offset;
-
-    if (shaded) {
-        if (focus)
-            y_offset = 29;
-        else
-            y_offset = 42;
-    }
-    else {
-        if (focus)
-            y_offset = 0;
-        else
-            y_offset = 15;
-    }
-
-    skin_draw_pixmap(skin, drawable, gc, SKIN_TITLEBAR, 27, y_offset,
-                     0, 0, bmp_active_skin->properties.mainwin_width, MAINWIN_TITLEBAR_HEIGHT);
-}
-
-
-void
-skin_set_random_skin(void)
-{
-    SkinNode *node;
-    guint32 randval;
-
-    /* Get a random value to select the skin to use */
-    randval = g_random_int_range(0, g_list_length(skinlist));
-    node = g_list_nth(skinlist, randval)->data;
-    bmp_active_skin_load(node->path);
-}
--- a/src/audacious/widgets/skin.h	Sat Aug 04 01:15:07 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-/*  Audacious
- *  Copyright (C) 2005-2007  Audacious development team.
- *
- *  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; under version 3 of the License.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses>.
- *
- *  The Audacious team does not consider modular code linking to
- *  Audacious or using our public API to be a derived work.
- */
-
-#ifndef _WIDGETCORE_H_
-#error Please do not include me directly! Use widgetcore.h instead!
-#endif
-
-#ifndef SKIN_H
-#define SKIN_H
-
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-
-#define BMP_DEFAULT_SKIN_PATH \
-  DATA_DIR G_DIR_SEPARATOR_S "Skins" G_DIR_SEPARATOR_S "Default"
-
-
-typedef enum {
-    SKIN_MAIN = 0,
-    SKIN_CBUTTONS,
-    SKIN_TITLEBAR,
-    SKIN_SHUFREP,
-    SKIN_TEXT,
-    SKIN_VOLUME,
-    SKIN_BALANCE,
-    SKIN_MONOSTEREO,
-    SKIN_PLAYPAUSE,
-    SKIN_NUMBERS,
-    SKIN_POSBAR,
-    SKIN_PLEDIT,
-    SKIN_EQMAIN,
-    SKIN_EQ_EX,
-    SKIN_PIXMAP_COUNT
-} SkinPixmapId;
-
-typedef enum {
-    SKIN_MASK_MAIN = 0,
-    SKIN_MASK_MAIN_SHADE,
-    SKIN_MASK_EQ,
-    SKIN_MASK_EQ_SHADE,
-    SKIN_MASK_COUNT
-} SkinMaskId;
-
-typedef enum {
-    SKIN_PLEDIT_NORMAL = 0,
-    SKIN_PLEDIT_CURRENT,
-    SKIN_PLEDIT_NORMALBG,
-    SKIN_PLEDIT_SELECTEDBG,
-    SKIN_TEXTBG,
-    SKIN_TEXTFG,
-    SKIN_COLOR_COUNT
-} SkinColorId;
-
-typedef struct _SkinProperties {
-	/* this enables the othertext engine, not it's visibility -nenolod */
-	gboolean mainwin_othertext;
-
-	/* Vis properties */
-	gint mainwin_vis_x;
-	gint mainwin_vis_y;
-	gint mainwin_vis_width;
-	gboolean mainwin_vis_visible;
-
-	/* Text properties */
-	gint mainwin_text_x;
-	gint mainwin_text_y;
-	gint mainwin_text_width;
-	gboolean mainwin_text_visible;
-
-	/* Infobar properties */
-	gint mainwin_infobar_x;
-	gint mainwin_infobar_y;
-	gboolean mainwin_othertext_visible;
-
-	gint mainwin_number_0_x;
-	gint mainwin_number_0_y;
-
-	gint mainwin_number_1_x;
-	gint mainwin_number_1_y;
-
-	gint mainwin_number_2_x;
-	gint mainwin_number_2_y;
-
-	gint mainwin_number_3_x;
-	gint mainwin_number_3_y;
-
-	gint mainwin_number_4_x;
-	gint mainwin_number_4_y;
-
-	gint mainwin_playstatus_x;
-	gint mainwin_playstatus_y;
-
-	gint mainwin_volume_x;
-	gint mainwin_volume_y;	
-
-	gint mainwin_balance_x;
-	gint mainwin_balance_y;	
-
-	gint mainwin_position_x;
-	gint mainwin_position_y;
-
-	gint mainwin_previous_x;
-	gint mainwin_previous_y;
-
-	gint mainwin_play_x;
-	gint mainwin_play_y;
-
-	gint mainwin_pause_x;
-	gint mainwin_pause_y;
-
-	gint mainwin_stop_x;
-	gint mainwin_stop_y;
-
-	gint mainwin_next_x;
-	gint mainwin_next_y;
-
-	gint mainwin_eject_x;
-	gint mainwin_eject_y;
-
-	gint mainwin_eqbutton_x;
-	gint mainwin_eqbutton_y;
-
-	gint mainwin_plbutton_x;
-	gint mainwin_plbutton_y;
-
-	gint mainwin_shuffle_x;
-	gint mainwin_shuffle_y;
-
-	gint mainwin_repeat_x;
-	gint mainwin_repeat_y;
-
-	gint mainwin_about_x;
-	gint mainwin_about_y;
-
-	gint mainwin_minimize_x;
-	gint mainwin_minimize_y;
-
-	gint mainwin_shade_x;
-	gint mainwin_shade_y;
-
-	gint mainwin_close_x;
-	gint mainwin_close_y;
-
-	gint mainwin_width;
-	gint mainwin_height;
-
-	gboolean mainwin_menurow_visible;
-	gboolean mainwin_othertext_is_status;
-
-	gint textbox_bitmap_font_width;
-	gint textbox_bitmap_font_height;
-} SkinProperties;
-
-#define SKIN_PIXMAP(x)  ((SkinPixmap *)(x))
-typedef struct _SkinPixmap {
-    GdkPixmap *pixmap;
-    /* GdkPixmap *def_pixmap; */
-
-    /* The real size of the pixmap */
-    gint width, height;
-
-    /* The size of the pixmap from the current skin,
-       which might be smaller */
-    gint current_width, current_height;
-} SkinPixmap;
-
-
-#define SKIN(x)  ((Skin *)(x))
-typedef struct _Skin {
-    GMutex *lock;
-    gchar *path;
-    gchar *def_path;
-    SkinPixmap pixmaps[SKIN_PIXMAP_COUNT];
-    GdkColor textbg[6], def_textbg[6];
-    GdkColor textfg[6], def_textfg[6];
-    GdkColor *colors[SKIN_COLOR_COUNT];
-    guchar vis_color[24][3];
-    GdkBitmap *masks[SKIN_MASK_COUNT];
-    GdkBitmap *ds_masks[SKIN_MASK_COUNT];
-    SkinProperties properties;
-} Skin;
-
-extern Skin *bmp_active_skin;
-
-gboolean init_skins(const gchar * path);
-void cleanup_skins(void);
-
-gboolean bmp_active_skin_load(const gchar * path);
-gboolean bmp_active_skin_reload(void);
-
-Skin *skin_new(void);
-gboolean skin_load(Skin * skin, const gchar * path);
-gboolean skin_reload_forced(void);
-void skin_reload(Skin * skin);
-void skin_free(Skin * skin);
-
-GdkBitmap *skin_get_mask(Skin * skin, SkinMaskId mi);
-GdkColor *skin_get_color(Skin * skin, SkinColorId color_id);
-
-void skin_get_viscolor(Skin * skin, guchar vis_color[24][3]);
-gint skin_get_id(void);
-void skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
-                      SkinPixmapId pixmap_id,
-                      gint xsrc, gint ysrc, gint xdest, gint ydest,
-                      gint width, gint height);
-void skin_get_eq_spline_colors(Skin * skin, guint32 colors[19]);
-void skin_install_skin(const gchar * path);
-
-void skin_draw_playlistwin_shaded(Skin * skin,
-                                  GdkDrawable * drawable, GdkGC * gc,
-                                  gint width, gboolean focus);
-void skin_draw_playlistwin_frame(Skin * skin,
-                                 GdkDrawable * drawable, GdkGC * gc,
-                                 gint width, gint height, gboolean focus);
-
-void skin_draw_mainwin_titlebar(Skin * skin,
-                                GdkDrawable * drawable, GdkGC * gc,
-                                gboolean shaded, gboolean focus);
-
-
-void skin_parse_hints(Skin * skin, gchar *path_p);
-
-
-void skin_set_random_skin(void);
-
-#endif
--- a/src/audacious/widgets/widgetcore.h	Sat Aug 04 01:15:07 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Audacious - a cross-platform multimedia player
- * Copyright (c) 2007  Audacious development team.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#ifndef _WIDGETCORE_H_
-#define _WIDGETCORE_H_
-
-#include "skin.h"
-
-#endif