changeset 2255:448d9e2aa126

merge
author Cristi Magherusan <majeru@atheme-project.org>
date Wed, 19 Dec 2007 17:51:50 +0200
parents 27fe97a846a4 (diff) b461d608befe (current diff)
children dc92a550179e b55720f38a3c
files
diffstat 61 files changed, 2629 insertions(+), 2875 deletions(-) [+]
line wrap: on
line diff
--- a/src/adplug/adplug-xmms.cc	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/adplug/adplug-xmms.cc	Wed Dec 19 17:51:50 2007 +0200
@@ -139,6 +139,7 @@
   return GTK_WIDGET (label);
 }
 
+#if 0
 static void
 MessageBox (const char *title, const char *text, const char *button)
 {
@@ -158,6 +159,7 @@
   free (tmptxt);
   free (tmpbutton);
 }
+#endif
 
 /***** Dialog boxes *****/
 
--- a/src/adplug/core/dmo.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/adplug/core/dmo.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -349,8 +349,10 @@
       if (opos + cx >= oend)
         return -1;
 
-      for (int i = 0; i < cx; i++)
-        *opos++ = *(opos - ax);
+      for (int i = 0; i < cx; i++) {
+        *opos = *(opos - ax);
+        opos++;
+      }
 
       continue;
     }
@@ -370,8 +372,10 @@
       if (opos + bx + cx >= oend)
         return -1;
 
-      for (i = 0; i < cx; i++)
-        *opos++ = *(opos - ax);
+      for (i = 0; i < cx; i++) {
+        *opos = *(opos - ax);
+        opos++;
+      }
 
       for (i = 0; i < bx; i++)
         *opos++ = *ipos++;
@@ -395,8 +399,10 @@
       if (opos + ax + cx >= oend)
         return -1;
 
-      for (i = 0; i < cx; i++)
-        *opos++ = *(opos - bx);
+      for (i = 0; i < cx; i++) {
+        *opos = *(opos - bx);
+        opos++;
+      }
 
       for (i = 0; i < ax; i++)
         *opos++ = *ipos++;
--- a/src/adplug/core/jbm.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/adplug/core/jbm.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -75,7 +75,7 @@
   // Allocate memory buffer m[] and read entire file into it
 
   m = new unsigned char[filelen];
-  if (f->readString((char *)m, filelen) != filelen) goto loaderr;
+  if (f->readString((char *)m, filelen) != (unsigned int)filelen) goto loaderr;
 
   fp.close(f);
 
--- a/src/alsa/alsa.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/alsa/alsa.h	Wed Dec 19 17:51:50 2007 +0200
@@ -21,6 +21,8 @@
 #ifndef ALSA_H
 #define ALSA_H
 
+#define NDEBUG
+
 #include "config.h"
 
 #include <audacious/util.h>
--- a/src/alsa/audio.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/alsa/audio.c	Wed Dec 19 17:51:50 2007 +0200
@@ -294,6 +294,7 @@
 }
 
 /* reopen ALSA PCM */
+#if 0
 static int alsa_reopen(struct snd_format *f)
 {
 	/* remember the current position */
@@ -304,6 +305,7 @@
 
 	return alsa_setup(f);
 }
+#endif
 
 /* do flush (drop) operation */
 static void alsa_do_flush(int time)
--- a/src/aosd/aosd_osd.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/aosd/aosd_osd.c	Wed Dec 19 17:51:50 2007 +0200
@@ -179,6 +179,7 @@
 aosd_osd_create ( void )
 {
   gint max_width, layout_width, layout_height;
+  PangoRectangle ink, log;
   GdkScreen *screen = gdk_screen_get_default();
   gint pos_x = 0, pos_y = 0;
   gint pad_left = 0 , pad_right = 0 , pad_top = 0 , pad_bottom = 0;
@@ -228,7 +229,9 @@
   pango_layout_set_ellipsize( osd_data->pango_layout , PANGO_ELLIPSIZE_NONE );
   pango_layout_set_justify( osd_data->pango_layout , FALSE );
   pango_layout_set_width( osd_data->pango_layout , PANGO_SCALE * max_width );
-  pango_layout_get_pixel_size( osd_data->pango_layout , &layout_width , &layout_height );
+  pango_layout_get_pixel_extents( osd_data->pango_layout , &ink , &log );
+  layout_width = ink.width;
+  layout_height = log.height;
 
   /* osd position */
   switch ( osd_data->cfg_osd->position.placement )
--- a/src/aosd/aosd_style.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/aosd/aosd_style.c	Wed Dec 19 17:51:50 2007 +0200
@@ -161,6 +161,22 @@
 }
 
 
+// sizing helper
+static void
+aosd_layout_size( PangoLayout * layout , gint * width , gint * height , gint * bearing )
+{
+  PangoRectangle ink, log;
+
+  pango_layout_get_pixel_extents( layout , &ink , &log );
+
+  if ( width != NULL )
+    *width = ink.width;
+  if ( height != NULL )
+    *height = log.height;
+  if ( bearing != NULL )
+    *bearing = -ink.x;
+}
+
 
 /* RENDER FUNCTIONS */
 
@@ -178,9 +194,9 @@
   aosd_color_t textcolor0 = data->text->fonts_color[0];
   aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
   gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0;
+  gint width = 0, height = 0, bearing = 0;
 
-  pango_layout_get_pixel_size( osd_layout , &width , &height );
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
 
   /* draw rectangle container */
   cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
@@ -201,7 +217,7 @@
     cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
       (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
     cairo_move_to( cr,
-      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + bearing + 2 ,
       aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + 2 );
     pango_cairo_show_layout( cr , osd_layout );
   }
@@ -210,7 +226,7 @@
   cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
     (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
   cairo_move_to( cr,
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + bearing ,
     aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top );
   pango_cairo_show_layout( cr , osd_layout );
 }
@@ -230,9 +246,9 @@
   aosd_color_t textcolor0 = data->text->fonts_color[0];
   aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
   gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0;
+  gint width = 0, height = 0, bearing = 0;
 
-  pango_layout_get_pixel_size( osd_layout , &width , &height );
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
 
   /* draw rounded-rectangle container */
   cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
@@ -262,7 +278,7 @@
     cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
       (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
     cairo_move_to( cr ,
-      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + bearing + 2 ,
       aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + 2 );
     pango_cairo_show_layout( cr , osd_layout );
   }
@@ -271,7 +287,7 @@
   cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
     (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
   cairo_move_to( cr ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + bearing ,
     aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top );
   pango_cairo_show_layout( cr , osd_layout );
 }
@@ -291,9 +307,9 @@
   aosd_color_t textcolor0 = data->text->fonts_color[0];
   aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
   gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0;
+  gint width = 0, height = 0, bearing = 0;
 
-  pango_layout_get_pixel_size( osd_layout , &width , &height );
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
 
   /* draw jigsaw-piece-like container */
   cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
@@ -323,7 +339,7 @@
     cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
       (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
     cairo_move_to( cr ,
-      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + bearing + 2 ,
       aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + 2 );
     pango_cairo_show_layout( cr , osd_layout );
   }
@@ -332,7 +348,7 @@
   cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
     (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
   cairo_move_to( cr ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + bearing ,
     aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top );
   pango_cairo_show_layout( cr , osd_layout );
 }
@@ -350,9 +366,9 @@
   aosd_color_t textcolor0 = data->text->fonts_color[0];
   aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
   gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0;
+  gint width = 0, height = 0, bearing = 0;
 
-  pango_layout_get_pixel_size( osd_layout , &width , &height );
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
 
   if ( draw_shadow == TRUE )
   {
@@ -360,7 +376,7 @@
     cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
       (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
     cairo_move_to( cr ,
-      aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + bearing + 2 ,
       aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.top + 2 );
     pango_cairo_show_layout( cr , osd_layout );
   }
@@ -369,7 +385,7 @@
   cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
     (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
   cairo_move_to( cr ,
-    aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + bearing ,
     aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.top );
   pango_cairo_show_layout( cr , osd_layout );
 }
--- a/src/console/Blip_Buffer.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Blip_Buffer.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -27,7 +27,7 @@
 
 Blip_Buffer::Blip_Buffer()
 {
-	factor_       = LONG_MAX;
+	factor_       = UINT_MAX;
 	offset_       = 0;
 	buffer_       = 0;
 	buffer_size_  = 0;
--- a/src/console/Blip_Buffer.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Blip_Buffer.h	Wed Dec 19 17:51:50 2007 +0200
@@ -8,7 +8,7 @@
 	#include <limits.h>
 	#if INT_MAX >= 0x7FFFFFFF
 		typedef int blip_long;
-		typedef unsigned blip_ulong;
+		typedef unsigned int blip_ulong;
 	#else
 		typedef long blip_long;
 		typedef unsigned long blip_ulong;
--- a/src/console/Hes_Cpu.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Hes_Cpu.h	Wed Dec 19 17:51:50 2007 +0200
@@ -8,7 +8,7 @@
 
 typedef blargg_long hes_time_t; // clock cycle count
 typedef unsigned hes_addr_t; // 16-bit address
-enum { future_hes_time = LONG_MAX / 2 + 1 };
+enum { future_hes_time = INT_MAX / 2 + 1 };
 
 class Hes_Cpu {
 public:
--- a/src/console/Music_Emu.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Music_Emu.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -33,7 +33,7 @@
 	emu_time         = 0;
 	emu_track_ended_ = true;
 	track_ended_     = true;
-	fade_start       = LONG_MAX / 2 + 1;
+	fade_start       = INT_MAX / 2 + 1;
 	fade_step        = 1;
 	silence_time     = 0;
 	silence_count    = 0;
--- a/src/console/Nes_Apu.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Nes_Apu.h	Wed Dec 19 17:51:50 2007 +0200
@@ -78,7 +78,7 @@
 	// Get time that APU-generated IRQ will occur if no further register reads
 	// or writes occur. If IRQ is already pending, returns irq_waiting. If no
 	// IRQ will occur, returns no_irq.
-	enum { no_irq = LONG_MAX / 2 + 1 };
+	enum { no_irq = INT_MAX / 2 + 1 };
 	enum { irq_waiting = 0 };
 	nes_time_t earliest_irq( nes_time_t ) const;
 	
--- a/src/console/Nes_Cpu.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Nes_Cpu.h	Wed Dec 19 17:51:50 2007 +0200
@@ -8,7 +8,7 @@
 
 typedef blargg_long nes_time_t; // clock cycle count
 typedef unsigned nes_addr_t; // 16-bit address
-enum { future_nes_time = LONG_MAX / 2 + 1 };
+enum { future_nes_time = INT_MAX / 2 + 1 };
 
 class Nes_Cpu {
 public:
--- a/src/console/Sap_Cpu.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/console/Sap_Cpu.h	Wed Dec 19 17:51:50 2007 +0200
@@ -8,7 +8,7 @@
 
 typedef blargg_long sap_time_t; // clock cycle count
 typedef unsigned sap_addr_t; // 16-bit address
-enum { future_sap_time = LONG_MAX / 2 + 1 };
+enum { future_sap_time = INT_MAX / 2 + 1 };
 
 class Sap_Cpu {
 public:
--- a/src/demac/ape.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/demac/ape.h	Wed Dec 19 17:51:50 2007 +0200
@@ -224,6 +224,12 @@
   return tmp;
 }
 
+#ifdef ARCH_X86_64
+#  define LEGACY_REGS "=Q"
+#else
+#  define LEGACY_REGS "=q"
+#endif
+
 static inline uint32_t bswap_32(uint32_t x)
 {
 #if defined(ARCH_X86)
--- a/src/evdev-plug/ed_bindings_store.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/evdev-plug/ed_bindings_store.c	Wed Dec 19 17:51:50 2007 +0200
@@ -82,7 +82,7 @@
   return;
 }
 
-gint
+void
 ed_bindings_store_foreach ( gpointer hashtable_gp ,
                             ed_bindings_store_foreach_func callback ,
                             gpointer user_data1 ,
--- a/src/evdev-plug/ed_bindings_store.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/evdev-plug/ed_bindings_store.h	Wed Dec 19 17:51:50 2007 +0200
@@ -29,7 +29,7 @@
 
 gpointer ed_bindings_store_new ( void );
 gint ed_bindings_store_insert ( gpointer , ed_inputevent_t * , gint );
-gint ed_bindings_store_foreach ( gpointer , ed_bindings_store_foreach_func , gpointer , gpointer );
+void ed_bindings_store_foreach ( gpointer , ed_bindings_store_foreach_func , gpointer , gpointer );
 guint ed_bindings_store_size ( gpointer );
 gboolean ed_bindings_store_lookup( gpointer , ed_inputevent_t * , gint * );
 gint ed_bindings_store_delete ( gpointer );
--- a/src/evdev-plug/ed_internals.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/evdev-plug/ed_internals.c	Wed Dec 19 17:51:50 2007 +0200
@@ -38,7 +38,8 @@
 #include <stdarg.h>
 
 #include <audacious/i18n.h>
-
+#include <glib.h>
+#include <glib/gstdio.h>
 
 static gboolean ed_device_giofunc ( GIOChannel * , GIOCondition , gpointer );
 
@@ -240,7 +241,7 @@
 }
 
 
-gint
+void
 ed_device_stop_listening_all ( gboolean delete_bindings )
 {
   /* convenience function that stops listening for all
--- a/src/evdev-plug/ed_internals.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/evdev-plug/ed_internals.h	Wed Dec 19 17:51:50 2007 +0200
@@ -48,7 +48,7 @@
 void ed_device_start_listening_from_config ( void );
 gint ed_device_stop_listening ( ed_device_t * );
 gint ed_device_stop_listening_from_info ( ed_device_info_t * );
-gint ed_device_stop_listening_all ( gboolean );
+void ed_device_stop_listening_all ( gboolean );
 gboolean ed_device_check_listening_from_info ( ed_device_info_t * );
 
 gboolean ed_inputevent_check_equality( ed_inputevent_t * , ed_inputevent_t * );
--- a/src/filewriter/filewriter.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/filewriter/filewriter.c	Wed Dec 19 17:51:50 2007 +0200
@@ -135,9 +135,9 @@
 static void file_init(void)
 {
     ConfigDb *db;
-    GtkWidget *menu_root;
+    /*GtkWidget *menu_root;
 
-    /*menu_root = gtk_menu_item_new_with_label(_("FileWriter"));
+    menu_root = gtk_menu_item_new_with_label(_("FileWriter"));
     gtk_widget_show(menu_root);
     audacious_menu_plugin_item_add(AUDACIOUS_MENU_PLAYLIST_RCLICK, menu_root);*/
 
--- a/src/flacng/flacng.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/flacng/flacng.h	Wed Dec 19 17:51:50 2007 +0200
@@ -25,7 +25,7 @@
 #include <audacious/main.h>
 #include <audacious/i18n.h>
 
-#define OUTPUT_BLOCK_SIZE (8192u)
+#define OUTPUT_BLOCK_SIZE (1024u)
 #define MAX_SUPPORTED_CHANNELS (2u)
 #define BUFFER_SIZE_SAMP (FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS)
 #define BUFFER_SIZE_BYTE (BUFFER_SIZE_SAMP * (FLAC__MAX_BITS_PER_SAMPLE/8))
--- a/src/m3u/m3u.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/m3u/m3u.c	Wed Dec 19 17:51:50 2007 +0200
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+/* #define AUD_DEBUG 1 */
+
 #include <glib.h>
 #include <string.h>
 #include <glib.h>
@@ -84,14 +86,14 @@
     gint ext_len = -1;
     gboolean is_extm3u = FALSE;
     Playlist *playlist = aud_playlist_get_active();
-    gchar *uri;
+    gchar *uri = NULL;
     
     uri = g_filename_to_uri(filename, NULL, NULL);
 
     if ((file = aud_vfs_fopen(uri ? uri : filename, "rb")) == NULL)
         return;
 
-    g_free(uri);
+    g_free(uri); uri = NULL;
 
     line = g_malloc(line_len);
     while (aud_vfs_fgets(line, line_len, file)) {
@@ -130,15 +132,21 @@
             ext_info = NULL;
         }
 
-        uri = g_filename_to_uri(line, NULL, NULL);
-        aud_playlist_load_ins_file(playlist, uri ? uri : line, filename, pos, ext_title, ext_len);
+        uri = aud_construct_uri(line, filename);
+        AUDDBG("uri=%s\n", uri);
+
+        /* add file only if valid uri has been constructed */
+        if (uri) {
+            aud_playlist_load_ins_file(playlist, uri, filename, pos, ext_title, ext_len);
+
+            if (pos >= 0)
+                pos++;
+        }
+
         g_free(uri);
 
         aud_str_replace_in(&ext_title, NULL);
         ext_len = -1;
-
-        if (pos >= 0)
-            pos++;
     }
 
     aud_vfs_fclose(file);
--- a/src/madplug/configure.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/configure.c	Wed Dec 19 17:51:50 2007 +0200
@@ -37,9 +37,8 @@
 {
     ConfigDb *db;
     const gchar *text = NULL;
-#ifdef DEBUG
-    g_message("saving");
-#endif
+
+    AUDDBG("saving");
 
     audmad_config.fast_play_time_calc =
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fast_playback));
--- a/src/madplug/decoder.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/decoder.c	Wed Dec 19 17:51:50 2007 +0200
@@ -196,10 +196,8 @@
         info->fileinfo_request = FALSE;
     }
 
-#ifdef DEBUG
-    g_message("f: scan_file");
-    g_message("scan_file frames = %d", info->frames);
-#endif                          /* DEBUG */
+    AUDDBG("f: scan_file");
+    AUDDBG("scan_file frames = %d", info->frames);
 
     while (1) {
         remainder = stream.bufend - stream.next_frame;
@@ -216,9 +214,7 @@
                              BUFFER_SIZE - remainder);
 
         if (len <= 0) {
-#ifdef DEBUG
-            g_message("scan_file: len <= 0 len = %d", len);
-#endif
+            AUDDBG("scan_file: len <= 0 len = %d", len);
             break;
         }
 
@@ -230,12 +226,10 @@
                     break;
                 }
                 if (!MAD_RECOVERABLE(stream.error)) {
-#ifdef DEBUG
-                    g_message("(fatal) error decoding header %d: %s",
+                    AUDDBG("(fatal) error decoding header %d: %s",
                               info->frames, mad_stream_errorstr(&stream));
-                    g_message("remainder = %d", remainder);
-                    g_message("len = %d", len);
-#endif                          /* DEBUG */
+                    AUDDBG("remainder = %d", remainder);
+                    AUDDBG("len = %d", len);
                     break;
                 }
                 if (stream.error == MAD_ERROR_LOSTSYNC) {
@@ -244,31 +238,27 @@
                                             stream.bufend -
                                             stream.this_frame);
                     if (tagsize > 0) {
-#ifdef DEBUG
-                        g_message("skipping id3_tag: %d", tagsize);
-#endif                          /* DEBUG */
+                        AUDDBG("skipping id3_tag: %d", tagsize);
                         mad_stream_skip(&stream, tagsize);
                         continue;
                     }
                 }
-#ifdef DEBUG
-                g_message("(recovered) error decoding header %d: %s",
+
+                AUDDBG("(recovered) error decoding header %d: %s",
                           info->frames, mad_stream_errorstr(&stream));
-                g_message("remainder = %d", remainder);
-                g_message("len = %d", len);
-#endif                          /* DEBUG */
+                AUDDBG("remainder = %d", remainder);
+                AUDDBG("len = %d", len);
+
                 continue;
             }
             info->frames++;
 
-#ifdef DEBUG
 #ifdef DEBUG_INTENSIVELY
-            g_message("header bitrate = %ld", header.bitrate);
-            g_message("duration = %ul",
+            AUDDBG("header bitrate = %ld", header.bitrate);
+            AUDDBG("duration = %ul",
                       mad_timer_count(header.duration,
                                       MAD_UNITS_MILLISECONDS));
-            g_message("size = %d", stream.next_frame - stream.this_frame);
-#endif
+            AUDDBG("size = %d", stream.next_frame - stream.this_frame);
 #endif
             if(aud_tuple_get_int(info->tuple, FIELD_LENGTH, NULL) == -1)
                 mad_timer_add(&info->duration, header.duration);
@@ -290,40 +280,34 @@
                 if (audmad_config.use_xing) {
                     frame.header = header;
                     if (mad_frame_decode(&frame, &stream) == -1) {
-#ifdef DEBUG
-                        g_message("xing frame decode failed");
-#endif
+                        AUDDBG("xing frame decode failed");
                         goto no_xing;
                     }
                     if (xing_parse(&info->xing, stream.anc_ptr, stream.anc_bitlen) == 0) {
-#ifdef DEBUG
-                        g_message("xing header found ");
-#endif                          /* DEBUG */
+                        AUDDBG("xing header found ");
                         has_xing = TRUE;
                         info->vbr = TRUE;   /* otherwise xing header would have been 'Info' */
 
-#ifdef DEBUG
-                        g_message("xing: bytes = %ld frames = %ld", info->xing.bytes, info->xing.frames);
-#endif
+                        AUDDBG("xing: bytes = %ld frames = %ld", info->xing.bytes, info->xing.frames);
+
                         /* we have enough info to calculate bitrate and duration */
                         if(info->xing.bytes && info->xing.frames) {
                             xing_bitrate = 8 * (double)info->xing.bytes * 38 / (double)info->xing.frames; //38fps in MPEG1.
-#ifdef DEBUG
+#ifdef AUD_DEBUG
                             {
                                 gint tmp = (gint)(info->xing.bytes * 8 / xing_bitrate);
-                                g_message("xing: bitrate = %4.1f kbps", xing_bitrate / 1000);
-                                g_message("xing: duration = %d:%02d", tmp / 60, tmp % 60);
+                                AUDDBG("xing: bitrate = %4.1f kbps", xing_bitrate / 1000);
+                                AUDDBG("xing: duration = %d:%02d", tmp / 60, tmp % 60);
                             }
 #endif
                         }
                         continue;
                     }
-#ifdef DEBUG
+#ifdef AUD_DEBUG
                     else {
-                        g_message("no usable xing header");
+                        AUDDBG("no usable xing header");
                         continue;
                     }
-                    
 #endif
                 } /* xing */
 
@@ -347,16 +331,16 @@
         no_xing:
             if (fast && info->frames >= N_AVERAGE_FRAMES) {
                 float frame_size = ((double) data_used) / N_AVERAGE_FRAMES;
-#ifdef DEBUG
-                g_message("bitrate = %ld samplerate = %d", header.bitrate, header.samplerate);
-                g_message("data_used = %d info->frames = %d info->size = %d tagsize = %d frame_size = %lf",
+
+                AUDDBG("bitrate = %ld samplerate = %d", header.bitrate, header.samplerate);
+                AUDDBG("data_used = %d info->frames = %d info->size = %d tagsize = %d frame_size = %lf",
                           data_used, info->frames, info->size, tagsize, frame_size);
-#endif
+
                 if(info->size != 0)
                     info->frames = (info->size - tagsize) / frame_size;
-#ifdef DEBUG
-                g_message("info->frames = %d", info->frames);
-#endif
+
+                AUDDBG("info->frames = %d", info->frames);
+
                 if(aud_tuple_get_int(info->tuple, FIELD_LENGTH, NULL) == -1) {
                     if(xing_bitrate > 0.0) {
                         /* calc duration with xing info */
@@ -376,15 +360,15 @@
                     info->duration.seconds = length / 1000;
                     info->duration.fraction = length % 1000;
                 }
-#ifdef DEBUG
-                g_message("using fast playtime calculation");
-                g_message("data used = %d [tagsize=%d framesize=%f]",
+#ifdef AUD_DEBUG
+                AUDDBG("using fast playtime calculation");
+                AUDDBG("data used = %d [tagsize=%d framesize=%f]",
                           data_used, tagsize, frame_size);
-                g_message("frames = %d, frequency = %d, channels = %d",
+                AUDDBG("frames = %d, frequency = %d, channels = %d",
                           info->frames, info->freq, info->channels);
                 long millis = mad_timer_count(info->duration,
                                               MAD_UNITS_MILLISECONDS);
-                g_message("duration = %ld:%02ld", millis / 1000 / 60, (millis / 1000) % 60);
+                AUDDBG("duration = %ld:%02ld", millis / 1000 / 60, (millis / 1000) % 60);
 #endif                          /* DEBUG */
                 break;
             }
@@ -408,10 +392,9 @@
     mad_stream_finish(&stream);
     xing_finish(&info->xing);
 
-#ifdef DEBUG
-    g_message("scan_file: info->frames = %d", info->frames);
-    g_message("e: scan_file");
-#endif                          /* DEBUG */
+    AUDDBG("scan_file: info->frames = %d", info->frames);
+    AUDDBG("e: scan_file");
+
     return (info->frames != 0 || info->remote == TRUE);
 }
 
@@ -445,9 +428,7 @@
     /* track info is passed in as thread argument */
     struct mad_info_t *info = (struct mad_info_t *) arg;
 
-#ifdef DEBUG
-    g_message("f: decode");
-#endif                          /* DEBUG */
+    AUDDBG("f: decode");
 
     /* init mad stuff */
     mad_frame_init(&frame);
@@ -456,15 +437,11 @@
     mad_synth_init(&synth);
 
     if(!info->playback){
-#ifdef DEBUG
-        g_message("decode: playback == NULL");
-#endif
+        AUDDBG("decode: playback == NULL");
         return NULL;
     }
 
-#ifdef DEBUG
-    g_message("decode: fmt = %d freq = %d channels = %d", info->fmt, info->freq, info->channels);
-#endif
+    AUDDBG("decode: fmt = %d freq = %d channels = %d", info->fmt, info->freq, info->channels);
 
     if(check_audio_param(info) == FALSE)
         return NULL;
@@ -489,16 +466,13 @@
         info->playback->set_params(info->playback, info->title,
                              (tlen == 0 || info->size <= 0) ? -1 : tlen,
                              info->bitrate, info->freq, info->channels);
-#ifdef DEBUG
-    g_message("decode: tlen = %d", tlen);
-#endif
+
+    AUDDBG("decode: tlen = %d", tlen);
 
     /* main loop */
     do {
         if (!info->playback->playing) {
-#ifdef DEBUG
-            g_message("decode: stop signaled");
-#endif                          /* DEBUG */
+            AUDDBG("decode: stop signaled");
             break;
         }
         if (seek_skip)
@@ -513,9 +487,7 @@
         input_process_remote_metadata(info);
 
         if (len <= 0) {
-#ifdef DEBUG
-            g_message("finished decoding");
-#endif                          /* DEBUG */
+            AUDDBG("finished decoding");
             break;
         }
         len += remainder;
@@ -529,9 +501,9 @@
         mad_stream_buffer(&stream, buffer, len);
 
         if (seek_skip) {
-#ifdef DEBUG
-            g_message("skipping: %d", seek_skip);
-#endif
+
+            AUDDBG("skipping: %d", seek_skip);
+
             int skip = 2;
             do {
                 if (mad_frame_decode(&frame, &stream) == 0) {
@@ -553,9 +525,9 @@
 
         while (info->playback->playing) {
             if (info->seek != -1 && info->size > 0) {
-#ifdef DEBUG
-                g_message("seeking: %ld", info->seek);
-#endif
+
+                AUDDBG("seeking: %ld", info->seek);
+
                 int new_position;
                 gulong milliseconds =
                     mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS);
@@ -568,9 +540,9 @@
 
                 if(new_position < 0)
                     new_position = 0;
-#ifdef DEBUG
-                g_message("seeking to: %d bytes", new_position);
-#endif
+
+                AUDDBG("seeking to: %d bytes", new_position);
+
                 if (aud_vfs_fseek(info->infile, new_position, SEEK_SET) == -1)
                     audmad_error("failed to seek to: %d", new_position);
                 mad_frame_mute(&frame);
@@ -597,21 +569,20 @@
                         continue;
                     }
                 }
-#ifdef DEBUG
-                g_message("(recovered) error decoding header %d: %s",
+
+                AUDDBG("(recovered) error decoding header %d: %s",
                           info->current_frame,
                           mad_stream_errorstr(&stream));
-#endif                          /* DEBUG */
+
                 continue;
             }
 
             info->bitrate = frame.header.bitrate;
 
             if (!audmad_config.show_avg_vbr_bitrate && info->vbr && (iteration % 40 == 0)) {
-#ifdef DEBUG
+
 #ifdef DEBUG_INTENSIVELY
-                g_message("decode vbr tlen = %d", tlen);
-#endif
+                AUDDBG("decode vbr tlen = %d", tlen);
 #endif
                 info->playback->set_params(info->playback, info->title,
                                      (tlen == 0 || info->size <= 0) ? -1 : tlen,
@@ -622,11 +593,11 @@
             if (mad_frame_decode(&frame, &stream) == -1) {
                 if (!MAD_RECOVERABLE(stream.error))
                     break;
-#ifdef DEBUG
-                g_message("(recovered) error decoding frame %d: %s",
+
+                AUDDBG("(recovered) error decoding frame %d: %s",
                           info->current_frame,
                           mad_stream_errorstr(&stream));
-#endif                          /* DEBUG */
+
             }
 
             info->current_frame++;
@@ -634,22 +605,22 @@
             if (info->freq != frame.header.samplerate
                 || info->channels !=
                 (guint) MAD_NCHANNELS(&frame.header)) {
-#ifdef DEBUG
-                g_message("change in audio type detected");
-                g_message("old: frequency = %d, channels = %d", info->freq,
+
+                AUDDBG("change in audio type detected");
+                AUDDBG("old: frequency = %d, channels = %d", info->freq,
                           info->channels);
-                g_message("new: frequency = %d, channels = %d",
+                AUDDBG("new: frequency = %d, channels = %d",
                           frame.header.samplerate,
                           (guint) MAD_NCHANNELS(&frame.header));
-#endif                          /* DEBUG */
+
                 info->freq = frame.header.samplerate;
                 info->channels = MAD_NCHANNELS(&frame.header);
 
                 if(audmad_config.force_reopen_audio && check_audio_param(info)) {
                     gint current_time = info->playback->output->output_time();
-#ifdef DEBUG
-                    g_message("re-opening audio due to change in audio type");
-#endif
+
+                    AUDDBG("re-opening audio due to change in audio type");
+
                     info->playback->output->close_audio();
                     if (!info->playback->output->open_audio(info->fmt, info->freq,
                                                             info->channels)) {
@@ -688,10 +659,9 @@
         info->playback->output->buffer_free();
         info->playback->output->buffer_free();
         while (info->playback->output->buffer_playing()) {
-#ifdef DEBUG
-            g_message("f: buffer_playing=%d",
-                      info->playback->output->buffer_playing());
-#endif
+
+            AUDDBG("f: buffer_playing=%d", info->playback->output->buffer_playing());
+
             g_get_current_time(&sleeptime);
             g_time_val_add(&sleeptime, 500000);
             
@@ -704,9 +674,8 @@
 
         }
     }
-#ifdef DEBUG
-    g_message("e: decode");
-#endif                          /* DEBUG */
+
+    AUDDBG("e: decode");
 
     aud_tuple_free(info->tuple);
     info->tuple = NULL;
--- a/src/madplug/input.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/input.c	Wed Dec 19 17:51:50 2007 +0200
@@ -71,9 +71,8 @@
  */
 gboolean input_init(struct mad_info_t * info, const char *url, VFSFile *fd)
 {
-#ifdef DEBUG
-    g_message("f: input_init");
-#endif
+    AUDDBG("f: input_init");
+
     memset(info, 0, sizeof(struct mad_info_t)); // all fields are cleared to 0 --yaz
 
     info->fmt = FMT_S16_LE;
@@ -100,9 +99,8 @@
         }
     }
     else{
-#ifdef DEBUG
-        printf("input_init: aud_vfs_dup\n");
-#endif
+        AUDDBG("input_init: aud_vfs_dup\n");
+
         info->infile = aud_vfs_dup(fd);
     }
 
@@ -114,10 +112,9 @@
 
     info->fileinfo_request = FALSE;
 
-#ifdef DEBUG
-    g_message("i: info->size = %lu", (long unsigned int)info->size);
-    g_message("e: input_init");
-#endif
+    AUDDBG("i: info->size = %lu", (long unsigned int)info->size);
+    AUDDBG("e: input_init");
+
     return TRUE;
 }
 
@@ -223,18 +220,16 @@
                 tp++;
             }
             if(is_num) {
-#ifdef DEBUG
-                printf("is_num!\n");
-#endif
+                AUDDBG("is_num!\n");
+
                 tmp = g_malloc0(BYTES(end - ptr + 1));
                 memcpy(tmp, ptr, BYTES(end - ptr));
                 *(tmp + (end - ptr)) = 0; //terminate
                 ptr += end - ptr;
 
                 genre = (id3_ucs4_t *)id3_genre_name((const id3_ucs4_t *)tmp);
-#ifdef DEBUG
-                printf("genre length = %d\n", mad_ucs4len(genre));
-#endif
+                AUDDBG("genre length = %d\n", mad_ucs4len(genre));
+
                 g_free(tmp);
                 tmp = NULL;
 
@@ -246,11 +241,10 @@
                 *(ret + ret_len) = 0; //terminate
             }
             else { // plain text
-#ifdef DEBUG
-                printf("plain!\n");
-                printf("ret_len = %d\n", ret_len);
-                printf("end - ptr = %d\n", BYTES(end - ptr));
-#endif
+                AUDDBG("plain!\n");
+                AUDDBG("ret_len = %d\n", ret_len);
+                AUDDBG("end - ptr = %d\n", BYTES(end - ptr));
+
                 memcpy(ret + BYTES(ret_len), ptr, BYTES(end - ptr));
                 ret_len = ret_len + (end - ptr);
                 *(ret + ret_len) = 0; //terminate
@@ -316,9 +310,8 @@
     }
     g_free((void *)string);
         
-#ifdef DEBUG
-    g_print("i: string = %s\n", rtn);
-#endif
+    AUDDBG("i: string = %s\n", rtn);
+
     return rtn;
 }
 
@@ -352,9 +345,8 @@
     Tuple *tuple;
     glong curpos = 0;
 
-#ifdef DEBUG
-    g_message("f: input_read_tag");
-#endif
+    AUDDBG("f: input_read_tag");
+
     if (info->tuple != NULL)
         aud_tuple_free(info->tuple);
         
@@ -370,17 +362,13 @@
     }
 
     if (!info->id3file) {
-#ifdef DEBUG
-        g_message("read_tag: no id3file");
-#endif
+        AUDDBG("read_tag: no id3file");
         return;
     }
 
     info->tag = id3_file_tag(info->id3file);
     if (!info->tag) {
-#ifdef DEBUG
-        g_message("read_tag: no tag");
-#endif
+        AUDDBG("read_tag: no tag");
         return;
     }
 
@@ -413,9 +401,7 @@
     string = input_id3_get_string(info->tag, "TLEN");
     if (string) {
         aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, atoi(string));
-#ifdef DEBUG
-        g_message("input_read_tag: TLEN = %d", atoi(string));
-#endif	
+        AUDDBG("input_read_tag: TLEN = %d", atoi(string));
         g_free(string);
         string = NULL;
     } else
@@ -433,9 +419,7 @@
         aud_vfs_fseek(info->infile, curpos, SEEK_SET);
     }
     
-#ifdef DEBUG
-    g_message("e: input_read_tag");
-#endif
+    AUDDBG("e: input_read_tag");
 }
 
 void input_process_remote_metadata(struct mad_info_t *info)
@@ -444,12 +428,10 @@
 
     if(info->remote && mad_timer_count(info->duration, MAD_UNITS_SECONDS) <= 0){
         gchar *tmp = NULL;
-#ifdef DEBUG
+
 #ifdef DEBUG_INTENSIVELY
-        g_message("process_remote_meta");
+        AUDDBG("process_remote_meta");
 #endif
-#endif
-
         g_free(info->title);
         info->title = NULL;
         aud_tuple_disassociate(info->tuple, FIELD_TITLE, NULL);
@@ -516,9 +498,9 @@
  */
 gboolean input_get_info(struct mad_info_t *info, gboolean fast_scan)
 {
-#ifdef DEBUG
+#ifdef AUD_DEBUG
     gchar *tmp = g_filename_to_utf8(info->filename, -1, NULL, NULL, NULL);    
-    g_message("f: input_get_info: %s, fast_scan = %s", tmp, fast_scan ? "TRUE" : "FALSE");
+    AUDDBG("f: input_get_info: %s, fast_scan = %s", tmp, fast_scan ? "TRUE" : "FALSE");
     g_free(tmp);
 #endif                          /* DEBUG */
 
@@ -531,9 +513,7 @@
 
     /* scan mp3 file, decoding headers */
     if (scan_file(info, fast_scan) == FALSE) {
-#ifdef DEBUG
-        g_message("input_get_info: scan_file failed");
-#endif
+        AUDDBG("input_get_info: scan_file failed");
         return FALSE;
     }
 
@@ -550,9 +530,7 @@
             info->title = g_strdup(info->filename); //XXX info->filename is uri. --yaz
     }
 
-#ifdef DEBUG
-    g_message("e: input_get_info");
-#endif                          /* DEBUG */
+    AUDDBG("e: input_get_info");
     return TRUE;
 }
 
@@ -570,10 +548,8 @@
                int buffer_size)
 {
     int len = 0;
-#ifdef DEBUG
 #ifdef DEBUG_INTENSIVELY
-  g_message ("f: input_get_data: %d", buffer_size);
-#endif
+  AUDDBG ("f: input_get_data: %d", buffer_size);
 #endif
     /* simply read to data from the file */
     len = aud_vfs_fread(buffer, 1, buffer_size, info->infile); //aud_vfs_fread returns num of elements.
@@ -582,11 +558,10 @@
         info->playback->eof = TRUE;
     }
 
-#ifdef DEBUG
 #ifdef DEBUG_INTENSIVELY
-    g_message ("e: input_get_data: size=%d offset=%d", len, info->offset);
+    AUDDBG ("e: input_get_data: size=%d offset=%d", len, info->offset);
 #endif
-#endif
+
     info->offset += len;
     return len;
 }
@@ -596,9 +571,7 @@
  */
 gboolean input_term(struct mad_info_t * info)
 {
-#ifdef DEBUG
-    g_message("f: input_term");
-#endif
+    AUDDBG("f: input_term");
 
     if (info->title)
         g_free(info->title);
@@ -634,8 +607,8 @@
 
     /* set everything to zero in case it gets used again. */
     memset(info, 0, sizeof(struct mad_info_t));
-#ifdef DEBUG
-    g_message("e: input_term");
-#endif
+
+    AUDDBG("e: input_term");
+
     return TRUE;
 }
--- a/src/madplug/plugin.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/plugin.c	Wed Dec 19 17:51:50 2007 +0200
@@ -1,6 +1,6 @@
 /*
  * mad plugin for audacious
- * Copyright (C) 2005-2007 William Pitcock, Yoshiki Yazawa
+ * Copyright (C) 2005-2007 William Pitcock, Yoshiki Yazawa, Eugene Zagidullin
  *
  * Portions derived from xmms-mad:
  * Copyright (C) 2001-2002 Sam Clegg - See COPYING
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/* #define AUD_DEBUG 1 */
+
 #include "config.h"
 #include "plugin.h"
 #include "input.h"
@@ -102,19 +104,15 @@
     else
       x = 0;
     config->pregain_scale = (x != 0) ? pow(10.0, x / 20) : 1;
-#ifdef DEBUG
-    g_message("pregain=[%s] -> %g  -> %g", text, x, config->pregain_scale);
-#endif
+    AUDDBG("pregain=[%s] -> %g  -> %g", text, x, config->pregain_scale);
     text = config->replaygain.default_db;
     if ( text != NULL )
       x = g_strtod(text, NULL);
     else
       x = 0;
     config->replaygain.default_scale = (x != 0) ? pow(10.0, x / 20) : 1;
-#ifdef DEBUG
-    g_message("RG.default=[%s] -> %g  -> %g", text, x,
+    AUDDBG("RG.default=[%s] -> %g  -> %g", text, x,
               config->replaygain.default_scale);
-#endif
 }
 
 static void audmad_init()
@@ -405,9 +403,7 @@
 
 static void audmad_stop(InputPlayback *playback)
 {
-#ifdef DEBUG
-    g_message("f: audmad_stop");
-#endif
+    AUDDBG("f: audmad_stop");
     g_mutex_lock(mad_mutex);
     info.playback = playback;
     g_mutex_unlock(mad_mutex);
@@ -419,20 +415,15 @@
         g_mutex_unlock(mad_mutex);
         g_cond_signal(mad_cond);
 
-#ifdef DEBUG
-        g_message("waiting for thread");
-#endif
+        AUDDBG("waiting for thread");
         g_thread_join(decode_thread);
-#ifdef DEBUG
-        g_message("thread done");
-#endif
+        AUDDBG("thread done");
+
         input_term(&info);
         decode_thread = NULL;
 
     }
-#ifdef DEBUG
-    g_message("e: audmad_stop");
-#endif
+    AUDDBG("e: audmad_stop");
 }
 
 static void audmad_play_file(InputPlayback *playback)
@@ -440,10 +431,10 @@
     gboolean rtn;
     gchar *url = playback->filename;
 
-#ifdef DEBUG
+#ifdef AUD_DEBUG
     {
         gchar *tmp = g_filename_to_utf8(url, -1, NULL, NULL, NULL);
-        g_message("playing %s", tmp);
+        AUDDBG("playing %s", tmp);
         g_free(tmp);
     }
 #endif                          /* DEBUG */
@@ -503,16 +494,14 @@
 audmad_get_song_info(char *url, char **title, int *length)
 {
     struct mad_info_t myinfo;
-#ifdef DEBUG
+#ifdef AUD_DEBUG
     gchar *tmp = g_filename_to_utf8(url, -1, NULL, NULL, NULL);
-    g_message("f: audmad_get_song_info: %s", tmp);
+    AUDDBG("f: audmad_get_song_info: %s", tmp);
     g_free(tmp);
 #endif                          /* DEBUG */
 
     if (input_init(&myinfo, url, NULL) == FALSE) {
-#ifdef DEBUG
-        g_message("error initialising input");
-#endif
+        AUDDBG("error initialising input");
         return;
     }
 
@@ -531,40 +520,22 @@
         *length = -1;
     }
     input_term(&myinfo);
-#ifdef DEBUG
-    g_message("e: audmad_get_song_info");
-#endif                          /* DEBUG */
+    AUDDBG("e: audmad_get_song_info");
 }
 
-static void
-audmad_get_song_length(char *url, int *length, VFSFile *fd)
+static gboolean
+audmad_fill_info(struct mad_info_t *info, VFSFile *fd)
 {
-    struct mad_info_t myinfo;
-#ifdef DEBUG
-    gchar *tmp = g_filename_to_utf8(url, -1, NULL, NULL, NULL);
-    g_message("f: audmad_get_song_length: %s", tmp);
-    g_free(tmp);
-#endif                          /* DEBUG */
+    if (fd == NULL || info == NULL) return FALSE;
+    AUDDBG("f: audmad_fill_info(): %s", fd->uri);
 
-    if (input_init(&myinfo, url, fd ? fd : NULL) == FALSE) {
-#ifdef DEBUG
-        g_message("error initialising input");
-#endif
-        return;
+    if (input_init(info, fd->uri, fd) == FALSE) {
+        AUDDBG("audmad_fill_info(): error initialising input");
+        return FALSE;
     }
-
-    if (input_get_info(&myinfo, info.remote ? TRUE : audmad_config.fast_play_time_calc) == TRUE) {
-        *length = aud_tuple_get_int(myinfo.tuple, FIELD_LENGTH, NULL);
-        if(*length == -1)
-            *length = mad_timer_count(myinfo.duration, MAD_UNITS_MILLISECONDS);
-    }
-    else {
-        *length = -1;
-    }
-    input_term(&myinfo);
-#ifdef DEBUG
-    g_message("e: audmad_get_song_info");
-#endif                          /* DEBUG */
+    
+    info->fileinfo_request = FALSE; /* we don't need to read tuple again */
+    return input_get_info(info, aud_vfs_is_remote(fd->uri) ? TRUE : audmad_config.fast_play_time_calc);
 }
 
 static void audmad_about()
@@ -639,28 +610,32 @@
 {
     Tuple *tuple = NULL;
     gchar *string = NULL;
-    gchar *realfn = NULL;
 
     struct id3_file *id3file = NULL;
     struct id3_tag *tag = NULL;
 
-    gboolean local_fd = FALSE;
+    struct mad_info_t myinfo;
 
-#ifdef DEBUG
+    gboolean local_fd = FALSE;
+    int length;
+
+#ifdef AUD_DEBUG
     string = aud_str_to_utf8(filename);
-    g_message("f: mad: audmad_get_song_tuple: %s", string);
+    AUDDBG("f: mad: audmad_get_song_tuple: %s", string);
     g_free(string);
     string = NULL;
 #endif
 
+    /* isn't is obfuscated? --eugene */
+
     if(info.remote && mad_timer_count(info.duration, MAD_UNITS_SECONDS) <= 0){
         if((fd && aud_vfs_is_streaming(fd)) || (info.playback && info.playback->playing)) {
             gchar *tmp = NULL;
             tuple = aud_tuple_new_from_filename(filename);
 
-#ifdef DEBUG
+#ifdef AUD_DEBUG
             if(info.playback)
-                g_message("info.playback->playing = %d",info.playback->playing);
+                AUDDBG("info.playback->playing = %d",info.playback->playing);
 #endif
             tmp = aud_vfs_get_metadata(info.infile ? info.infile : fd, "track-name");
             if(tmp){
@@ -685,21 +660,14 @@
                 tmp = NULL;
             }
 
-#ifdef DEBUG
-            g_message("audmad_get_song_tuple: track_name = %s", aud_tuple_get_string(tuple, -1, "track-name"));
-            g_message("audmad_get_song_tuple: stream_name = %s", aud_tuple_get_string(tuple, -1, "stream-name"));
-#endif
+            AUDDBG("audmad_get_song_tuple: track_name = %s", aud_tuple_get_string(tuple, -1, "track-name"));
+            AUDDBG("audmad_get_song_tuple: stream_name = %s", aud_tuple_get_string(tuple, -1, "stream-name"));
             aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, -1);
             aud_tuple_associate_int(tuple, FIELD_MTIME, NULL, 0); // this indicates streaming
-#ifdef DEBUG
-            g_message("get_song_tuple: remote: tuple");
-#endif
+            AUDDBG("get_song_tuple: remote: tuple");
             return tuple;
         }
-#ifdef DEBUG
-        g_message("get_song_tuple: remote: NULL");
-#endif
-//        return NULL;
+        AUDDBG("get_song_tuple: remote: NULL");
     } /* info.remote  */
 
     // if !fd, pre-open the file with aud_vfs_fopen() and reuse fd.
@@ -710,6 +678,12 @@
         local_fd = TRUE;
     }
 
+    if (!audmad_fill_info(&myinfo, fd)) {
+        AUDDBG("get_song_tuple: error obtaining info\n");
+        if (local_fd) aud_vfs_fclose(fd);
+        return NULL;
+    }
+
     tuple = aud_tuple_new();
     aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, -1);
 
@@ -734,29 +708,14 @@
                 g_free(string);
                 string = NULL;
             }
-            realfn = g_filename_from_uri(filename, NULL, NULL);
-            __set_and_free(tuple, FIELD_FILE_NAME, NULL, g_path_get_basename(realfn ? realfn : filename));
-            __set_and_free(tuple, FIELD_FILE_PATH, NULL, g_path_get_dirname(realfn ? realfn : filename));
-            aud_tuple_associate_string(tuple, FIELD_FILE_EXT, NULL, extname(realfn ? realfn : filename));
-            g_free(realfn); realfn = NULL;
+
+            __set_and_free(tuple, FIELD_FILE_NAME, NULL, aud_uri_to_display_basename(filename));
+            __set_and_free(tuple, FIELD_FILE_PATH, NULL, aud_uri_to_display_dirname(filename));
+            aud_tuple_associate_string(tuple, FIELD_FILE_EXT, NULL, extname(filename));
 
             // length
-            string = input_id3_get_string(tag, "TLEN");
-            if (string) {
-                aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, atoi(string));
-#ifdef DEBUG
-                g_message("get_song_tuple: TLEN = %d", aud_tuple_get_int(tuple, FIELD_LENGTH, NULL));
-#endif
-                g_free(string);
-                string = NULL;
-            }
-            else {
-                char *dummy = NULL;
-                int length = 0;
-                audmad_get_song_length(filename, &length, fd);
-                aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, length);
-                g_free(dummy);
-            }
+            length = mad_timer_count(myinfo.duration, MAD_UNITS_MILLISECONDS);
+            aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, length);
 
             // track number
             string = input_id3_get_string(tag, ID3_FRAME_TRACK);
@@ -768,43 +727,35 @@
             // genre
             __set_and_free(tuple, FIELD_GENRE, NULL, input_id3_get_string(tag, ID3_FRAME_GENRE));
             __set_and_free(tuple, FIELD_COMMENT, NULL, input_id3_get_string(tag, ID3_FRAME_COMMENT));
-#ifdef DEBUG
-            g_message("genre = %s", aud_tuple_get_string(tuple, FIELD_GENRE, NULL));
-#endif
+            AUDDBG("genre = %s", aud_tuple_get_string(tuple, FIELD_GENRE, NULL));
         }
         id3_file_close(id3file);
     } // id3file
     else { // no id3tag
-        realfn = g_filename_from_uri(filename, NULL, NULL);
-        __set_and_free(tuple, FIELD_FILE_NAME, NULL, g_path_get_basename(realfn ? realfn : filename));
-        __set_and_free(tuple, FIELD_FILE_PATH, NULL, g_path_get_dirname(realfn ? realfn : filename));
-        aud_tuple_associate_string(tuple, FIELD_FILE_EXT, NULL, extname(realfn ? realfn : filename));
-        g_free(realfn); realfn = NULL;
+        __set_and_free(tuple, FIELD_FILE_NAME, NULL, aud_uri_to_display_basename(filename));
+        __set_and_free(tuple, FIELD_FILE_PATH, NULL, aud_uri_to_display_dirname(filename));
+        aud_tuple_associate_string(tuple, FIELD_FILE_EXT, NULL, extname(filename));
         // length
-        {
-            char *dummy = NULL;
-            int length = 0;
-            if(aud_tuple_get_int(tuple, FIELD_LENGTH, NULL) == -1) {
-                audmad_get_song_length(filename, &length, fd);
-                aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, length);
-            }
-            g_free(dummy);
-        }
+        length = mad_timer_count(myinfo.duration, MAD_UNITS_MILLISECONDS);
+        aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, length);
     }
 
-    /* TUDO: make tuple more informative (bitrate, layer).
-     * but it can slowdown tuple creation and avoid sense of TLEN reading. --eugene */
+    aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossy");
+    aud_tuple_associate_int(tuple, FIELD_BITRATE, NULL, myinfo.bitrate / 1000);
+    g_free(string);
 
-    aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossy");
-    aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, "MPEG Audio (MP3)");
+    string = g_strdup_printf("MPEG-1 Audio Layer %d", myinfo.mpeg_layer);
+    aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, string);
+    g_free(string);
+
     aud_tuple_associate_string(tuple, FIELD_MIMETYPE, NULL, "audio/mpeg");
+    
+    input_term(&myinfo);
 
     if(local_fd)
         aud_vfs_fclose(fd);
 
-#ifdef DEBUG
-    g_message("e: mad: audmad_get_song_tuple");
-#endif
+    AUDDBG("e: mad: audmad_get_song_tuple");
     return tuple;
 }
 
--- a/src/madplug/plugin.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/plugin.h	Wed Dec 19 17:51:50 2007 +0200
@@ -22,7 +22,7 @@
 #ifndef AUD_MAD_H
 #define AUD_MAD_H
 
-/* #define DEBUG 1 */
+/* #define AUD_DEBUG 1 */
 /* #define DEBUG_INTENSIVELY 1 */
 /* #define DEBUG_DITHER 1 */
 
--- a/src/madplug/replaygain.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/replaygain.c	Wed Dec 19 17:51:50 2007 +0200
@@ -92,10 +92,9 @@
         free(buff);
         return 8;
     }
-#ifdef DEBUG
-    printf("ver = %ld\n", Read_LE_Uint32(tp->Version));
-    printf("taglen = %ld\n", TagLen);
-#endif
+
+    AUDDBG("ver = %ld\n", Read_LE_Uint32(tp->Version));
+    AUDDBG("taglen = %ld\n", TagLen);
 
     TagCount = Read_LE_Uint32(tp->TagCount);
     end = buff + TagLen - sizeof(T);
@@ -204,14 +203,11 @@
 	char *value;
 	struct id3_frame *frame;
 
-#ifdef DEBUG
-	g_message("f: ReadId3v2TXXX");
-#endif
+	AUDDBG("f: ReadId3v2TXXX");
+
 	/* tag must be read before! */
 	if (! file_info->tag ) {
-#ifdef DEBUG
-		g_message("id3v2 not found");
-#endif
+		AUDDBG("id3v2 not found");
 		return 0;
 	}
 
@@ -259,9 +255,7 @@
     VFSFile *fp;
     glong curpos = 0;
 
-#ifdef DEBUG
-    g_message("f: read_replaygain");
-#endif
+    AUDDBG("f: read_replaygain");
 
     file_info->has_replaygain = FALSE;
     file_info->replaygain_album_scale = -1;
@@ -270,11 +264,11 @@
     file_info->mp3gain_minmax = -77;
 
     if (ReadId3v2TXXX(file_info)) {
-#ifdef DEBUG
-        g_message("found ReplayGain info in id3v2 tag");
+#ifdef AUD_DEBUG
+        AUDDBG("found ReplayGain info in id3v2 tag");
 
 	gchar *tmp = g_filename_to_utf8(file_info->filename, -1, NULL, NULL, NULL);
-        g_message("RG album scale= %g, RG track scale = %g, in %s",
+        AUDDBG("RG album scale= %g, RG track scale = %g, in %s",
 		  file_info->replaygain_album_scale,
 		  file_info->replaygain_track_scale, tmp);
         g_free(tmp);
@@ -322,15 +316,15 @@
                      offs, res);
             }
         }
-#ifdef DEBUG
+#ifdef AUD_DEBUG
         else 
-            g_message("replaygain: not found");
+            AUDDBG("replaygain: not found");
 #endif
     }
-#ifdef DEBUG
+#ifdef AUD_DEBUG
     if (res == 0) {             // got APE tags, show the result
         gchar *tmp = g_filename_to_utf8(file_info->filename, -1, NULL, NULL, NULL);        
-        g_message("RG album scale= %g, RG track scale = %g, in %s",
+        AUDDBG("RG album scale= %g, RG track scale = %g, in %s",
 		  file_info->replaygain_album_scale,
 		  file_info->replaygain_track_scale, tmp);
         g_free(tmp);
@@ -346,7 +340,5 @@
 
     aud_vfs_fclose(fp);
 
-#ifdef DEBUG
-    g_message("e: read_replaygain");
-#endif
+    AUDDBG("e: read_replaygain");
 }
--- a/src/madplug/tuple.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/madplug/tuple.c	Wed Dec 19 17:51:50 2007 +0200
@@ -35,7 +35,6 @@
 #include <audacious/plugin.h>
 #include <audacious/id3tag.h>
 
-/* yaz */
 #include <langinfo.h>
 
 static void
@@ -56,9 +55,7 @@
     */
     if (strlen(data) == 0) {
         while ((frame = id3_tag_findframe(tag, frame_name, 0))) {
-#ifdef DEBUG
-            fprintf(stderr, "madplug: detachframe\n");
-#endif
+            AUDDBG("madplug: detachframe\n");
             id3_tag_detachframe(tag, frame);
         }
         return;
@@ -66,9 +63,7 @@
 
     frame = id3_tag_findframe(tag, frame_name, 0);
     if (!frame) {
-#ifdef DEBUG
-        printf("frame_new\n");
-#endif
+        AUDDBG("frame_new\n");
         frame = id3_frame_new(frame_name);
         id3_tag_attachframe(tag, frame);
     }
@@ -93,9 +88,7 @@
         g_free(ucs4);
 
         if(index == -1) { /* unknown genre. remove TCON frame. */
-#ifdef DEBUG
-            fprintf(stderr, "madplug: remove genre frame\n");
-#endif
+            AUDDBG("madplug: remove genre frame\n");
             id3_tag_detachframe(tag, frame);
         }
         else { /* meaningful genre */
@@ -132,9 +125,7 @@
         val = aud_tuple_get_int(tuple, fieldn, NULL);
         if(val > 0) {
             text2 = g_strdup_printf("%d", val);
-#ifdef DEBUG
-            fprintf(stderr, "madplug: updating field:\"%s\"=\"%s\", enc %s\n", field, text2, encoding);
-#endif
+            AUDDBG("madplug: updating field:\"%s\"=\"%s\", enc %s\n", field, text2, encoding);
             update_id3_frame(id3tag, field, text2, 0);
             g_free(text2);
         } else {
@@ -144,9 +135,7 @@
     } else if(aud_tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_STRING) {
         text = (char*)aud_tuple_get_string(tuple, fieldn, NULL);
         text2 = g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL);
-#ifdef DEBUG
-        fprintf(stderr, "madplug: updating field:\"%s\"=\"%s\", enc %s\n", field, text2, encoding);
-#endif
+        AUDDBG("madplug: updating field:\"%s\"=\"%s\", enc %s\n", field, text2, encoding);
         update_id3_frame(id3tag, field, text2, sjis);
         g_free(text2);
     }
@@ -164,9 +153,7 @@
     
     id3tag = id3_file_tag(id3file);
     if (!id3tag) {
-#ifdef DEBUG
-        fprintf(stderr, "no id3tag\n. append new tag.\n");
-#endif
+        AUDDBG("no id3tag\n. append new tag.\n");
         id3tag = id3_tag_new();
         id3_tag_clearframes(id3tag);
         id3tag->options |= ID3_TAG_OPTION_APPENDEDTAG | ID3_TAG_OPTION_ID3V1;
@@ -183,15 +170,11 @@
     update_id3_frame_from_tuple(id3tag, ID3_FRAME_GENRE, tuple, FIELD_GENRE, audmad_config.sjis);
 
     if(!id3_tag_findframe(id3tag, "TLEN", 0) && input_init(&songinfo, fd->uri, fd) && !songinfo.remote) {
-#ifdef DEBUG
-        fprintf(stderr, "update TLEN frame\n");
-#endif
+        AUDDBG("update TLEN frame\n");
         songinfo.fileinfo_request = FALSE; /* we don't need to read tuple again */
         input_get_info(&songinfo, FALSE);
         text = g_strdup_printf("%ld", mad_timer_count(songinfo.duration, MAD_UNITS_MILLISECONDS));
-#ifdef DEBUG
-        fprintf(stderr, "TLEN: \"%s\"\n", text);
-#endif
+        AUDDBG("TLEN: \"%s\"\n", text);
         update_id3_frame(id3tag, "TLEN", text, 0);
         g_free(text);
         input_term(&songinfo);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modplug/load_mid.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -0,0 +1,1126 @@
+/*
+ * This program is  free software; you can redistribute it  and modify it
+ * under the terms of the GNU  General Public License as published by the
+ * Free Software Foundation; either version 2  of the license or (at your
+ * option) any later version.
+ *
+ * Authors: Olivier Lapicque <olivierl@jps.net>
+*/
+
+//////////////////////////////////////////////
+// MIDI loader                              //
+//////////////////////////////////////////////
+#include "stdafx.h"
+#include "sndfile.h"
+
+#define MIDI_DRUMCHANNEL	10
+#define MIDI_MAXTRACKS		64
+
+UINT gnMidiImportSpeed = 3;
+UINT gnMidiPatternLen = 128;
+
+#pragma pack(1)
+
+typedef struct MIDIFILEHEADER
+{
+	CHAR id[4];		// "MThd" = 0x6468544D
+	DWORD len;		// 6
+	WORD w1;		// 1?
+	WORD wTrks;		// 2?
+	WORD wDivision;	// F0
+} MIDIFILEHEADER;
+
+
+typedef struct MIDITRACKHEADER
+{
+	CHAR id[4];	// "MTrk" = 0x6B72544D
+	DWORD len;
+} MIDITRACKHEADER;
+
+static LONG midivolumetolinear(UINT nMidiVolume)
+{
+	return (nMidiVolume * nMidiVolume << 16) / (127*127);
+}
+
+//////////////////////////////////////////////////////////////////////
+// Midi Loader Internal Structures
+
+#define CHNSTATE_NOTEOFFPENDING		0x0001
+
+// MOD Channel State description (current volume, panning, etc...)
+typedef struct MODCHANNELSTATE
+{
+	DWORD flags;	// Channel Flags
+	WORD idlecount;
+	WORD pitchsrc, pitchdest;	// Pitch Bend (current position/new position)
+	BYTE parent;	// Midi Channel parent
+	BYTE pan;		// Channel Panning			0-255
+	BYTE note;		// Note On # (0=available)
+} MODCHANNELSTATE;
+
+// MIDI Channel State (Midi Channels 0-15)
+typedef struct MIDICHANNELSTATE
+{
+	DWORD flags;		// Channel Flags
+	WORD pitchbend;		// Pitch Bend Amount (14-bits unsigned)
+	BYTE note_on[128];	// If note=on -> MOD channel # + 1 (0 if note=off)
+	BYTE program;		// Channel Midi Program
+	WORD bank;			// 0-16383
+	// -- Controllers --------- function ---------- CC# --- range  --- init (midi) ---
+	BYTE pan;			// Channel Panning			CC10	[0-255]		128 (64)
+	BYTE expression;	// Channel Expression		CC11	0-128		128	(127)
+	BYTE volume;		// Channel Volume			CC7		0-128		80	(100)
+	BYTE modulation;	// Modulation				CC1		0-127		0
+	BYTE pitchbendrange;// Pitch Bend Range								64
+} MIDICHANNELSTATE;
+
+typedef struct MIDITRACK
+{
+	LPCBYTE ptracks, ptrmax;
+	DWORD status;
+	LONG nexteventtime;
+} MIDITRACK;
+
+#pragma pack()
+
+
+
+LPCSTR szMidiGroupNames[17] =
+{
+	"Piano",
+	"Chromatic Percussion",
+	"Organ",
+	"Guitar",
+	"Bass",
+	"Strings",
+	"Ensemble",
+	"Brass",
+	"Reed",
+	"Pipe",
+	"Synth Lead",
+	"Synth Pad",
+	"Synth Effects",
+	"Ethnic",
+	"Percussive",
+	"Sound Effects",
+	"Percussions"
+};
+
+
+LPCSTR szMidiProgramNames[128] =
+{
+	// 1-8: Piano
+	"Acoustic Grand Piano",
+	"Bright Acoustic Piano",
+	"Electric Grand Piano",
+	"Honky-tonk Piano",
+	"Electric Piano 1",
+	"Electric Piano 2",
+	"Harpsichord",
+	"Clavi",
+	// 9-16: Chromatic Percussion
+	"Celesta",
+	"Glockenspiel",
+	"Music Box",
+	"Vibraphone",
+	"Marimba",
+	"Xylophone",
+	"Tubular Bells",
+	"Dulcimer",
+	// 17-24: Organ
+	"Drawbar Organ",
+	"Percussive Organ",
+	"Rock Organ",
+	"Church Organ",
+	"Reed Organ",
+	"Accordion",
+	"Harmonica",
+	"Tango Accordion",
+	// 25-32: Guitar
+	"Acoustic Guitar (nylon)",
+	"Acoustic Guitar (steel)",
+	"Electric Guitar (jazz)",
+	"Electric Guitar (clean)",
+	"Electric Guitar (muted)",
+	"Overdriven Guitar",
+	"Distortion Guitar",
+	"Guitar harmonics",
+	// 33-40   Bass
+	"Acoustic Bass",
+	"Electric Bass (finger)",
+	"Electric Bass (pick)",
+	"Fretless Bass",
+	"Slap Bass 1",
+	"Slap Bass 2",
+	"Synth Bass 1",
+	"Synth Bass 2",
+	// 41-48   Strings
+	"Violin",
+	"Viola",
+	"Cello",
+	"Contrabass",
+	"Tremolo Strings",
+	"Pizzicato Strings",
+	"Orchestral Harp",
+	"Timpani",
+	// 49-56   Ensemble
+	"String Ensemble 1",
+	"String Ensemble 2",
+	"SynthStrings 1",
+	"SynthStrings 2",
+	"Choir Aahs",
+	"Voice Oohs",
+	"Synth Voice",
+	"Orchestra Hit",
+	// 57-64   Brass
+	"Trumpet",
+	"Trombone",
+	"Tuba",
+	"Muted Trumpet",
+	"French Horn",
+	"Brass Section",
+	"SynthBrass 1",
+	"SynthBrass 2",
+	// 65-72   Reed
+	"Soprano Sax",
+	"Alto Sax",
+	"Tenor Sax",
+	"Baritone Sax",
+	"Oboe",
+	"English Horn",
+	"Bassoon",
+	"Clarinet",
+	// 73-80   Pipe
+	"Piccolo",
+	"Flute",
+	"Recorder",
+	"Pan Flute",
+	"Blown Bottle",
+	"Shakuhachi",
+	"Whistle",
+	"Ocarina",
+	// 81-88   Synth Lead
+	"Lead 1 (square)",
+	"Lead 2 (sawtooth)",
+	"Lead 3 (calliope)",
+	"Lead 4 (chiff)",
+	"Lead 5 (charang)",
+	"Lead 6 (voice)",
+	"Lead 7 (fifths)",
+	"Lead 8 (bass + lead)",
+	// 89-96   Synth Pad
+	"Pad 1 (new age)",
+	"Pad 2 (warm)",
+	"Pad 3 (polysynth)",
+	"Pad 4 (choir)",
+	"Pad 5 (bowed)",
+	"Pad 6 (metallic)",
+	"Pad 7 (halo)",
+	"Pad 8 (sweep)",
+	// 97-104  Synth Effects
+	"FX 1 (rain)",
+	"FX 2 (soundtrack)",
+	"FX 3 (crystal)",
+	"FX 4 (atmosphere)",
+	"FX 5 (brightness)",
+	"FX 6 (goblins)",
+	"FX 7 (echoes)",
+	"FX 8 (sci-fi)",
+	// 105-112 Ethnic
+	"Sitar",
+	"Banjo",
+	"Shamisen",
+	"Koto",
+	"Kalimba",
+	"Bag pipe",
+	"Fiddle",
+	"Shanai",
+	// 113-120 Percussive
+	"Tinkle Bell",
+	"Agogo",
+	"Steel Drums",
+	"Woodblock",
+	"Taiko Drum",
+	"Melodic Tom",
+	"Synth Drum",
+	"Reverse Cymbal",
+	// 121-128 Sound Effects
+	"Guitar Fret Noise",
+	"Breath Noise",
+	"Seashore",
+	"Bird Tweet",
+	"Telephone Ring",
+	"Helicopter",
+	"Applause",
+	"Gunshot"
+};
+
+
+// Notes 25-85
+LPCSTR szMidiPercussionNames[61] =
+{
+	"Seq Click",
+	"Brush Tap",
+	"Brush Swirl",
+	"Brush Slap",
+	"Brush Swirl W/Attack",
+	"Snare Roll",
+	"Castanet",
+	"Snare Lo",
+	"Sticks",
+	"Bass Drum Lo",
+	"Open Rim Shot",
+	"Acoustic Bass Drum",
+	"Bass Drum 1",
+	"Side Stick",
+	"Acoustic Snare",
+	"Hand Clap",
+	"Electric Snare",
+	"Low Floor Tom",
+	"Closed Hi Hat",
+	"High Floor Tom",
+	"Pedal Hi-Hat",
+	"Low Tom",
+	"Open Hi-Hat",
+	"Low-Mid Tom",
+	"Hi Mid Tom",
+	"Crash Cymbal 1",
+	"High Tom",
+	"Ride Cymbal 1",
+	"Chinese Cymbal",
+	"Ride Bell",
+	"Tambourine",
+	"Splash Cymbal",
+	"Cowbell",
+	"Crash Cymbal 2",
+	"Vibraslap",
+	"Ride Cymbal 2",
+	"Hi Bongo",
+	"Low Bongo",
+	"Mute Hi Conga",
+	"Open Hi Conga",
+	"Low Conga",
+	"High Timbale",
+	"Low Timbale",
+	"High Agogo",
+	"Low Agogo",
+	"Cabasa",
+	"Maracas",
+	"Short Whistle",
+	"Long Whistle",
+	"Short Guiro",
+	"Long Guiro",
+	"Claves",
+	"Hi Wood Block",
+	"Low Wood Block",
+	"Mute Cuica",
+	"Open Cuica",
+	"Mute Triangle",
+	"Open Triangle",
+	"Shaker",
+	"Jingle Bell",
+	"Bell Tree",
+};
+
+
+const WORD kMidiChannelPriority[16] =
+{
+	0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0,	0xFFE0, 0xFFC0, 0xFF80, 0xFF00,
+	0xFE00, 0xFDFF, 0xF800, 0xF000,	0xE000, 0xC000, 0x8000, 0x0000,
+};
+
+
+///////////////////////////////////////////////////////////////////////////
+// Helper functions
+
+static LONG getmidilong(LPCBYTE &p, LPCBYTE pmax)
+//----------------------------------------------------------
+{
+	DWORD n;
+	UINT a;
+
+	a = (p < pmax) ? *(p++) : 0;
+	n = 0;
+	while (a&0x80)
+	{
+		n = (n<<7)|(a&0x7F);
+		a = (p < pmax) ? *(p++) : 0;
+	}
+	return (n<<7)|(LONG)a;
+}
+
+
+// Returns MOD tempo and tick multiplier
+static int ConvertMidiTempo(int tempo_us, int *pTickMultiplier)
+//-------------------------------------------------------------
+{
+	int nBestModTempo = 120;
+	int nBestError = 1000000; // 1s
+	int nBestMultiplier = 1;
+	int nSpeed = gnMidiImportSpeed;
+	for (int nModTempo=110; nModTempo<=240; nModTempo++)
+	{
+		int tick_us = (2500000) / nModTempo;
+		int nFactor = (tick_us+tempo_us/2) / tempo_us;
+		if (!nFactor) nFactor = 1;
+		int nError = tick_us - tempo_us * nFactor;
+		if (nError < 0) nError = -nError;
+		if (nError < nBestError)
+		{
+			nBestError = nError;
+			nBestModTempo = nModTempo;
+			nBestMultiplier = nFactor;
+		}
+		if ((!nError) || ((nError<=1) && (nFactor==64))) break;
+	}
+	*pTickMultiplier = nBestMultiplier * nSpeed;
+	return nBestModTempo;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Maps a midi instrument - returns the instrument number in the file
+UINT CSoundFile::MapMidiInstrument(DWORD dwBankProgram, UINT nChannel, UINT nNote)
+//--------------------------------------------------------------------------------
+{
+	INSTRUMENTHEADER *penv;
+	UINT nProgram = dwBankProgram & 0x7F;
+	UINT nBank = dwBankProgram >> 7;
+
+	nNote &= 0x7F;
+	if (nNote >= 120) return 0;
+	for (UINT i=1; i<=m_nInstruments; i++) if (Headers[i])
+	{
+		INSTRUMENTHEADER *p = Headers[i];
+		// Drum Kit ?
+		if (nChannel == MIDI_DRUMCHANNEL)
+		{
+			if (nNote == p->nMidiDrumKey) return i;
+		} else
+		// Melodic Instrument
+		{
+			if (nProgram == p->nMidiProgram) return i;
+		}
+	}
+	if ((m_nInstruments + 1 >= MAX_INSTRUMENTS) || (m_nSamples + 1 >= MAX_SAMPLES)) return 0;
+	penv = new INSTRUMENTHEADER;
+	if (!penv) return 0;
+	memset(penv, 0, sizeof(INSTRUMENTHEADER));
+	m_nSamples++;
+	m_nInstruments++;
+	Headers[m_nInstruments] = penv;
+	penv->wMidiBank = nBank;
+	penv->nMidiProgram = nProgram;
+	penv->nMidiChannel = nChannel;
+	if (nChannel == MIDI_DRUMCHANNEL) penv->nMidiDrumKey = nNote;
+	penv->nGlobalVol = 128;
+	penv->nFadeOut = 1024;
+	penv->nPan = 128;
+	penv->nPPC = 5*12;
+	penv->nNNA = NNA_NOTEOFF;
+	penv->nDCT = (nChannel == MIDI_DRUMCHANNEL) ? DCT_SAMPLE : DCT_NOTE;
+	penv->nDNA = DNA_NOTEFADE;
+	for (UINT j=0; j<120; j++)
+	{
+		int mapnote = j+1;
+		if (nChannel == MIDI_DRUMCHANNEL)
+		{
+			mapnote = 61;
+			/*mapnote = 61 + j - nNote;
+			if (mapnote < 1) mapnote = 1;
+			if (mapnote > 120) mapnote = 120;*/
+		}
+		penv->Keyboard[j] = m_nSamples;
+		penv->NoteMap[j] = (BYTE)mapnote;
+	}
+	penv->dwFlags |= ENV_VOLUME;
+	if (nChannel != MIDI_DRUMCHANNEL) penv->dwFlags |= ENV_VOLSUSTAIN;
+	penv->VolEnv.nNodes=4;
+	penv->VolEnv.Ticks[0]=0;
+	penv->VolEnv.Values[0] = 64;
+	penv->VolEnv.Ticks[1] = 10;
+	penv->VolEnv.Values[1] = 64;
+	penv->VolEnv.Ticks[2] = 15;
+	penv->VolEnv.Values[2] = 48;
+	penv->VolEnv.Ticks[3] = 20;
+	penv->VolEnv.Values[3] = 0;
+	penv->VolEnv.nSustainStart=1;
+	penv->VolEnv.nSustainEnd=1;
+	// Sample
+	Ins[m_nSamples].nPan = 128;
+	Ins[m_nSamples].nVolume = 256;
+	Ins[m_nSamples].nGlobalVol = 64;
+	if (nChannel != MIDI_DRUMCHANNEL)
+	{
+		// GM Midi Name
+		strcpy((char*)penv->name, (char*)szMidiProgramNames[nProgram]);
+		strcpy((char*)m_szNames[m_nSamples], (char*)szMidiProgramNames[nProgram]);
+	} else
+	{
+		strcpy((char*)penv->name, "Percussions");
+		if ((nNote >= 24) && (nNote <= 84))
+			strcpy((char*)m_szNames[m_nSamples], (char*)szMidiPercussionNames[nNote-24]);
+		else
+			strcpy((char*)m_szNames[m_nSamples], "Percussions");
+	}
+	return m_nInstruments;
+}
+
+
+/////////////////////////////////////////////////////////////////
+// Loader Status
+#define MIDIGLOBAL_SONGENDED		0x0001
+#define MIDIGLOBAL_FROZEN			0x0002
+#define MIDIGLOBAL_UPDATETEMPO		0x0004
+#define MIDIGLOBAL_UPDATEMASTERVOL	0x0008
+// Midi Globals
+#define MIDIGLOBAL_GMSYSTEMON		0x0100
+#define MIDIGLOBAL_XGSYSTEMON		0x0200
+
+
+BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
+//---------------------------------------------------------------
+{
+	const MIDIFILEHEADER *pmfh = (const MIDIFILEHEADER *)lpStream;
+	const MIDITRACKHEADER *pmth;
+	MODCHANNELSTATE chnstate[MAX_BASECHANNELS];
+	MIDICHANNELSTATE midichstate[16];
+	MIDITRACK miditracks[MIDI_MAXTRACKS];
+	DWORD dwMemPos, dwGlobalFlags, tracks, tempo;
+	UINT row, pat, midimastervol;
+	short int division;
+	int midi_clock, nTempoUsec, nPPQN, nTickMultiplier;
+
+	// Fix import parameters
+	if (gnMidiImportSpeed < 2) gnMidiImportSpeed = 2;
+	if (gnMidiImportSpeed > 6) gnMidiImportSpeed = 6;
+	if (gnMidiPatternLen < 64) gnMidiPatternLen = 64;
+	if (gnMidiPatternLen > 256) gnMidiPatternLen = 256;
+	// Detect RMI files
+	if ((dwMemLength > 12)
+	 && (memcmp(lpStream, "RIFF",4) == 0)
+	 && (memcmp(lpStream, "RMID",4) == 0))
+	{
+		lpStream += 12;
+		dwMemLength -= 12;
+		while (dwMemLength > 8)
+		{
+			char *id = (char*)lpStream;
+			DWORD len = *(DWORD *)(lpStream+4);
+			lpStream += 8;
+			dwMemLength -= 8;
+			if ((memcmp(id, "data",4) == 0) && (len < dwMemLength))
+			{
+				dwMemLength = len;
+				pmfh = (const MIDIFILEHEADER *)lpStream;
+				break;
+			}
+			if (len >= dwMemLength) return FALSE;
+			lpStream += len;
+			dwMemLength -= len;
+		}
+	}
+	// MIDI File Header
+	if ((dwMemLength < sizeof(MIDIFILEHEADER)+8) || (memcmp(pmfh->id, "MThd",4) != 0)) return FALSE;
+	dwMemPos = 8 + bswapBE32(pmfh->len);
+	if (dwMemPos >= dwMemLength - 8) return FALSE;
+	pmth = (MIDITRACKHEADER *)(lpStream+dwMemPos);
+	tracks = bswapBE16(pmfh->wTrks);
+	if ((!tracks) || (memcmp(pmth->id, "MTrk", 4) != 0)) return FALSE;
+	if (tracks > MIDI_MAXTRACKS) tracks = MIDI_MAXTRACKS;
+	// Reading File...
+	m_nType = MOD_TYPE_MID;
+	m_nChannels = 32;
+	m_nSamples = 0;
+	m_nInstruments = 0;
+	m_dwSongFlags |= (SONG_LINEARSLIDES | SONG_INSTRUMENTMODE);
+	m_szNames[0][0] = 0;
+	// MIDI->MOD Tempo Conversion
+	division = bswapBE16(pmfh->wDivision);
+	if (division < 0)
+	{
+		int nFrames = -(division>>8);
+		int nSubFrames = (division & 0xff);
+		nPPQN = nFrames * nSubFrames / 2;
+		if (!nPPQN) nPPQN = 1;
+	} else
+	{
+		nPPQN = (division) ? division : 96;
+	}
+	nTempoUsec = 500000 / nPPQN;
+	tempo = ConvertMidiTempo(nTempoUsec, &nTickMultiplier);
+	m_nDefaultTempo = tempo;
+	m_nDefaultSpeed = gnMidiImportSpeed;
+	m_nDefaultGlobalVolume = 256;
+	midimastervol = m_nDefaultGlobalVolume;
+	
+	// Initializing 
+	memset(Order, 0xFF, sizeof(Order));
+	memset(chnstate, 0, sizeof(chnstate));
+	memset(miditracks, 0, sizeof(miditracks));
+	memset(midichstate, 0, sizeof(midichstate));
+	// Initializing Patterns
+	Order[0] = 0;
+	for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++) PatternSize[ipat] = gnMidiPatternLen;
+	// Initializing Channels
+	for (UINT ics=0; ics<MAX_BASECHANNELS; ics++)
+	{
+		// Channel settings
+		ChnSettings[ics].nPan = 128;
+		ChnSettings[ics].nVolume = 64;
+		ChnSettings[ics].dwFlags = 0;
+		// Channels state
+		chnstate[ics].pan = 128;
+		chnstate[ics].pitchsrc = 0x2000;
+		chnstate[ics].pitchdest = 0x2000;
+	}
+	// Initializing Track Pointers
+	for (UINT itrk=0; itrk<tracks; itrk++)
+	{
+		miditracks[itrk].nexteventtime = -1;
+		miditracks[itrk].status = 0x2F;
+		pmth = (MIDITRACKHEADER *)(lpStream+dwMemPos);
+		if (dwMemPos + 8 >= dwMemLength) break;
+		DWORD len = bswapBE32(pmth->len);
+		if ((memcmp(pmth->id, "MTrk", 4) == 0) && (dwMemPos + 8 + len <= dwMemLength))
+		{
+			// Initializing midi tracks
+			miditracks[itrk].ptracks = lpStream+dwMemPos+8;
+			miditracks[itrk].ptrmax = miditracks[itrk].ptracks + len;
+			miditracks[itrk].nexteventtime = getmidilong(miditracks[itrk].ptracks, miditracks[itrk].ptrmax);
+		}
+		dwMemPos += 8 + len;
+	}
+	// Initializing midi channels state
+	for (UINT imidi=0; imidi<16; imidi++)
+	{
+		midichstate[imidi].pan = 128;			// middle
+		midichstate[imidi].expression = 128;	// no attenuation
+		midichstate[imidi].volume = 80;			// GM specs defaults to 100
+		midichstate[imidi].pitchbend = 0x2000;	// Pitch Bend Amount
+		midichstate[imidi].pitchbendrange = 64;	// Pitch Bend Range: +/- 2 semitones
+	}
+	////////////////////////////////////////////////////////////////////////////
+	// Main Midi Sequencer Loop
+	pat = 0;
+	row = 0;
+	midi_clock = 0;
+	dwGlobalFlags = MIDIGLOBAL_UPDATETEMPO | MIDIGLOBAL_FROZEN;
+	do
+	{
+		// Allocate current pattern if not allocated yet
+		if (!Patterns[pat])
+		{
+			Patterns[pat] = AllocatePattern(PatternSize[pat], m_nChannels);
+			if (!Patterns[pat]) break;
+		}
+		dwGlobalFlags |= MIDIGLOBAL_SONGENDED;
+		MODCOMMAND *m = Patterns[pat] + row * m_nChannels;
+		// Parse Tracks
+		for (UINT trk=0; trk<tracks; trk++) if (miditracks[trk].ptracks)
+		{
+			MIDITRACK *ptrk = &miditracks[trk];
+			dwGlobalFlags &= ~MIDIGLOBAL_SONGENDED;
+			while ((ptrk->ptracks) && (ptrk->nexteventtime >= 0) && (midi_clock+(nTickMultiplier>>2) >= ptrk->nexteventtime))
+			{
+				if (ptrk->ptracks[0] & 0x80) ptrk->status = *(ptrk->ptracks++);
+				switch(ptrk->status)
+				{
+				/////////////////////////////////////////////////////////////////////
+				// End Of Track
+				case 0x2F:
+				// End Of Song
+				case 0xFC:
+					ptrk->ptracks = NULL;
+					break;
+
+				/////////////////////////////////////////////////////////////////////
+				// SYSEX messages
+				case 0xF0:
+				case 0xF7:
+					{
+						LONG len = getmidilong(ptrk->ptracks, ptrk->ptrmax);
+						if ((len > 1) && (ptrk->ptracks + len <ptrk->ptrmax) && (ptrk->ptracks[len-1] == 0xF7))
+						{
+							DWORD dwSysEx1 = 0, dwSysEx2 = 0;
+							if (len >= 4) dwSysEx1 = (*((DWORD *)(ptrk->ptracks))) & 0x7F7F7F7F;
+							if (len >= 8) dwSysEx2 = (*((DWORD *)(ptrk->ptracks+4))) & 0x7F7F7F7F;
+							// GM System On
+							if ((len == 5) && (dwSysEx1 == 0x01097F7E))
+							{
+								dwGlobalFlags |= MIDIGLOBAL_GMSYSTEMON;
+							} else
+							// XG System On
+							if ((len == 8) && ((dwSysEx1 & 0xFFFFF0FF) == 0x004c1043) && (dwSysEx2 == 0x77007e00))
+							{
+								dwGlobalFlags |= MIDIGLOBAL_XGSYSTEMON;
+							} else
+							// Midi Master Volume
+							if ((len == 7) && (dwSysEx1 == 0x01047F7F))
+							{
+								midimastervol = midivolumetolinear(ptrk->ptracks[5] & 0x7F) >> 8;
+								if (midimastervol < 16) midimastervol = 16;
+								dwGlobalFlags |= MIDIGLOBAL_UPDATEMASTERVOL;
+							}
+						}
+						ptrk->ptracks += len;
+					}
+					break;
+				
+				//////////////////////////////////////////////////////////////////////
+				// META-events: FF.code.len.data[len]
+				case 0xFF:
+					{
+						UINT i = *(ptrk->ptracks++);
+						LONG len = getmidilong(ptrk->ptracks, ptrk->ptrmax);
+						if (ptrk->ptracks+len > ptrk->ptrmax)
+						{
+							// EOF
+							ptrk->ptracks = NULL;
+						} else
+						switch(i)
+						{
+						// FF.01 [text]: Song Information
+						case 0x01:
+							if (!len) break;
+							if ((len < 32) && (!m_szNames[0][0]))
+							{
+								memcpy(m_szNames[0], ptrk->ptracks, len);
+								m_szNames[0][len] = 0;
+							} else
+							if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F))
+							{
+								m_lpszSongComments = new char [len+1];
+								if (m_lpszSongComments)
+								{
+									memcpy(m_lpszSongComments, ptrk->ptracks, len);
+									m_lpszSongComments[len] = 0;
+								}
+							}
+							break;
+						// FF.02 [text]: Song Copyright
+						case 0x02:
+							if (!len) break;
+							if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F) && (len > 7))
+							{
+								m_lpszSongComments = new char [len+1];
+								if (m_lpszSongComments)
+								{
+									memcpy(m_lpszSongComments, ptrk->ptracks, len);
+									m_lpszSongComments[len] = 0;
+								}
+							}
+							break;
+						// FF.03: Sequence Name
+						case 0x03:
+						// FF.06: Sequence Text (->Pattern names)
+						case 0x06:
+							if ((len > 1) && (!trk))
+							{
+								UINT k = (len < 32) ? len : 31;
+								CHAR s[32];
+								memcpy(s, ptrk->ptracks, k);
+								s[k] = 0;
+								if ((!strnicmp((char*)s, "Copyri", 6)) || (!s[0])) break;
+								if (i == 0x03)
+								{
+									if (!m_szNames[0][0]) strcpy((char*)m_szNames[0], (char*)s);
+								}
+							}
+							break;
+						// FF.07: Cue Point (marker)
+						// FF.20: Channel Prefix
+						// FF.2F: End of Track
+						case 0x2F:
+							ptrk->status = 0x2F;
+							ptrk->ptracks = NULL;
+							break;
+						// FF.51 [tttttt]: Set Tempo
+						case 0x51:
+							{
+								LONG l = ptrk->ptracks[0];
+								l = (l << 8) | ptrk->ptracks[1];
+								l = (l << 8) | ptrk->ptracks[2];
+								if (l <= 0) break;
+								nTempoUsec = l / nPPQN;
+								if (nTempoUsec < 100) nTempoUsec = 100;
+								tempo = ConvertMidiTempo(nTempoUsec, &nTickMultiplier);
+								dwGlobalFlags |= MIDIGLOBAL_UPDATETEMPO;
+							}
+							break;
+						// FF.58: Time Signature
+						// FF.7F: Sequencer-Specific
+						}
+						if (ptrk->ptracks) ptrk->ptracks += len;
+					}
+					break;
+
+				//////////////////////////////////////////////////////////////////////////
+				// Regular Voice Events
+				default:
+				{
+					UINT midich = (ptrk->status & 0x0F)+1;
+					UINT midist = ptrk->status & 0xF0;
+					MIDICHANNELSTATE *pmidich = &midichstate[midich-1];
+					UINT note, velocity;
+
+					switch(midist)
+					{
+					//////////////////////////////////
+					// Note Off:	80.note.velocity
+					case 0x80:
+					// Note On:		90.note.velocity
+					case 0x90:
+						note = ptrk->ptracks[0] & 0x7F;
+						velocity = (midist == 0x90) ? (ptrk->ptracks[1] & 0x7F) : 0;
+						ptrk->ptracks += 2;
+						// Note On: 90.note.velocity
+						if (velocity)
+						{
+							// Start counting rows
+							dwGlobalFlags &= ~MIDIGLOBAL_FROZEN;
+							// if the note is already playing, we reuse this channel
+							UINT nchn = pmidich->note_on[note];
+							if ((nchn) && (chnstate[nchn-1].parent != midich)) nchn = 0;
+							// or else, we look for an available child channel
+							if (!nchn)
+							{
+								for (UINT i=0; i<m_nChannels; i++) if (chnstate[i].parent == midich)
+								{
+									if ((!chnstate[i].note) && ((!m[i].note) || (m[i].note & 0x80)))
+									{
+										// found an available channel
+										nchn = i+1;
+										break;
+									}
+								}
+							}
+							// still nothing? in this case, we try to allocate a new mod channel
+							if (!nchn)
+							{
+								for (UINT i=0; i<m_nChannels; i++) if (!chnstate[i].parent)
+								{
+									nchn = i+1;
+									chnstate[i].parent = midich;
+									break;
+								}
+							}
+							// still not? we have to steal a voice from another channel
+							// We found our channel: let's do the note on
+							if (nchn)
+							{
+								pmidich->note_on[note] = nchn;
+								nchn--;
+								chnstate[nchn].pitchsrc = pmidich->pitchbend;
+								chnstate[nchn].pitchdest = pmidich->pitchbend;
+								chnstate[nchn].flags &= ~CHNSTATE_NOTEOFFPENDING;
+								chnstate[nchn].idlecount = 0;
+								chnstate[nchn].note = note+1;
+								int realnote = note;
+								if (midich != 10)
+								{
+									realnote += (((int)pmidich->pitchbend - 0x2000) * pmidich->pitchbendrange) / (0x2000*32);
+									if (realnote < 0) realnote = 0;
+									if (realnote > 119) realnote = 119;
+								}
+								m[nchn].note = realnote+1;
+								m[nchn].instr = MapMidiInstrument(pmidich->program + ((UINT)pmidich->bank << 7), midich, note);
+								m[nchn].volcmd = VOLCMD_VOLUME;
+								LONG vol = midivolumetolinear(velocity) >> 8;
+								vol = (vol * (LONG)pmidich->volume * (LONG)pmidich->expression) >> 13;
+								if (vol > 256) vol = 256;
+								if (vol < 4) vol = 4;
+								m[nchn].vol = (BYTE)(vol>>2);
+								// Channel Panning
+								if ((!m[nchn].command) && (pmidich->pan != chnstate[nchn].pan))
+								{
+									chnstate[nchn].pan = pmidich->pan;
+									m[nchn].param = pmidich->pan;
+									m[nchn].command = CMD_PANNING8;
+								}
+							}
+						} else
+						// Note Off; 90.note.00
+						if (!(dwGlobalFlags & MIDIGLOBAL_FROZEN))
+						{
+							UINT nchn = pmidich->note_on[note];
+							if (nchn)
+							{
+								nchn--;
+								chnstate[nchn].flags |= CHNSTATE_NOTEOFFPENDING;
+								chnstate[nchn].note = 0;
+								pmidich->note_on[note] = 0;
+							} else
+							{
+								for (UINT i=0; i<m_nChannels; i++)
+								{
+									if ((chnstate[i].parent == midich) && (chnstate[i].note == note+1))
+									{
+										chnstate[i].note = 0;
+										chnstate[i].flags |= CHNSTATE_NOTEOFFPENDING;
+									}
+								}
+							}
+						}
+						break;
+
+					///////////////////////////////////
+					// A0.xx.yy: Aftertouch
+					case 0xA0:
+						{
+							ptrk->ptracks += 2;
+						}
+						break;
+
+					///////////////////////////////////
+					// B0: Control Change
+					case 0xB0:
+						{
+							UINT controller = ptrk->ptracks[0];
+							UINT value = ptrk->ptracks[1] & 0x7F;
+							ptrk->ptracks += 2;
+							switch(controller)
+							{
+							// Bn.00.xx: Bank Select MSB (GS)
+							case 0x00:
+								pmidich->bank &= 0x7F;
+								pmidich->bank |= (value << 7);
+								break;
+							// Bn.01.xx: Modulation Depth
+							case 0x01:
+								pmidich->pitchbendrange = value;
+								break;
+							// Bn.07.xx: Volume
+							case 0x07:
+								pmidich->volume = (BYTE)(midivolumetolinear(value) >> 9);
+								break;
+							// Bn.0B.xx: Expression
+							case 0x0B:
+								pmidich->expression = (BYTE)(midivolumetolinear(value) >> 9);
+								break;
+							// Bn.0A.xx: Pan
+							case 0x0A:
+								pmidich->pan = value * 2;
+								break;
+							// Bn.20.xx: Bank Select LSB (GS)
+							case 0x20:
+								pmidich->bank &= (0x7F << 7);
+								pmidich->bank |= value;
+								break;
+							// Bn.79.00: Reset All Controllers (GM)
+							case 0x79:
+								pmidich->modulation = 0;
+								pmidich->expression = 128;
+								pmidich->pitchbend = 0x2000;
+								pmidich->pitchbendrange = 64;
+								// Should also reset pedals (40h-43h), NRP, RPN, aftertouch
+								break;
+							// Bn.78.00: All Sound Off (GS)
+							// Bn.7B.00: All Notes Off (GM)
+							case 0x78:
+							case 0x7B:
+								if (value == 0x00)
+								{
+									// All Notes Off
+									for (UINT k=0; k<m_nChannels; k++)
+									{
+										if (chnstate[k].note)
+										{
+											chnstate[k].flags |= CHNSTATE_NOTEOFFPENDING;
+											chnstate[k].note = 0;
+										}
+									}
+								}
+								break;
+							////////////////////////////////////
+							// Controller List
+							//
+							// Bn.02.xx: Breath Control
+							// Bn.04.xx: Foot Pedal
+							// Bn.05.xx: Portamento Time (Glissando Time)
+							// Bn.06.xx: Data Entry MSB
+							// Bn.08.xx: Balance
+							// Bn.10-13.xx: GP Control #1-#4
+							// Bn.20-3F.xx: Data LSB for controllers 0-31
+							// Bn.26.xx: Data Entry LSB
+							// Bn.40.xx: Hold Pedal #1
+							// Bn.41.xx: Portamento (GS)
+							// Bn.42.xx: Sostenuto (GS)
+							// Bn.43.xx: Soft Pedal (GS)
+							// Bn.44.xx: Legato Pedal
+							// Bn.45.xx: Hold Pedal #2
+							// Bn.46.xx: Sound Variation
+							// Bn.47.xx: Sound Timbre
+							// Bn.48.xx: Sound Release Time
+							// Bn.49.xx: Sound Attack Time
+							// Bn.4A.xx: Sound Brightness
+							// Bn.4B-4F.xx: Sound Control #6-#10
+							// Bn.50-53.xx: GP Control #5-#8
+							// Bn.54.xx: Portamento Control (GS)
+							// Bn.5B.xx: Reverb Level (GS)
+							// Bn.5C.xx: Tremolo Depth
+							// Bn.5D.xx: Chorus Level (GS)
+							// Bn.5E.xx: Celeste Depth
+							// Bn.5F.xx: Phaser Depth
+							// Bn.60.xx: Data Increment
+							// Bn.61.xx: Data Decrement
+							// Bn.62.xx: Non-RPN Parameter LSB (GS)
+							// Bn.63.xx: Non-RPN Parameter MSB (GS)
+							// Bn.64.xx: RPN Parameter LSB (GM)
+							// Bn.65.xx: RPN Parameter MSB (GM)
+							// Bn.7A.00: Local On/Off
+							// Bn.7C.00: Omni Mode Off
+							// Bn.7D.00: Omni Mode On
+							// Bn.7E.mm: Mono Mode On
+							// Bn.7F.00: Poly Mode On
+							}
+						}
+						break;
+
+					////////////////////////////////
+					// C0.pp: Program Change
+					case 0xC0:
+						{
+							pmidich->program = ptrk->ptracks[0] & 0x7F;
+							ptrk->ptracks++;
+						}
+						break;
+
+					////////////////////////////////
+					// D0: Channel Aftertouch (Polyphonic Key Pressure)
+					case 0xD0:
+						{
+							ptrk->ptracks++;
+						}
+						break;
+					
+					////////////////////////////////
+					// E0: Pitch Bend
+					case 0xE0:
+						{
+							pmidich->pitchbend = (WORD)(((UINT)ptrk->ptracks[1] << 7) + (ptrk->ptracks[0] & 0x7F));
+							for (UINT i=0; i<128; i++) if (pmidich->note_on[i])
+							{
+								UINT nchn = pmidich->note_on[i]-1;
+								if (chnstate[nchn].parent == midich)
+								{
+									chnstate[nchn].pitchdest = pmidich->pitchbend;
+								}
+							}
+							ptrk->ptracks+=2;
+						}
+						break;
+
+					//////////////////////////////////////
+					// F0 & Unsupported commands: skip it
+					default:
+						ptrk->ptracks++;
+					}
+				}} // switch+default
+				// Process to next event
+				if (ptrk->ptracks)
+				{
+					ptrk->nexteventtime += getmidilong(ptrk->ptracks, ptrk->ptrmax);
+				}
+				if (ptrk->ptracks >= ptrk->ptrmax) ptrk->ptracks = NULL;
+			}
+			// End reached?
+			if (ptrk->ptracks >= ptrk->ptrmax) ptrk->ptracks = NULL;
+		}
+
+		////////////////////////////////////////////////////////////////////
+		// Move to next row
+		if (!(dwGlobalFlags & MIDIGLOBAL_FROZEN))
+		{
+			// Check MOD channels status
+			for (UINT ichn=0; ichn<m_nChannels; ichn++)
+			{
+				// Pending Global Effects ?
+				if (!m[ichn].command)
+				{
+					if ((chnstate[ichn].pitchsrc != chnstate[ichn].pitchdest) && (chnstate[ichn].parent))
+					{
+						int newpitch = chnstate[ichn].pitchdest;
+						int pitchbendrange = midichstate[chnstate[ichn].parent-1].pitchbendrange;
+						// +/- 256 for +/- pitch bend range
+						int slideamount = (newpitch - (int)chnstate[ichn].pitchsrc) / (int)32;
+						if (slideamount)
+						{
+							const int ppdiv = (16 * 128 * (gnMidiImportSpeed-1));
+							newpitch = (int)chnstate[ichn].pitchsrc + slideamount;
+							if (slideamount < 0)
+							{
+								int param = (-slideamount * pitchbendrange + ppdiv/2) / ppdiv;
+								if (param >= 0x80) param = 0x80;
+								if (param > 0)
+								{
+									m[ichn].param = (BYTE)param;
+									m[ichn].command = CMD_PORTAMENTODOWN;
+								}
+							} else
+							{
+								int param = (slideamount * pitchbendrange + ppdiv/2) / ppdiv;
+								if (param >= 0x80) param = 0x80;
+								if (param > 0)
+								{
+									m[ichn].param = (BYTE)param;
+									m[ichn].command = CMD_PORTAMENTOUP;
+								}
+							}
+						}
+						chnstate[ichn].pitchsrc = (WORD)newpitch;
+
+					} else
+					if (dwGlobalFlags & MIDIGLOBAL_UPDATETEMPO)
+					{
+						m[ichn].command = CMD_TEMPO;
+						m[ichn].param = (BYTE)tempo;
+						dwGlobalFlags &= ~MIDIGLOBAL_UPDATETEMPO;
+					} else
+					if (dwGlobalFlags & MIDIGLOBAL_UPDATEMASTERVOL)
+					{
+						m[ichn].command = CMD_GLOBALVOLUME;
+						m[ichn].param = midimastervol >> 1; // 0-128
+						dwGlobalFlags &= ~MIDIGLOBAL_UPDATEMASTERVOL;
+					}
+				}
+				// Check pending noteoff events for m[ichn]
+				if (!m[ichn].note)
+				{
+					if (chnstate[ichn].flags & CHNSTATE_NOTEOFFPENDING)
+					{
+						chnstate[ichn].flags &= ~CHNSTATE_NOTEOFFPENDING;
+						m[ichn].note = 0xFF;
+					}
+					// Check State of channel
+					chnstate[ichn].idlecount++;
+					if ((chnstate[ichn].note) && (chnstate[ichn].idlecount >= 50))
+					{
+						chnstate[ichn].note = 0;
+						m[ichn].note = 0xFF;	// only if not drum channel ?
+					} else
+					if (chnstate[ichn].idlecount >= 500) // 20secs of inactivity
+					{
+						chnstate[ichn].idlecount = 0;
+						chnstate[ichn].parent = 0;
+					}
+				}
+			}
+
+			if ((++row) >= PatternSize[pat])
+			{
+				pat++;
+				if (pat >= MAX_PATTERNS-1) break;
+				Order[pat] = pat;
+				Order[pat+1] = 0xFF;
+				row = 0;
+			}
+		}
+
+		// Increase midi clock
+		midi_clock += nTickMultiplier;
+	} while (!(dwGlobalFlags & MIDIGLOBAL_SONGENDED));
+	return TRUE;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modplug/snd_eq.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -0,0 +1,228 @@
+/*
+ * This program is  free software; you can redistribute it  and modify it
+ * under the terms of the GNU  General Public License as published by the
+ * Free Software Foundation; either version 2  of the license or (at your
+ * option) any later version.
+ *
+ * Authors: Olivier Lapicque <olivierl@jps.net>
+ *
+ * Name                Date             Description
+ * 
+ * Olivier Lapicque    --/--/--         Creation
+ * Trevor Nunes        26/01/04         conditional compilation for AMD,MMX calls
+ *
+*/
+#include "stdafx.h"
+#include "sndfile.h"
+#include <math.h>
+
+
+#define EQ_BANDWIDTH	2.0
+#define EQ_ZERO			0.000001
+#define REAL			float
+
+extern REAL MixFloatBuffer[];
+
+extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount);
+extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
+extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount);
+extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount);
+
+typedef struct _EQBANDSTRUCT
+{
+	REAL a0, a1, a2, b1, b2;
+	REAL x1, x2, y1, y2;
+	REAL Gain, CenterFrequency;
+	BOOL bEnable;
+} EQBANDSTRUCT, *PEQBANDSTRUCT;
+
+UINT gEqLinearToDB[33] =
+{
+	16, 19, 22, 25, 28, 31, 34, 37,
+	40, 43, 46, 49, 52, 55, 58, 61,
+	64, 76, 88, 100, 112, 124, 136, 148,
+	160, 172, 184, 196, 208, 220, 232, 244, 256
+};
+
+
+//static REAL f2ic = (REAL)(1 << 28);
+//static REAL i2fc = (REAL)(1.0 / (1 << 28));
+
+static EQBANDSTRUCT gEQ[MAX_EQ_BANDS*2] =
+{
+	// Default: Flat EQ
+	{0,0,0,0,0, 0,0,0,0, 1,   120, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,   600, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,  1200, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,  3000, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,  6000, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1, 10000, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,   120, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,   600, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,  1200, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,  3000, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1,  6000, FALSE},
+	{0,0,0,0,0, 0,0,0,0, 1, 10000, FALSE},
+};
+
+void EQFilter(EQBANDSTRUCT *pbs, REAL *pbuffer, UINT nCount)
+//----------------------------------------------------------
+{
+	for (UINT i=0; i<nCount; i++)
+	{
+		REAL x = pbuffer[i];
+		REAL y = pbs->a1 * pbs->x1 + pbs->a2 * pbs->x2 + pbs->a0 * x + pbs->b1 * pbs->y1 + pbs->b2 * pbs->y2;
+		pbs->x2 = pbs->x1;
+		pbs->y2 = pbs->y1;
+		pbs->x1 = x;
+		pbuffer[i] = y;
+		pbs->y1 = y;
+	}
+}
+
+void CSoundFile::EQMono(int *pbuffer, UINT nCount)
+//------------------------------------------------
+{
+	MonoMixToFloat(pbuffer, MixFloatBuffer, nCount);
+	for (UINT b=0; b<MAX_EQ_BANDS; b++)
+	{
+		if ((gEQ[b].bEnable) && (gEQ[b].Gain != 1.0f))
+			EQFilter(&gEQ[b], MixFloatBuffer, nCount);
+	}
+	FloatToMonoMix(MixFloatBuffer, pbuffer, nCount);
+}
+
+void CSoundFile::EQStereo(int *pbuffer, UINT nCount)
+//--------------------------------------------------
+{
+	StereoMixToFloat(pbuffer, MixFloatBuffer, MixFloatBuffer+MIXBUFFERSIZE, nCount);
+		
+	for (UINT bl=0; bl<MAX_EQ_BANDS; bl++)
+	{
+		if ((gEQ[bl].bEnable) && (gEQ[bl].Gain != 1.0f))
+			EQFilter(&gEQ[bl], MixFloatBuffer, nCount);
+	}
+	for (UINT br=MAX_EQ_BANDS; br<MAX_EQ_BANDS*2; br++)
+	{
+		if ((gEQ[br].bEnable) && (gEQ[br].Gain != 1.0f))
+			EQFilter(&gEQ[br], MixFloatBuffer+MIXBUFFERSIZE, nCount);
+	}
+
+	FloatToStereoMix(MixFloatBuffer, MixFloatBuffer+MIXBUFFERSIZE, pbuffer, nCount);
+
+}
+
+void CSoundFile::InitializeEQ(BOOL bReset)
+//----------------------------------------
+{
+	REAL fMixingFreq = (REAL)gdwMixingFreq;
+	// Gain = 0.5 (-6dB) .. 2 (+6dB)
+	for (UINT band=0; band<MAX_EQ_BANDS*2; band++) if (gEQ[band].bEnable)
+	{
+		REAL k, k2, r, f;
+		REAL v0, v1;
+		BOOL b = bReset;
+
+		f = gEQ[band].CenterFrequency / fMixingFreq;
+		if (f > 0.45f) gEQ[band].Gain = 1;
+		// if (f > 0.25) f = 0.25;
+		// k = tan(PI*f);
+		k = f * 3.141592654f;
+		k = k + k*f;
+//		if (k > (REAL)0.707) k = (REAL)0.707;
+		k2 = k*k;
+		v0 = gEQ[band].Gain;
+		v1 = 1;
+		if (gEQ[band].Gain < 1.0)
+		{
+			v0 *= (0.5f/EQ_BANDWIDTH);
+			v1 *= (0.5f/EQ_BANDWIDTH);
+		} else
+		{
+			v0 *= (1.0f/EQ_BANDWIDTH);
+			v1 *= (1.0f/EQ_BANDWIDTH);
+		}
+		r = (1 + v0*k + k2) / (1 + v1*k + k2);
+		if (r != gEQ[band].a0)
+		{
+			gEQ[band].a0 = r;
+			b = TRUE;
+		}
+		r = 2 * (k2 - 1) / (1 + v1*k + k2);
+		if (r != gEQ[band].a1)
+		{
+			gEQ[band].a1 = r;
+			b = TRUE;
+		}
+		r = (1 - v0*k + k2) / (1 + v1*k + k2);
+		if (r != gEQ[band].a2)
+		{
+			gEQ[band].a2 = r;
+			b = TRUE;
+		}
+		r = - 2 * (k2 - 1) / (1 + v1*k + k2);
+		if (r != gEQ[band].b1)
+		{
+			gEQ[band].b1 = r;
+			b = TRUE;
+		}
+		r = - (1 - v1*k + k2) / (1 + v1*k + k2);
+		if (r != gEQ[band].b2)
+		{
+			gEQ[band].b2 = r;
+			b = TRUE;
+		}
+		if (b)
+		{
+			gEQ[band].x1 = 0;
+			gEQ[band].x2 = 0;
+			gEQ[band].y1 = 0;
+			gEQ[band].y2 = 0;
+		}
+	} else
+	{
+		gEQ[band].a0 = 0;
+		gEQ[band].a1 = 0;
+		gEQ[band].a2 = 0;
+		gEQ[band].b1 = 0;
+		gEQ[band].b2 = 0;
+		gEQ[band].x1 = 0;
+		gEQ[band].x2 = 0;
+		gEQ[band].y1 = 0;
+		gEQ[band].y2 = 0;
+	}
+}
+
+
+void CSoundFile::SetEQGains(const UINT *pGains, UINT nGains, const UINT *pFreqs, BOOL bReset)
+//-------------------------------------------------------------------------------------------
+{
+	for (UINT i=0; i<MAX_EQ_BANDS; i++)
+	{
+		REAL g, f = 0;
+		if (i < nGains)
+		{
+			UINT n = pGains[i];
+//			if (n > 32) n = 32;
+			g = 1.0 + (((double)n) / 64.0);
+			if (pFreqs) f = (REAL)(int)pFreqs[i];
+		} else
+		{
+			g = 1;
+		}
+		gEQ[i].Gain = g;
+		gEQ[i].CenterFrequency = f;
+		gEQ[i+MAX_EQ_BANDS].Gain = g;
+		gEQ[i+MAX_EQ_BANDS].CenterFrequency = f;
+		if (f > 20.0f && i < nGains) /* don't enable bands outside... */
+		{
+			gEQ[i].bEnable = TRUE;
+			gEQ[i+MAX_EQ_BANDS].bEnable = TRUE;
+		} else
+		{
+			gEQ[i].bEnable = FALSE;
+			gEQ[i+MAX_EQ_BANDS].bEnable = FALSE;
+		}
+	}
+	InitializeEQ(bReset);
+}
--- a/src/paranormal/plugin.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/paranormal/plugin.c	Wed Dec 19 17:51:50 2007 +0200
@@ -267,13 +267,6 @@
 }
 
 static void
-about_close_clicked(GtkWidget *w, GtkWidget **window)
-{
-	gtk_widget_destroy(*window);
-	*window=NULL;
-}
-
-static void
 pn_xmms_about (void)
 {
   audacious_info_dialog("About Paranormal Visualization Studio", 
--- a/src/pls/pls.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/pls/pls.c	Wed Dec 19 17:51:50 2007 +0200
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+/* #define AUD_DEBUG 1 */
+
 #include <glib.h>
 #include <string.h>
 #include <glib.h>
@@ -65,30 +67,28 @@
         g_snprintf(line_key, sizeof(line_key), "File%d", i);
         if ((line = aud_read_ini_string(inifile, "playlist", line_key)))
         {
-            gchar *uri = g_filename_to_uri(line, NULL, NULL);
-
-            if (uri)
-                g_free(line);
-            else
-                uri = line;
+            gchar *uri = aud_construct_uri(line, filename);
+            g_free(line);
 
-            if (aud_cfg->use_pl_metadata)
-            {
-                g_snprintf(title_key, sizeof(title_key), "Title%d", i);
+            /* add file only if valid uri has been constructed */
+            if (uri) {
+                if (aud_cfg->use_pl_metadata)
+                {
+                    g_snprintf(title_key, sizeof(title_key), "Title%d", i);
 
-                if ((title = aud_read_ini_string(inifile, "playlist", title_key)))
-                    aud_playlist_load_ins_file(playlist, uri, filename, pos, title, -1);
+                    if ((title = aud_read_ini_string(inifile, "playlist", title_key)))
+                        aud_playlist_load_ins_file(playlist, uri, filename, pos, title, -1);
+                    else
+                        aud_playlist_load_ins_file(playlist, uri, filename, pos, NULL, -1);
+                }
                 else
                     aud_playlist_load_ins_file(playlist, uri, filename, pos, NULL, -1);
-            }
-            else
-                aud_playlist_load_ins_file(playlist, uri, filename, pos, NULL, -1);
+
+                added_count++;
 
-            added_count++;
-
-            if (pos >= 0)
-                pos++;
-
+                if (pos >= 0)
+                    pos++;
+            }
             g_free(uri);
         }
     }
@@ -99,10 +99,14 @@
 static void
 playlist_save_pls(const gchar *filename, gint pos)
 {
+    gchar *uri = g_filename_to_uri(filename, NULL, NULL);
     GList *node;
-    VFSFile *file = aud_vfs_fopen(filename, "wb");
+    VFSFile *file = aud_vfs_fopen(uri, "wb");
     Playlist *playlist = aud_playlist_get_active();
 
+    AUDDBG("filename=%s\n", filename);
+    AUDDBG("uri=%s\n", uri);
+
     g_return_if_fail(file != NULL);
     g_return_if_fail(playlist != NULL);
 
--- a/src/projectm-1.0/Makefile	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/projectm-1.0/Makefile	Wed Dec 19 17:51:50 2007 +0200
@@ -1,7 +1,6 @@
 PLUGIN = projectm-1.0${PLUGIN_SUFFIX}
 
 SRCS = main.cxx		\
-       video_init.cxx   \
        ConfigFile.cxx   \
        main_visplugin.c
 
--- a/src/projectm-1.0/main.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/projectm-1.0/main.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -1,30 +1,11 @@
-/* 
-projectM v1.01 - xmms-projectm.sourceforge.net
---------------------------------------------------
-
-Lead Developers:  Carmelo Piccione (carmelo.piccione@gmail.com) &
-                  Peter Sperl (peter@sperl.com)
-
-We have also been advised by some professors at CMU, namely Roger B. Dannenberg.
-http://www-2.cs.cmu.edu/~rbd/    
-  
-The inspiration for this program was Milkdrop by Ryan Geiss. Obviously. 
-
-This code is distributed under the GPL.
-
-
-THANKS FOR THE CODE!!!
--------------------------------------------------
-The base for this program was andy@nobugs.org's XMMS plugin tutorial
-http://www.xmms.org/docs/vis-plugin.html
-
-We used some FFT code by Takuya OOURA instead of XMMS' built-in fft code
-fftsg.c - http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
-
-and some beat detection code was inspired by Frederic Patin @
-www.gamedev.net/reference/programming/features/beatdetection/
-
-*/
+/*
+ * main.cxx: plugin glue to libprojectm
+ * Copyright (c) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
+ * Portions copyright (c) 2004-2006 Peter Sperl
+ *
+ * This program is free software; you may distribute it under the terms
+ * of the GNU General Public License; version 2.
+ */
 
 #include <stdio.h>
 #include <string.h>
@@ -35,9 +16,11 @@
 #include <SDL/SDL.h>
 #include <SDL/SDL_thread.h>
 
-extern "C" {
+extern "C"
+{
 #include <audacious/util.h>
 #include <audacious/plugin.h>
+#include <audacious/playlist.h>
 #include <audacious/auddrct.h>
 }
 
@@ -47,416 +30,422 @@
 #include <libprojectM/projectM.hpp>
 
 #include "sdltoprojectM.h"
-#include "video_init.h"
 
 #include <GL/gl.h>
 #define CONFIG_FILE "/share/projectM/config.inp"
 
 // Forward declarations 
-extern "C" void projectM_xmms_init(void); 
+extern "C" void projectM_xmms_init(void);
 extern "C" void projectM_cleanup(void);
-extern "C" void projectM_about(void);
-extern "C" void projectM_configure(void);
-extern "C" void projectM_playback_start(void);
-extern "C" void projectM_playback_stop(void);
 extern "C" void projectM_render_pcm(gint16 pcm_data[2][512]);
-extern "C" void projectM_render_freq(gint16 pcm_data[2][256]);
-extern "C" int worker_func(void*);
+extern "C" int worker_func(void *);
 std::string read_config();
-void saveSnapshotToFile();
 
 extern "C" VisPlugin projectM_vtable;
 
-//extern preset_t * active_preset;
+int SDLThreadWrapper(void *);
+void handle_playback_trigger(void *, void *);
+
+class projectMPlugin
+{
+  private:
+    projectM *pm;
+
+    gint wvw, wvh, fvw, fvh;
+    gboolean fullscreen;
+    gboolean error;
 
-//FILE * debugFile = fopen("./dwrite-dump", "wb");
+    SDL_Event event;
+    SDL_Surface *screen;
+    SDL_Thread *worker_thread;
+    SDL_sem *sem;
+
+  public:
+    projectMPlugin()
+    {
+        std::string configFile = read_config();
+        ConfigFile config(configFile);
+
+        this->wvw = config.read<int>("Window Width", 512);
+        this->wvh = config.read<int>("Window Height", 512);
+
+        this->fullscreen = FALSE;
+        if (config.read("Fullscreen", true))
+              this->fullscreen = TRUE;
 
-// Our worker thread
-SDL_Thread *worker_thread = NULL;
-SDL_sem *sem = NULL;
-SDL_Event event;
+        /* initialise SDL */
+        if (SDL_Init(SDL_INIT_VIDEO) < 0)
+        {
+            this->error++;
+            return;
+        }
+
+        SDL_WM_SetCaption("projectM", "audacious");
+        SDL_EnableUNICODE(1);
+
+        this->sem = SDL_CreateSemaphore(0);
+
+        /* XXX */
+        aud_hook_associate("playback begin", handle_playback_trigger, NULL);
+    }
 
-SDL_Surface *screen;
+    ~projectMPlugin()
+    {
+        if (!this->sem)
+            return;
+
+        SDL_SemWait(this->sem);
+
+        if (this->worker_thread)
+            SDL_WaitThread(this->worker_thread, NULL);
 
+        SDL_DestroySemaphore(this->sem);
+        SDL_Quit();
 
-projectM * globalPM = NULL;
+        this->sem = 0;
+        this->worker_thread = 0;
+
+        delete this->pm;
+        this->pm = 0;
+
+        aud_hook_dissociate("playback begin", handle_playback_trigger);
+    }
 
-int maxsamples=512;
+    int run(void *unused)
+    {
+        if (error)
+            return -1;
+
+        std::string configFile = read_config();
+        this->initDisplay(this->wvw, this->wvh, &this->fvw, &this->fvh, this->fullscreen);
+        this->pm = new projectM(configFile);
+        this->pm->projectM_resetGL(this->wvw, this->wvh);
+
+        SDL_SemPost(this->sem);
+
+        while (SDL_SemValue(this->sem) == 1)
+        {
+            projectMEvent evt;
+            projectMKeycode key;
+            projectMModifier mod;
+
+            SDL_Event event;
+            while (SDL_PollEvent(&event))
+            {
+                evt = sdl2pmEvent(event);
+
+                key = sdl2pmKeycode(event.key.keysym.sym);
+                mod = sdl2pmModifier(event.key.keysym.mod);
+
+                switch (evt)
+                {
+                  case PROJECTM_KEYDOWN:
+                      switch (key)
+                      {
+                        case PROJECTM_K_c:
+                            this->takeScreenshot();
+                            break;
 
-int texsize=512;
-int gx=32,gy=24;
-int wvw=400,wvh=400;
-int fvw=1024,fvh=768;
-int fps=35, fullscreen=0;
+                        case PROJECTM_K_f:
+                            int w, h;
+                            if (fullscreen == 0)
+                            {
+                                w = fvw;
+                                h = fvh;
+                                fullscreen = 1;
+                            }
+                            else
+                            {
+                                w = wvw;
+                                h = wvh;
+                                fullscreen = 0;
+                            }
 
-// char *title;
+                            this->resizeDisplay(w, h, fullscreen);
+                            this->pm->projectM_resetGL(w, h);
+
+                            break;
+
+                        default:
+                            this->pm->key_handler(evt, key, mod);
+                            break;
+                      }
 
-gint disable_projectm(void *something) {
-	projectM_vtable.disable_plugin(&projectM_vtable);
-	return 0;
-}
+                      break;
+
+                  case PROJECTM_VIDEORESIZE:
+                      wvw = event.resize.w;
+                      wvh = event.resize.h;
+                      this->resizeDisplay(wvw, wvh, fullscreen);
+                      this->pm->projectM_resetGL(wvw, wvh);
+
+                      break;
 
-Uint32 get_xmms_title(Uint32 something, void *somethingelse) {
-	static char check_title = 1;
-	static int last_pos;
-	static char *last_title = NULL;
-	int pos;
-	char *title = NULL;
+                  case PROJECTM_VIDEOQUIT:
+                      std::cerr << "XXX: PROJECTM_VIDEOQUIT is not implemented yet!" << std::endl;
+                      break;
+
+                  default:
+                      break;
+                }
+            }
+
+            this->pm->renderFrame();
+
+            SDL_GL_SwapBuffers();
+        }
+
+        return 0;
+    }
+
+    void launchThread()
+    {
+        /* SDL sucks and won't let you use C++ functors... */
+        this->worker_thread = SDL_CreateThread(SDLThreadWrapper, NULL);
+    }
+
+    void addPCMData(gint16 pcm_data[2][512])
+    {
+        if (SDL_SemValue(this->sem) == 1)
+            this->pm->pcm->addPCM16(pcm_data);
+    }
 
-	//Nice optimization, but we want the title no matter what so I can display it when the song changes
-#if 0
-	if(!(globalPM->showtitle%2)) {
-		/* Repeat less often when not showing title */
-		return 1000;
-	}
-#endif
+    void initDisplay(gint width, gint height, gint *rwidth, gint *rheight, gboolean fullscreen)
+    {
+        this->wvw = width;
+        this->wvh = height;
+        this->fvw = *rwidth;
+        this->fvw = *rheight;
+        this->fullscreen = fullscreen;
+
+        const SDL_VideoInfo *info = NULL;
+        int bpp;
+        int flags;
+
+        info = SDL_GetVideoInfo();
+        if (!info)
+        {
+            this->error++;
+            return;
+        }
+
+        /* initialize fullscreen resolution to something "sane" */
+        *rwidth = width;
+        *rheight = height;
+
+        bpp = info->vfmt->BitsPerPixel;
+        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+        if (this->fullscreen)
+            flags = SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN;
+        else
+            flags = SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE;
+
+        this->screen = SDL_SetVideoMode(width, height, bpp, flags);
+        if (!this->screen)
+            this->error++;
+    }
 
-        pos = audacious_drct_pl_get_pos();
-	/* Only check every 1 second for title change, otherwise check pos */
-	if(check_title || pos != last_pos) {
-                title = audacious_drct_pl_get_title(pos);
-		if(title && (!last_title || strcmp(last_title,title))) {
-		  //globalPM->renderer->title = title;
-			//globalPM->renderer->drawtitle = 1;
+    void resizeDisplay(gint width, gint height, gboolean fullscreen)
+    {
+        this->fullscreen = fullscreen;
+
+        int flags;
+
+        if (this->fullscreen)
+            flags = SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN;
+        else
+            flags = SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE;
+
+        this->screen = SDL_SetVideoMode(width, height, 0, flags);
+        if (this->screen == 0)
+            return;
+
+        SDL_ShowCursor(this->fullscreen ? SDL_DISABLE : SDL_ENABLE);
+    }
+
+    void triggerPlaybackBegin(PlaylistEntry *entry)
+    {
+        std::string title(entry->title);
+        this->pm->projectM_setTitle(title);
+    }
+
+    void takeScreenshot(void)
+    {
+        static int frame = 1;
+
+        std::string dumpPath(g_get_home_dir());
+        dumpPath.append("/.projectM/");
+
+        gchar *frame_ = g_strdup_printf("%.8d.bmp", frame);
+        dumpPath.append(frame_);
+        g_free(frame_);
 
-		  std::string titlepp(title);
-		  globalPM->projectM_setTitle(titlepp);
-			g_free(last_title);
-			last_title = title;
-		} else if(title && last_title != title) {
-			/* New copy of last title */
-			g_free(title);
-		}
-		check_title = !check_title;
-	}
-	last_pos = pos;
-	/* Repeat every 500ms */
-	return 500;
+        SDL_Surface *bitmap;
+
+        GLint viewport[4];
+        long bytewidth;
+        GLint width, height;
+        long bytes;
+
+        glReadBuffer(GL_FRONT);
+        glGetIntegerv(GL_VIEWPORT, viewport);
+
+        width = viewport[2];
+        height = viewport[3];
+
+        bytewidth = width * 4;
+        bytewidth = (bytewidth + 3) & ~3;
+        bytes = bytewidth * height;
+
+        bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0);
+        glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, bitmap->pixels);
+
+        SDL_SaveBMP(bitmap, dumpPath.c_str());
+
+        SDL_FreeSurface(bitmap);
+
+        frame++;
+    }
+};
+
+/* glue to implementation section */
+projectMPlugin *thePlugin = 0;
+
+/* SDL sucks and won't let you use proper C++ functors. :( */
+int SDLThreadWrapper(void *unused)
+{
+    return thePlugin->run(unused);
 }
 
-int capture = 0;
-
-int worker_func(void*)
-{ 
-// char projectM_data[1024]; 
- SDL_TimerID title_timer = NULL;
- std::string config_file;
- config_file = read_config();
- ConfigFile config(config_file);
-
- int wvw = config.read<int>( "Window Width", 512 );
- int wvh = config.read<int>( "Window Height", 512 );
-
- int fullscreen = 0;
- if (config.read("Fullscreen", true)) fullscreen = 1;
-      else fullscreen = 0;
-
-  init_display(wvw,wvh,&fvw,&fvh,fullscreen); 
-  SDL_WM_SetCaption("projectM v1.00", "projectM v1.00");
-
-  /** Initialise projectM */
-    
-  globalPM = new projectM(config_file);
-  SDL_SemPost(sem);
-  title_timer = SDL_AddTimer(500, get_xmms_title, NULL);
-    /** Initialise the thread */
-  // SDL_SemTryWait(sem);
-  while ( SDL_SemValue(sem)==1 ) {
-        projectMEvent evt;
-        projectMKeycode key;
-        projectMModifier mod;
-
-        /** Process SDL events */
-        SDL_Event event;
-        while ( SDL_PollEvent( &event ) ) {
-            /** Translate into projectM codes and process */
-            evt = sdl2pmEvent( event );	  
-
-            key = sdl2pmKeycode( event.key.keysym.sym );
-            mod = sdl2pmModifier( event.key.keysym.mod );
-
-            if ( evt == PROJECTM_KEYDOWN ) {                 
-	   
-	      if(key == PROJECTM_K_c)
-		{
-		  //SDL_SaveBMP(screen, "/home/pete/1.bmp");
-		  saveSnapshotToFile();
-		}
-	      if(key == PROJECTM_K_v)
-		{
-		  // capture++;
-		}
-	      if(key == PROJECTM_K_f)
-		{
-		 
+void handle_playback_trigger(gpointer plentry_p, gpointer unused)
+{
+    PlaylistEntry *entry = reinterpret_cast<PlaylistEntry *>(plentry_p);
 
-		 int w, h;
-                    if (fullscreen == 0) {
-                        w = fvw;
-                        h = fvh;
-			fullscreen = 1;
-                    } else {
-                        w = wvw;
-                        h = wvh;
-			fullscreen = 0;
-                    }
-                  
-                    resize_display(w, h, fullscreen);
-                    globalPM->projectM_resetGL( w, h ); 
-                }
-	      else  globalPM->key_handler(evt,key,mod);
-
-              }
-	    else if ( evt == PROJECTM_VIDEORESIZE )
-	      {
-
-	       
+    if (!thePlugin)
+        return;
 
-		wvw=event.resize.w;
-		wvh=event.resize.h;
-	       
-		
-		resize_display(wvw,wvh,fullscreen);
-		globalPM->projectM_resetGL( wvw, wvh ); 
- 
-              } 
-	    else if ( evt == PROJECTM_VIDEOQUIT ) {
-	      
-	      (void) g_idle_add ((GSourceFunc) disable_projectm, NULL);
-	    }
-	}
-	
-        /** Add the waveform data */
-      
-
-        /** Render the new frame */
-	//	 strcpy(title,xmms_remote_get_playlist_title(projectM_vtable.xmms_session, xmms_remote_get_playlist_pos(projectM_vtable.xmms_session))); 
-
-	 //printf("%s\n",title);
-	// strcpy(globalPM->title,title);
-	
-	  globalPM->renderFrame();
-	
-      
-
-        SDL_GL_SwapBuffers();
-
-	if (capture % 2 == 1) saveSnapshotToFile();
-	//	SDL_SemPost(sem);
-      }
-
- if(title_timer) 
-  	SDL_RemoveTimer(title_timer);
- delete globalPM;
-
-
- return 0;
+    thePlugin->triggerPlaybackBegin(entry);
 }
 
-extern "C" void projectM_xmms_init(void) 
+extern "C" void projectM_xmms_init(void)
 {
-  
-  /* First, initialize SDL's video subsystem. */
- // std::cerr << "sdl init begin" << std::endl;  
-  if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 ) {
-    /* Failed, exit. */
-    fprintf( stderr, "Video initialization failed: %s\n",
-             SDL_GetError( ) );
-    //projectM_vtable.disable_plugin (&projectM_vtable);
-    return;
-    
-  }
-  sem = SDL_CreateSemaphore(0);
- // printf("projectM plugin: Initializing\n");
- 
-  SDL_EnableUNICODE(1);
-  
-  worker_thread = SDL_CreateThread ( *worker_func, NULL);
- 
+    thePlugin = new projectMPlugin;
+    thePlugin->launchThread();
 }
 
-
-
 extern "C" void projectM_cleanup(void)
 {
-
-  if(!sem) return;
-  SDL_SemWait(sem);
-  if(worker_thread) SDL_WaitThread(worker_thread, NULL);
-  // SDL_KillThread(worker_thread);
-  //printf("killed thread\n");
+    if (!thePlugin)
+        return;
 
-  SDL_DestroySemaphore(sem);
-  //printf("Destroy Mutex\n");
-  SDL_Quit();
-
-  sem = NULL;
-  worker_thread = NULL;
-  
- // printf("projectM plugin: Cleanup completed\n");
+    delete thePlugin;
 }
-extern "C" void projectM_about(void)
-{
-  printf("projectM plugin: About\n");
-}
-extern "C" void projectM_configure(void)
-{
-  printf("projectM plugin: Configure\n");
-}
-extern "C" void projectM_playback_start(void)
-{//thread_control = GO;
-  printf("projectM plugin: Playback starting\n");
-}
-extern "C" void projectM_playback_stop(void)
-{//thread_control = STOP;
-  printf("projectM plugin: Playback stopping\n");
-}
+
 extern "C" void projectM_render_pcm(gint16 pcm_data[2][512])
 {
-  //SDL_mutexP(mutex); while ( SDL_SemValue(sem)==1 )
-  if ( SDL_SemValue(sem)==1 )
-        globalPM->pcm->addPCM16(pcm_data);
-	 
-       	//SDL_mutexV(mutex);
-	
+    if (!thePlugin)
+        return;
+
+    thePlugin->addPCMData(pcm_data);
 }
 
-extern "C" void projectM_render_freq(gint16 freq_data[2][256])
-{
-  printf("NO GOOD\n");
- }
-
+/********************************************************************************
+ * XXX: This code is from projectM and still needs to be rewritten!             *
+ ********************************************************************************/
 std::string read_config()
 {
 
 //   int n;
-   
-   char num[512];
-   FILE *in; 
-   FILE *out;
-
-   char* home;
-   char projectM_home[1024];
-   char projectM_config[1024];
-
-   strcpy(projectM_config, PROJECTM_PREFIX);
-   strcpy(projectM_config+strlen(PROJECTM_PREFIX), CONFIG_FILE);
-   projectM_config[strlen(PROJECTM_PREFIX)+strlen(CONFIG_FILE)]='\0';
-   //printf("dir:%s \n",projectM_config);
-   home=getenv("HOME");
-   strcpy(projectM_home, home);
-   strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
-   projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
 
-  
- if ((in = fopen(projectM_home, "r")) != 0) 
-   {
-     //printf("reading ~/.projectM/config.inp \n");
-     fclose(in);
-     return std::string(projectM_home);
-   }
- else
-   {
-     printf("trying to create ~/.projectM/config.inp \n");
+    char num[512];
+    FILE *in;
+    FILE *out;
 
-     strcpy(projectM_home, home);
-     strcpy(projectM_home+strlen(home), "/.projectM");
-     projectM_home[strlen(home)+strlen("/.projectM")]='\0';
-     mkdir(projectM_home,0755);
-
-     strcpy(projectM_home, home);
-     strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
-     projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
+    char *home;
+    char projectM_home[1024];
+    char projectM_config[1024];
 
-     if((out = fopen(projectM_home,"w"))!=0)
-       {
-	
-	 if ((in = fopen(projectM_config, "r")) != 0) 
-	   {
-
-	     while(fgets(num,80,in)!=NULL)
-	       {
-		 fputs(num,out);
-	       }
-	     fclose(in);
-	     fclose(out);
-	    
-
-	     if ((in = fopen(projectM_home, "r")) != 0) 
-	       { 
-		 printf("created ~/.projectM/config.inp successfully\n");  
-		 fclose(in);
-		 return std::string(projectM_home);
-	       }
-	     else{printf("This shouldn't happen, using implementation defualts\n");abort();}
-	   }
-	 else{printf("Cannot find projectM default config, using implementation defaults\n");abort();}
-       }
-     else
-       {
-	 printf("Cannot create ~/.projectM/config.inp, using default config file\n");
-	 if ((in = fopen(projectM_config, "r")) != 0) 
-	   { printf("Successfully opened default config file\n");
-	     fclose(in);
-	     return std::string(projectM_config);}
-	 else{ printf("Using implementation defaults, your system is really messed up, I'm suprised we even got this far\n");  abort();}
-       }
-
-   }
-
- abort();
-}
-
-int frame = 1;
+    strcpy(projectM_config, PROJECTM_PREFIX);
+    strcpy(projectM_config + strlen(PROJECTM_PREFIX), CONFIG_FILE);
+    projectM_config[strlen(PROJECTM_PREFIX) + strlen(CONFIG_FILE)] = '\0';
+    //printf("dir:%s \n",projectM_config);
+    home = getenv("HOME");
+    strcpy(projectM_home, home);
+    strcpy(projectM_home + strlen(home), "/.projectM/config.inp");
+    projectM_home[strlen(home) + strlen("/.projectM/config.inp")] = '\0';
 
 
-void saveSnapshotToFile()
-{
-  char dumpPath[512];
-  char Home[512];
-  //char *home;
-  
-  SDL_Surface *	bitmap;
-  
-  GLint		viewport[4];
-  long		bytewidth;
-  GLint		width, height;
-  long		bytes;
-  
-  glReadBuffer(GL_FRONT);
-  glGetIntegerv(GL_VIEWPORT, viewport);
-  
-  width = viewport[2];
-  height = viewport[3];
-            
-  bytewidth = width * 4;
-  bytewidth = (bytewidth + 3) & ~3;
-  bytes = bytewidth * height;
-  
-  /*
-    glFinish();
-    glPixelStorei(GL_PACK_ALIGNMENT, 4);
-    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
-    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
-    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
-  */
-  
-  
-  bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, width,  height, 32,0,0,0,0);
-  glReadPixels(0, 0, width, height,
-	       GL_BGRA,
-	       GL_UNSIGNED_INT_8_8_8_8_REV,
-	       bitmap->pixels);
-  
-  sprintf(dumpPath, "/.projectM/%.8d.bmp", frame++);
-  // home=getenv("HOME");
-  strcpy(Home, getenv("HOME"));
-  strcpy(Home+strlen(Home), dumpPath);
-  Home[strlen(Home)]='\0';
-  SDL_SaveBMP(bitmap, Home);
-     
-  SDL_FreeSurface(bitmap);
- 
-       
+    if ((in = fopen(projectM_home, "r")) != 0)
+    {
+        //printf("reading ~/.projectM/config.inp \n");
+        fclose(in);
+        return std::string(projectM_home);
+    }
+    else
+    {
+        printf("trying to create ~/.projectM/config.inp \n");
+
+        strcpy(projectM_home, home);
+        strcpy(projectM_home + strlen(home), "/.projectM");
+        projectM_home[strlen(home) + strlen("/.projectM")] = '\0';
+        mkdir(projectM_home, 0755);
+
+        strcpy(projectM_home, home);
+        strcpy(projectM_home + strlen(home), "/.projectM/config.inp");
+        projectM_home[strlen(home) + strlen("/.projectM/config.inp")] = '\0';
+
+        if ((out = fopen(projectM_home, "w")) != 0)
+        {
+
+            if ((in = fopen(projectM_config, "r")) != 0)
+            {
+
+                while (fgets(num, 80, in) != NULL)
+                {
+                    fputs(num, out);
+                }
+                fclose(in);
+                fclose(out);
+
+
+                if ((in = fopen(projectM_home, "r")) != 0)
+                {
+                    printf("created ~/.projectM/config.inp successfully\n");
+                    fclose(in);
+                    return std::string(projectM_home);
+                }
+                else
+                {
+                    printf("This shouldn't happen, using implementation defualts\n");
+                    abort();
+                }
+            }
+            else
+            {
+                printf("Cannot find projectM default config, using implementation defaults\n");
+                abort();
+            }
+        }
+        else
+        {
+            printf("Cannot create ~/.projectM/config.inp, using default config file\n");
+            if ((in = fopen(projectM_config, "r")) != 0)
+            {
+                printf("Successfully opened default config file\n");
+                fclose(in);
+                return std::string(projectM_config);
+            }
+            else
+            {
+                printf("Using implementation defaults, your system is really messed up, I'm suprised we even got this far\n");
+                abort();
+            }
+        }
+
+    }
+
+    abort();
 }
-
--- a/src/projectm-1.0/main_visplugin.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/projectm-1.0/main_visplugin.c	Wed Dec 19 17:51:50 2007 +0200
@@ -2,24 +2,14 @@
 
 extern void projectM_xmms_init(void);
 extern void projectM_cleanup(void);
-extern void projectM_about(void);
-extern void projectM_configure(void);
-extern void projectM_playback_start(void);
-extern void projectM_playback_stop(void);
 extern void projectM_render_pcm(gint16 pcm_data[2][512]);
-extern void projectM_render_freq(gint16 pcm_data[2][256]);
 
 VisPlugin projectM_vtable = {
     .description = "projectM v1.0",
     .num_pcm_chs_wanted = 2,
     .init = projectM_xmms_init,
     .cleanup = projectM_cleanup,
-    .about = projectM_about,
-    .configure = projectM_configure,
-    .playback_start = projectM_playback_start,
-    .playback_stop = projectM_playback_stop,
     .render_pcm = projectM_render_pcm,
-    .render_freq = projectM_render_freq,
 };
 
 VisPlugin *projectM_vplist[] = { &projectM_vtable, NULL };
--- a/src/projectm-1.0/video_init.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-//video_init.c - SDL/Opengl Windowing Creation/Resizing Functions
-//
-//by Peter Sperl
-//
-//Opens an SDL Window and creates an OpenGL session
-//also able to handle resizing and fullscreening of windows
-//just call init_display again with differant variables
-
-#include <SDL/SDL.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include "video_init.h"
-#include <iostream>
-extern SDL_Surface *screen;
-extern int texsize;
-
-void resize_display(int w, int h, int f) {
-  int flags;
-  if (f) flags =  SDL_OPENGL|SDL_HWSURFACE|SDL_FULLSCREEN;
-  else   flags =  SDL_OPENGL|SDL_HWSURFACE|SDL_RESIZABLE;
-//  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
-  screen = SDL_SetVideoMode( w, h, 0, flags ) ;
-  if(screen == 0 ) {
-      fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) );
-      return;
-  }
-  
-  SDL_ShowCursor(f ? SDL_DISABLE : SDL_ENABLE);
-}
-
-//init_display
-//
-//Sets screen to new width and height (w,h)
-//Also switches between fullscreen and windowed
-//with the boolean f (fullscreen)
-void init_display(int w, int h, int *fvw, int *fvh, int f)
-{
-  
-  /* Information about the current video settings. */
-  const SDL_VideoInfo* info = NULL;
-  int bpp = 0;
-  /* Flags we will pass into SDL_SetVideoMode. */
-  int flags = 0;
-
-
-  /* Let's get some video information. */
-  info = SDL_GetVideoInfo( );
-  if( !info ) {
-    /* This should probably never happen. */
-    fprintf( stderr, "Video query failed: %s\n",
-             SDL_GetError( ) );
-    //    projectM_vtable.disable_plugin (&projectM_vtable);
-    return;
-  }
-  
-//  printf("Screen Resolution: %d x %d\n", info->current_w, info->current_h);
-// XXX
-  *fvw = w;
-  *fvh = h;
-  bpp = info->vfmt->BitsPerPixel;
-  //SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
-  //SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
-  //SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
-
-  // SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 8 );
-  //  SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 8 );
-  //  SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 8 );
-  SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
-  SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
-  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
-  if (f==0)
-     flags = SDL_OPENGL|SDL_HWSURFACE|SDL_RESIZABLE;
-  else flags = SDL_OPENGL|SDL_HWSURFACE|SDL_FULLSCREEN;
- screen= SDL_SetVideoMode( w, h, bpp, flags ) ;
-  if(screen == 0 ) {
-    /* 
-     * This could happen for a variety of reasons,
-     * including DISPLAY not being set, the specified
-     * resolution not being available, etc.
-     */
-   fprintf( stderr, "Video mode set failed: %s\n",
-	     SDL_GetError( ) );
-    
-   // projectM_vtable.disable_plugin (&projectM_vtable);
-    return;
-    
-  }
-  
-  // setup_opengl(w,h);
-  //gluOrtho2D(0, w, 0, h);
-}
-
-
--- a/src/projectm-1.0/video_init.h	Wed Dec 05 13:35:16 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
- 
- void init_display( int w, int h, int *fvw, int *fvh, int fullscreen );
- void resize_display( int w, int h, int fullscreen );
-
-
--- a/src/rootvis/config_frontend_widgets.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/rootvis/config_frontend_widgets.c	Wed Dec 19 17:51:50 2007 +0200
@@ -371,8 +371,7 @@
 
 	{
 		GtkWidget *vbox_0, *notebook_1, *button_box_1,
-			*vbox_2[4], *frame_3[4], *vbox_3[1], *hbox_4[5],
-			*check_debug, *check_stereo,
+			*vbox_2[4], *frame_3[4], *hbox_4[5],
 			*close_button, *revert_button;
 
 		vbox_0 = frontend_create_box(VBOX, window, "rootvis_config_vbox", ATTACH_TO_CONTAINER);
@@ -427,7 +426,7 @@
 {
 	GtkWidget *window, *channel_button[2],
 		  *button_box[2], *channels_frame, *main_frame, *vbox,
-		  *main_vbox, *channels_hbox, *channel_vbox[2],
+		  *main_vbox, *channel_vbox[2],
 		  *save_button, *revert_button, *close_button;
 
 	window = frontend_create_window(GTK_WINDOW_TOPLEVEL, "Main");
--- a/src/rootvis/rootvis.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/rootvis/rootvis.c	Wed Dec 19 17:51:50 2007 +0200
@@ -13,7 +13,6 @@
 // Forward declarations
 static void rootvis_init(void);
 static void rootvis_cleanup(void);
-static void rootvis_about(void);
 static void rootvis_configure(void);
 static void rootvis_playback_start(void);
 static void rootvis_playback_stop(void);
@@ -416,11 +415,6 @@
   }
 }
 
-static void rootvis_about(void)
-{
-	print_status("About");
-}
-
 static void rootvis_configure(void)
 {
 	print_status("Configuration trigger");
--- a/src/scrobbler/fmt.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/scrobbler/fmt.c	Wed Dec 19 17:51:50 2007 +0200
@@ -6,6 +6,7 @@
 #include <ctype.h>
 #include "fmt.h"
 #include <curl/curl.h>
+#include <glib.h>
 
 char *fmt_escape(const char *str)
 {
--- a/src/scrobbler/scrobbler.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/scrobbler/scrobbler.c	Wed Dec 19 17:51:50 2007 +0200
@@ -674,9 +674,9 @@
 	/*cfa(&post, &last, "debug", "failed");*/
 
 	entry = g_strdup_printf("s=%s&a=%s&t=%s&b=%s&l=%d&n=%d&m=", sc_session_id,
-		aud_tuple_get_string(tuple, FIELD_ARTIST, NULL),
-		aud_tuple_get_string(tuple, FIELD_TITLE, NULL),
-		aud_tuple_get_string(tuple, FIELD_ALBUM, NULL) ? aud_tuple_get_string(tuple, FIELD_ALBUM, NULL) : "",
+		fmt_escape(aud_tuple_get_string(tuple, FIELD_ARTIST, NULL)),
+		fmt_escape(aud_tuple_get_string(tuple, FIELD_TITLE, NULL)),
+		aud_tuple_get_string(tuple, FIELD_ALBUM, NULL) ? fmt_escape(aud_tuple_get_string(tuple, FIELD_ALBUM, NULL)) : "",
 		aud_tuple_get_int(tuple, FIELD_LENGTH, NULL) / 1000,
 		aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL));
 
--- a/src/sexypsf/PsxBios.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/sexypsf/PsxBios.c	Wed Dec 19 17:51:50 2007 +0200
@@ -269,12 +269,14 @@
 }
 
 static void bios_atoi() { // 0x10
-	v0 = atoi((char *)Ra0);
+	char *p0 = Ra0;
+	v0 = atoi(p0);
 	pc0 = ra;
 }
 
 static void bios_atol() { // 0x11
-	v0 = atoi((char *)Ra0);
+	char *p0 = Ra0;
+	v0 = atoi(p0);
 	pc0 = ra;
 }
 
@@ -300,7 +302,7 @@
 	sp = BFLIP32(jmp_buf[1]); /* sp */
 	fp = BFLIP32(jmp_buf[2]); /* fp */
 	for (i=0; i<8; i++) // s0-s7
-	   psxRegs.GPR.r[16+i] =  BFLIP32(jmp_buf[3+i]);
+		psxRegs.GPR.r[16+i] =  BFLIP32(jmp_buf[3+i]);
 	gp = BFLIP32(jmp_buf[11]); /* gp */
 
 	v0 = a1; pc0 = ra;
@@ -315,10 +317,10 @@
 	while(PSXMu8(dest) != 0) dest++; /* Move to end of first string. */
 	while(PSXMu8(src) != 0) 
 	{
-	 if(PSXM(dest) && PSXM(src))
-	  PSXMu8(dest)=PSXMu8(src);
-	 src++;
-	 dest++;
+		if(PSXM(dest) && PSXM(src))
+			PSXMu8(dest)=PSXMu8(src);
+		src++;
+		dest++;
 	}
 	PSXMu8(dest) = 0;	/* Append null character. */
 	//strcat(Ra0, Ra1);
@@ -339,21 +341,22 @@
         while(PSXMu8(dest) != 0) dest++; /* Move to end of first string. */
         while(PSXMu8(src) != 0 && count)
         {
-         if(PSXM(dest) && PSXM(src))
-          PSXMu8(dest)=PSXMu8(src);
-         src++;
-         dest++;
-	 count--;
+		if(PSXM(dest) && PSXM(src))
+			PSXMu8(dest)=PSXMu8(src);
+		src++;
+		dest++;
+		count--;
         }
         PSXMu8(dest) = 0;       /* Append null character. */
 
- //strncat(Ra0, Ra1, a2); 
- v0 = a0; 
- pc0 = ra;
+	//strncat(Ra0, Ra1, a2); 
+	v0 = a0; 
+	pc0 = ra;
 }
 
 static void bios_strcmp() { // 0x17
-	v0 = strcmp(Ra0, Ra1);
+	char *p0 = Ra0, *p1 = Ra1;
+	v0 = strcmp(p0, p1);
 	pc0 = ra;
 }
 
@@ -365,18 +368,18 @@
 
 	while(max>0)
 	{
-	 u8 tmp1=PSXMuR8(string1);
-	 u8 tmp2=PSXMuR8(string2);
+		u8 tmp1=PSXMuR8(string1);
+		u8 tmp2=PSXMuR8(string2);
 
-	 if(!tmp1 || !tmp2) break;
+		if(!tmp1 || !tmp2) break;
 
-	 tmpv=tmp1-tmp2;
-	 if(tmpv) break;
-         if(!tmp1 || !tmp2) break;
-	 if(!PSXM(string1) || !PSXM(string2)) break;
-	 max--;
-	 string1++;
-	 string2++;
+		tmpv=tmp1-tmp2;
+		if(tmpv) break;
+		if(!tmp1 || !tmp2) break;
+		if(!PSXM(string1) || !PSXM(string2)) break;
+		max--;
+		string1++;
+		string2++;
 	}
 	if(tmpv>0) v0=1;
 	else if(tmpv<0) v0=-1;
@@ -389,49 +392,49 @@
 /*0x19*/
 static void bios_strcpy()  
 { 
- u32 src=a1,dest=a0;
- u8 val;
+	u32 src=a1,dest=a0;
+	u8 val;
 
- do
- {
-  val=PSXMu8(src);
-  PSXMu8(dest)=val;
-  src++; 
-  dest++;
- } while(val);
- //strcpy(Ra0, Ra1); 
- v0 = a0; 
- pc0 = ra;
+	do
+	{
+		val=PSXMu8(src);
+		PSXMu8(dest)=val;
+		src++; 
+		dest++;
+	} while(val);
+	//strcpy(Ra0, Ra1); 
+	v0 = a0; 
+	pc0 = ra;
 }
 /*0x1a*/
 static void bios_strncpy() 
 { 
- u32 src=a1,dest=a0,max=a2;
- u8 val;  
+	u32 src=a1,dest=a0,max=a2;
+	u8 val;  
  
- do
- {
-  val=PSXMu8(src); 
-  PSXMu8(dest)=val;
-  src++;   
-  dest++;
-  max--;
- } while(val && max);
+	do
+	{
+		val=PSXMu8(src); 
+		PSXMu8(dest)=val;
+		src++;   
+		dest++;
+		max--;
+	} while(val && max);
 
- //strncpy(Ra0, Ra1, a2);  
- v0 = a0; 
- pc0 = ra;
+	//strncpy(Ra0, Ra1, a2);  
+	v0 = a0; 
+	pc0 = ra;
 }
 
 /*0x1b*/
 static void bios_strlen()  
 { 
- u32 src=a0;
+	u32 src=a0;
 
- while(PSXMu8(src)) src++;
+	while(PSXMu8(src)) src++;
 
- v0 = src-a0;  
- pc0 = ra;
+	v0 = src-a0;  
+	pc0 = ra;
 }
 
 static void bios_index() { // 0x1c
@@ -441,7 +444,7 @@
 		v0 = a0 + pcRet - pcA0; 
 	else 
 		v0 = 0;
-    pc0 = ra;
+	pc0 = ra;
 }
 
 static void bios_rindex() { // 0x1d
@@ -451,7 +454,7 @@
 		v0 = a0 + pcRet - pcA0; 
 	else 
 		v0 = 0;
-    pc0 = ra;  
+	pc0 = ra;  
 }
 
 static void bios_strchr() { // 0x1e
@@ -461,7 +464,7 @@
 		v0 = a0 + pcRet - pcA0; 
 	else 
 		v0 = 0;
-    pc0 = ra;
+	pc0 = ra;
 }
 
 static void bios_strrchr() { // 0x1f
@@ -471,42 +474,50 @@
 		v0 = a0 + pcRet - pcA0; 
 	else 
 		v0 = 0;
-    pc0 = ra;
+	pc0 = ra;
 }
 
 static void bios_strpbrk() { // 0x20
-	char *pcA0 = (char *)Ra0; 
-	char *pcRet = strpbrk(pcA0, (char *)Ra1); 
+	char *pcA0 = Ra0, *pcA1 = Ra1;
+	char *pcRet = strpbrk(pcA0, pcA1); 
 	if(pcRet) 
 		v0 = a0 + pcRet - pcA0; 
 	else 
 		v0 = 0;
-    pc0 = ra;
+	pc0 = ra;
 }
 
-static void bios_strspn()  { v0 = strspn ((char *)Ra0, (char *)Ra1); pc0 = ra;}/*21*/ 
-static void bios_strcspn() { v0 = strcspn((char *)Ra0, (char *)Ra1); pc0 = ra;}/*22*/ 
+static void bios_strspn() { /*21*/
+	char *p0 = Ra0, *p1 = Ra1;
+	v0 = strspn (p0, p1);
+	pc0 = ra;
+}
+static void bios_strcspn() { /*22*/
+	char *p0 = Ra0, *p1 = Ra1;
+	v0 = strcspn(p0, p1);
+	pc0 = ra;
+}
 
 #ifdef MOO
 static void bios_strtok() { // 0x23
-	char *pcA0 = (char *)Ra0;
-	char *pcRet = strtok(pcA0, (char *)Ra1);
+	char *pcA0 = Ra0, *pcA1 = Ra1;
+	char *pcRet = strtok(pcA0, pcA1);
 	if(pcRet)
 		v0 = a0 + pcRet - pcA0;
 	else
 		v0 = 0;
-    pc0 = ra;
+	pc0 = ra;
 }
 #endif
 
 static void bios_strstr() { // 0x24
-	char *pcA0 = (char *)Ra0;
-	char *pcRet = strstr(pcA0, (char *)Ra1);
+	char *pcA0 = Ra0, *pcA1 = Ra1;
+	char *pcRet = strstr(pcA0, pcA1);
 	if(pcRet)
 		v0 = a0 + pcRet - pcA0;
 	else
 		v0 = 0;
-    pc0 = ra;
+	pc0 = ra;
 }
 
 /*0x25*/
@@ -518,81 +529,91 @@
 /*0x27*/
 static void bios_bcopy()   
 {
- u32 dest=a1, src=a0, len=a2;
+	u32 dest=a1, src=a0, len=a2;
 
- while(len--)
- {
-  PSXMu8(dest)=PSXMu8(src);
-  dest++;
-  src++;
- }
- //memcpy(Ra1,Ra0,a2); 
- pc0=ra;
+	while(len--)
+	{
+		PSXMu8(dest)=PSXMu8(src);
+		dest++;
+		src++;
+	}
+	//memcpy(Ra1,Ra0,a2); 
+	pc0=ra;
 }
 
 /*0x28*/
 static void bios_bzero()   
 {
- u32 dest=a0, len=a1;
+	u32 dest=a0, len=a1;
  
- while(len--)
- {
-  PSXMu8(dest)=0;
-  dest++;
- }
+	while(len--)
+	{
+		PSXMu8(dest)=0;
+		dest++;
+	}
 
- //memset(Ra0,0,a1); 
- pc0=ra;
+	//memset(Ra0,0,a1); 
+	pc0=ra;
 }
 
 /*0x29*/
-static void bios_bcmp()    {v0 = memcmp(Ra0,Ra1,a2); pc0=ra; }
+static void bios_bcmp() {
+	char *p0 = Ra0, *p1 = Ra1;
+	v0 = memcmp(p0, p1, a2);
+	pc0=ra;
+}
 
 /*0x2a*/
 static void bios_memcpy()  
 {
- u32 dest=a0, src=a1, len=a2;
+	u32 dest=a0, src=a1, len=a2;
  
- while(len--)
- {
-  PSXMu8(dest)=PSXMu8(src);
-  dest++;
-  src++;
- }
- //memcpy(Ra0, Ra1, a2); 
- v0 = a0; 
- pc0 = ra;
+	while(len--)
+	{
+		PSXMu8(dest)=PSXMu8(src);
+		dest++;
+		src++;
+	}
+	//memcpy(Ra0, Ra1, a2); 
+	v0 = a0; 
+	pc0 = ra;
 }
 
 static void bios_memset()  /*0x2b*/
 {
- u32 len=a2;
- u32 dest=a0;
+	u32 len=a2;
+	u32 dest=a0;
 
- while(len--)
- {
-  if(PSXM(dest)) PSXMu8(dest)=a1;
-  dest++;
- }
- //memset(Ra0, a1, a2);
- v0 = a0; 
- pc0 = ra;
+	while(len--)
+	{
+		if(PSXM(dest)) PSXMu8(dest)=a1;
+		dest++;
+	}
+	//memset(Ra0, a1, a2);
+	v0 = a0; 
+	pc0 = ra;
 }
 
 #ifdef MOO
-/*0x2c*/void bios_memmove() {memmove(Ra0, Ra1, a2); v0 = a0; pc0 = ra;}
+/*0x2c*/void bios_memmove() {
+	char *p0 = Ra0, *p1 = Ra1;
+	memmove(p0, p1, a2);
+	v0 = a0;
+	pc0 = ra;
+}
 #endif
 
 /*0x2d*/
-static void bios_memcmp()  
-{
- v0 = memcmp(Ra0, Ra1, a2); 
- pc0 = ra;
+static void bios_memcmp() {
+	char *p0 = Ra0, *p1 = Ra1;
+	v0 = memcmp(p0, p1, a2); 
+	pc0 = ra;
 }
 
 static void bios_memchr() { // 2e
-	void *ret = memchr(Ra0, a1, a2);
-	if (ret != NULL) v0 = (u32)((char*)ret - Ra0) + a0;
+	char *p0 = Ra0;
+	void *ret = memchr(p0, a1, a2);
+	if (ret != NULL) v0 = (u32)((char*)ret - p0) + a0;
 	else v0 = 0;
 	pc0 = ra;
 }
@@ -603,7 +624,8 @@
 }
 
 static void bios_srand() { // 30
-	srand(a0); pc0 = ra;
+	srand(a0);
+	pc0 = ra;
 }
 
 static void bios_malloc() { // 33
@@ -618,7 +640,7 @@
 	   being used.
 	*/
 	while( (a0 > BFLIP32(((malloc_chunk*)PSXM(chunk)) ->size)) ||
-		(BFLIP32( ((malloc_chunk*)PSXM(chunk))->stat  ) == INUSE)
+	       (BFLIP32( ((malloc_chunk*)PSXM(chunk))->stat  ) == INUSE)
 		)
 		chunk=((malloc_chunk*)PSXM(chunk)) -> fd;
 	//printf("%08x\n",chunk);
@@ -649,7 +671,7 @@
 	chunk = (malloc_chunk *)PSXM(heap_addr);
 	chunk->stat = 0;
 	if (((a0 & 0x1fffff) + a1)>= 0x200000) 
-	 chunk->size = BFLIP32(0x1ffffc - (a0 & 0x1fffff));
+		chunk->size = BFLIP32(0x1ffffc - (a0 & 0x1fffff));
 	else chunk->size = BFLIP32(a1);
 	chunk->fd = 0;
 	chunk->bk = 0;
@@ -737,21 +759,21 @@
 
 
 /* gets ev for use with Event */
-#define GetEv() \
-	ev = (a0 >> 24) & 0xf; \
-	if (ev == 0xf) ev = 0x5; \
-	ev*= 32; \
+#define GetEv()					\
+	ev = (a0 >> 24) & 0xf;			\
+	if (ev == 0xf) ev = 0x5;		\
+	ev*= 32;				\
 	ev+= a0&0x1f;
 
 /* gets spec for use with Event */
-#define GetSpec() \
-	spec = 0; \
-	switch (a1) { \
-		case 0x0301: spec = 16; break; \
-		case 0x0302: spec = 17; break; \
-		default: \
-			for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
-			break; \
+#define GetSpec()							\
+	spec = 0;							\
+	switch (a1) {							\
+	case 0x0301: spec = 16; break;					\
+	case 0x0302: spec = 17; break;					\
+	default:							\
+		for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
+		break;							\
 	}
 
 static void bios_DeliverEvent() { // 07
@@ -909,7 +931,7 @@
 	if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
 
 	psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
-						  ((psxRegs.CP0.n.Status & 0x3c) >> 2);
+		((psxRegs.CP0.n.Status & 0x3c) >> 2);
 }
 
 static void bios_ResetEntryInt() { // 18
@@ -932,8 +954,8 @@
 	GetSpec();
 
 	if (Event[ev][spec].status == BFLIP32S(EvStALREADY) &&
-		Event[ev][spec].mode == BFLIP32S(EvMdNOINTR))
-			Event[ev][spec].status = BFLIP32S(EvStACTIVE);
+	    Event[ev][spec].mode == BFLIP32S(EvMdNOINTR))
+		Event[ev][spec].status = BFLIP32S(EvStACTIVE);
 
 	pc0 = ra;
 }
@@ -1302,66 +1324,66 @@
 	int i;
 
 	switch (psxRegs.CP0.n.Cause & 0x3c) {
-		case 0x00: // Interrupt
+	case 0x00: // Interrupt
 #ifdef PSXCPU_LOG
 //			PSXCPU_LOG("interrupt\n");
 #endif
-			SaveRegs();
+		SaveRegs();
 
-			biosInterrupt();
+		biosInterrupt();
 
-			for (i=0; i<8; i++) {
-				if (SysIntRP[i]) {
-					u32 *queue = (u32*)PSXM(SysIntRP[i]);
+		for (i=0; i<8; i++) {
+			if (SysIntRP[i]) {
+				u32 *queue = (u32*)PSXM(SysIntRP[i]);
 
-					s0 = BFLIP32(queue[2]);
-					softCall(BFLIP32(queue[1]));
-				}
+				s0 = BFLIP32(queue[2]);
+				softCall(BFLIP32(queue[1]));
 			}
+		}
 
-			if (jmp_int != NULL) {
-				int i;
+		if (jmp_int != NULL) {
+			int i;
 
-				psxHwWrite32(0x1f801070, 0xffffffff);
+			psxHwWrite32(0x1f801070, 0xffffffff);
 
-				ra = BFLIP32(jmp_int[0]);
-				sp = BFLIP32(jmp_int[1]);
-				fp = BFLIP32(jmp_int[2]);
-				for (i=0; i<8; i++) // s0-s7
-					 psxRegs.GPR.r[16+i] = BFLIP32(jmp_int[3+i]);
-				gp = BFLIP32(jmp_int[11]);
+			ra = BFLIP32(jmp_int[0]);
+			sp = BFLIP32(jmp_int[1]);
+			fp = BFLIP32(jmp_int[2]);
+			for (i=0; i<8; i++) // s0-s7
+				psxRegs.GPR.r[16+i] = BFLIP32(jmp_int[3+i]);
+			gp = BFLIP32(jmp_int[11]);
 
-				v0 = 1;
-				pc0 = ra;
-				return;
-			}
-			psxHwWrite16(0x1f801070, 0);
-			break;
-		case 0x20: // Syscall
+			v0 = 1;
+			pc0 = ra;
+			return;
+		}
+		psxHwWrite16(0x1f801070, 0);
+		break;
+	case 0x20: // Syscall
 #ifdef PSXCPU_LOG
 //			PSXCPU_LOG("syscall exp %x\n", a0);
 #endif
-			switch (a0) {
-				case 1: // EnterCritical - disable irq's
-					psxRegs.CP0.n.Status&=~0x404; break;
-				case 2: // ExitCritical - enable irq's
-					psxRegs.CP0.n.Status|= 0x404; break;
-			}
-			pc0 = psxRegs.CP0.n.EPC + 4;
+		switch (a0) {
+		case 1: // EnterCritical - disable irq's
+			psxRegs.CP0.n.Status&=~0x404; break;
+		case 2: // ExitCritical - enable irq's
+			psxRegs.CP0.n.Status|= 0x404; break;
+		}
+		pc0 = psxRegs.CP0.n.EPC + 4;
 
-			psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
-								  ((psxRegs.CP0.n.Status & 0x3c) >> 2);
-			return;
-		default:
+		psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
+			((psxRegs.CP0.n.Status & 0x3c) >> 2);
+		return;
+	default:
 #ifdef PSXCPU_LOG
-			PSXCPU_LOG("unk exp\n");
+		PSXCPU_LOG("unk exp\n");
 #endif
-			break;
+		break;
 	}
 
 	pc0 = psxRegs.CP0.n.EPC;
 	if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
 
 	psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
-						  ((psxRegs.CP0.n.Status & 0x3c) >> 2);
+		((psxRegs.CP0.n.Status & 0x3c) >> 2);
 }
--- a/src/statusicon/si_ui.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/statusicon/si_ui.c	Wed Dec 19 17:51:50 2007 +0200
@@ -34,6 +34,9 @@
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
 
 static void si_ui_statusicon_popup_timer_start ( GtkWidget * );
 static void si_ui_statusicon_popup_timer_stop ( GtkWidget * );
@@ -139,6 +142,8 @@
       }
       break;
     }
+
+    default: ;
   }
 
   return FALSE;
@@ -330,6 +335,8 @@
   GdkPixbuf *si_pixbuf, *si_scaled_pixbuf;
   gint size = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(image) , "size" ));
   static gchar *wmname = NULL;
+  
+  AUDDBG("WM reported proposed icon size: %d\n", size);
 
   /* sometimes, KDE won't give the correct size-allocation; workaround this */
   if ( wmname == NULL )
@@ -337,8 +344,9 @@
     GdkScreen *screen = gdk_screen_get_default();
     if ( screen != NULL )
       wmname = (gchar*)gdk_x11_screen_get_window_manager_name( screen );
+      AUDDBG("WM name: %s\n", wmname);
   }
-  if ( ( size > 22 ) && ( wmname != NULL ) && ( !strcmp("KWin",wmname) ) )
+  if ( ( size <= 1 || size > 22 ) && ( wmname != NULL ) && !strcmp("KWin",wmname) )
     size = 22;
 
   si_pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)si_xpm );
@@ -354,15 +362,17 @@
 static void
 si_ui_statusicon_cb_image_sizalloc ( GtkWidget * image , GtkAllocation * allocation , gpointer si_applet )
 {
-  GtkOrientation orientation;
+  /*GtkOrientation orientation;*/
   static gint prev_size = 0;
   gint size = 0;
 
-  orientation = _aud_gtk_tray_icon_get_orientation( AUD_GTK_TRAY_ICON(si_applet) );
+  /*orientation = _aud_gtk_tray_icon_get_orientation( AUD_GTK_TRAY_ICON(si_applet) );
   if ( orientation == GTK_ORIENTATION_HORIZONTAL )
     size = allocation->height;
   else
-    size = allocation->width;
+    size = allocation->width;*/
+  
+  size = MAX(allocation->height, allocation->width); /* some WMs doesn't report orientation correctly --asphyx */
 
   if ( prev_size != size )
   {
--- a/src/statusicon/si_ui.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/statusicon/si_ui.h	Wed Dec 19 17:51:50 2007 +0200
@@ -21,12 +21,14 @@
 #ifndef _I_SI_UI_H
 #define _I_SI_UI_H 1
 
-#include "si_ui.h"
+#include <glib.h>
 
 
 void si_ui_statusicon_show( void );
 void si_ui_statusicon_hide( void );
 void si_ui_about_show( void );
+void si_ui_statusicon_enable ( gboolean );
+void si_ui_prefs_show ( void );
 
 
 #endif /* !_I_SI_UI_H */
--- a/src/tta/libtta.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/tta/libtta.c	Wed Dec 19 17:51:50 2007 +0200
@@ -28,6 +28,8 @@
  * information.
  */
 
+/* #define AUD_DEBUG 1 */
+
 #include "config.h"
 
 #include <stdio.h>
@@ -695,18 +697,14 @@
                 tp++;
             }
             if(is_num) {
-#ifdef DEBUG
-                printf("is_num!\n");
-#endif
+                AUDDBG("is_num!\n");
                 tmp = g_malloc0(BYTES(end - ptr + 1));
                 memcpy(tmp, ptr, BYTES(end - ptr));
                 *(tmp + (end - ptr)) = 0; //terminate
                 ptr += end - ptr;
 
                 genre = (id3_ucs4_t *)id3_genre_name((const id3_ucs4_t *)tmp);
-#ifdef DEBUG
-                printf("genre length = %d\n", tta_ucs4len(genre));
-#endif
+                AUDDBG("genre length = %d\n", tta_ucs4len(genre));
                 g_free(tmp);
                 tmp = NULL;
 
@@ -718,10 +716,8 @@
                 *(ret + ret_len) = 0; //terminate
             }
             else { // plain text
-#ifdef DEBUG
-                printf("plain!\n");
-                printf("ret_len = %d\n", ret_len);
-#endif
+                AUDDBG("plain!\n");
+                AUDDBG("ret_len = %d\n", ret_len);
                 memcpy(ret + BYTES(ret_len), ptr, BYTES(end - ptr));
                 ret_len = ret_len + (end - ptr);
                 *(ret + ret_len) = 0; //terminate
@@ -796,9 +792,7 @@
     }
     g_free(string);
     string = NULL;
-#ifdef DEBUG
-    g_print("string = %s\n", rtn);
-#endif
+    AUDDBG("string = %s\n", rtn);
 
     return rtn;
 }
--- a/src/tta/ttadec.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/tta/ttadec.c	Wed Dec 19 17:51:50 2007 +0200
@@ -476,7 +476,7 @@
 	byte *p = buffer;
 	decoder *dec = tta;
 	int *prev = cache;
-	int value, res;
+	int value, value_tmp, res;
 
 	for (res = 0; p < buffer + pcm_buffer_size;) {
 		fltst *fst = &dec->fst;
@@ -529,8 +529,8 @@
 			else if (rice->sum0 > shift_16[rice->k0 + 1])
 			rice->k0++;
 		}
-
-		value = DEC(value);
+		value_tmp = DEC(value);
+		value = value_tmp;
 
 		// decompress stage 1: adaptive hybrid filter
 		hybrid_filter(fst, &value);
--- a/src/vorbis/Makefile	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/vorbis/Makefile	Wed Dec 19 17:51:50 2007 +0200
@@ -1,7 +1,7 @@
 PLUGIN = vorbis${PLUGIN_SUFFIX}
 
 SRCS = configure.c	\
-       fileinfo.c	\
+       vcupdate.c	\
        vcedit.c		\
        vorbis.c
 
--- a/src/vorbis/fileinfo.c	Wed Dec 05 13:35:16 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1084 +0,0 @@
-/*  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; either version 2
- * of the License, or (at your option) any later version.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <unistd.h>
-
-#include <audacious/strings.h>
-#include <audacious/util.h>
-#include <audacious/i18n.h>
-
-#include "vorbis.h"
-#include "vcedit.h"
-
-#include "ogg.xpm"
-
-static struct vte_struct {
-    VFSFile *in;
-    gchar *filename;
-} vte;
-
-static void fail(const gchar * error);
-static void save_cb(GtkWidget * w, gpointer data);
-static void remove_cb(GtkWidget * w, gpointer data);
-static gint init_files(vcedit_state * state);
-static gint close_files(vcedit_state * state);
-
-extern GMutex *vf_mutex;
-static GtkWidget *window = NULL;
-static GList *genre_list = NULL;
-
-static GtkWidget *title_entry, *album_entry, *performer_entry;
-static GtkWidget *tracknumber_entry, *date_entry;
-static GtkWidget *genre_combo, *user_comment_entry;
-#ifdef ALL_VORBIS_TAGS
-static GtkWidget *description_entry, *version_entry, *isrc_entry;
-static GtkWidget *copyright_entry, *organization_entry, *location_entry;
-#endif
-static GtkWidget *rg_track_entry, *rg_album_entry, *rg_track_peak_entry,
-    *rg_album_peak_entry;
-static GtkWidget *rg_track_label, *rg_album_label, *rg_track_peak_label,
-    *rg_album_peak_label;
-static GtkWidget *rg_show_button;
-
-GtkWidget *save_button, *remove_button;
-GtkWidget *rg_frame, *rg_table;
-
-/* From mpg123.c, as no standardized Ogg Vorbis genres exists. */
-static const gchar *vorbis_genres[] = {
-    N_("Blues"), N_("Classic Rock"), N_("Country"), N_("Dance"),
-    N_("Disco"), N_("Funk"), N_("Grunge"), N_("Hip-Hop"),
-    N_("Jazz"), N_("Metal"), N_("New Age"), N_("Oldies"),
-    N_("Other"), N_("Pop"), N_("R&B"), N_("Rap"), N_("Reggae"),
-    N_("Rock"), N_("Techno"), N_("Industrial"), N_("Alternative"),
-    N_("Ska"), N_("Death Metal"), N_("Pranks"), N_("Soundtrack"),
-    N_("Euro-Techno"), N_("Ambient"), N_("Trip-Hop"), N_("Vocal"),
-    N_("Jazz+Funk"), N_("Fusion"), N_("Trance"), N_("Classical"),
-    N_("Instrumental"), N_("Acid"), N_("House"), N_("Game"),
-    N_("Sound Clip"), N_("Gospel"), N_("Noise"), N_("AlternRock"),
-    N_("Bass"), N_("Soul"), N_("Punk"), N_("Space"),
-    N_("Meditative"), N_("Instrumental Pop"),
-    N_("Instrumental Rock"), N_("Ethnic"), N_("Gothic"),
-    N_("Darkwave"), N_("Techno-Industrial"), N_("Electronic"),
-    N_("Pop-Folk"), N_("Eurodance"), N_("Dream"),
-    N_("Southern Rock"), N_("Comedy"), N_("Cult"),
-    N_("Gangsta Rap"), N_("Top 40"), N_("Christian Rap"),
-    N_("Pop/Funk"), N_("Jungle"), N_("Native American"),
-    N_("Cabaret"), N_("New Wave"), N_("Psychedelic"), N_("Rave"),
-    N_("Showtunes"), N_("Trailer"), N_("Lo-Fi"), N_("Tribal"),
-    N_("Acid Punk"), N_("Acid Jazz"), N_("Polka"), N_("Retro"),
-    N_("Musical"), N_("Rock & Roll"), N_("Hard Rock"), N_("Folk"),
-    N_("Folk/Rock"), N_("National Folk"), N_("Swing"),
-    N_("Fast-Fusion"), N_("Bebob"), N_("Latin"), N_("Revival"),
-    N_("Celtic"), N_("Bluegrass"), N_("Avantgarde"),
-    N_("Gothic Rock"), N_("Progressive Rock"),
-    N_("Psychedelic Rock"), N_("Symphonic Rock"), N_("Slow Rock"),
-    N_("Big Band"), N_("Chorus"), N_("Easy Listening"),
-    N_("Acoustic"), N_("Humour"), N_("Speech"), N_("Chanson"),
-    N_("Opera"), N_("Chamber Music"), N_("Sonata"), N_("Symphony"),
-    N_("Booty Bass"), N_("Primus"), N_("Porn Groove"),
-    N_("Satire"), N_("Slow Jam"), N_("Club"), N_("Tango"),
-    N_("Samba"), N_("Folklore"), N_("Ballad"), N_("Power Ballad"),
-    N_("Rhythmic Soul"), N_("Freestyle"), N_("Duet"),
-    N_("Punk Rock"), N_("Drum Solo"), N_("A Cappella"),
-    N_("Euro-House"), N_("Dance Hall"), N_("Goa"),
-    N_("Drum & Bass"), N_("Club-House"), N_("Hardcore"),
-    N_("Terror"), N_("Indie"), N_("BritPop"), N_("Negerpunk"),
-    N_("Polsk Punk"), N_("Beat"), N_("Christian Gangsta Rap"),
-    N_("Heavy Metal"), N_("Black Metal"), N_("Crossover"),
-    N_("Contemporary Christian"), N_("Christian Rock"),
-    N_("Merengue"), N_("Salsa"), N_("Thrash Metal"),
-    N_("Anime"), N_("JPop"), N_("Synthpop")
-};
-
-static const gchar *
-get_comment(vorbis_comment * vc, const gchar * tag)
-{
-    const gchar *value;
-
-    g_return_val_if_fail(tag != NULL, "");
-
-    if (!vc)
-        return "";
-
-    if ((value = vorbis_comment_query(vc, (gchar *) tag, 0)))
-        return value;
-    else
-        return "";
-}
-
-static gboolean
-str_equal_nocase(gconstpointer a,
-                 gconstpointer b)
-{
-    return strcasecmp((const gchar *) a, (const gchar *) b) == 0;
-}
-
-static GHashTable *
-hash_table_from_vorbis_comment(vorbis_comment * vc)
-{
-    GHashTable *table;
-    gint i;
-
-    table = g_hash_table_new_full(g_str_hash, str_equal_nocase,
-                                  g_free, g_free);
-
-    for (i = 0; i < vc->comments; i++) {
-        gchar **frags;
-#ifdef DEBUG
-        g_message(vc->user_comments[i]);
-#endif
-        frags = g_strsplit(vc->user_comments[i], "=", 2);
-      
-        /* FIXME: need more rigorous checks to guard against
-           borqued comments */
-
-        /* No RHS? */
-        if (!frags[1]) frags[1] = g_strdup("");
-
-        g_hash_table_replace(table, frags[0], frags[1]);
-        g_free(frags);
-    }
-
-    return table;
-}
-
-static void
-comment_hash_add_tag(GHashTable * table,
-                     const gchar * tag,
-                     const gchar * value)
-{
-    g_hash_table_replace(table, g_strdup(tag), g_strdup(value));
-}
-
-
-static void
-vorbis_comment_add_swapped(gchar * key,
-                           gchar * value,
-                           vorbis_comment * vc)
-{
-    vorbis_comment_add_tag(vc, key, value);
-}
-
-static void
-hash_table_to_vorbis_comment(vorbis_comment * vc, GHashTable * table)
-{
-    vorbis_comment_clear(vc);
-    g_hash_table_foreach(table, (GHFunc) vorbis_comment_add_swapped,
-                         vc);
-}
-
-
-static void
-fail(const gchar * error)
-{
-    gchar *errorstring;
-    errorstring = g_strdup_printf(_("An error occured:\n%s"), error);
-
-    audacious_info_dialog(_("Error!"), errorstring, _("Ok"), FALSE, NULL, NULL);
-
-    g_free(errorstring);
-    return;
-}
-
-
-static void
-save_cb(GtkWidget * w, gpointer data)
-{
-    const gchar *track_name, *performer, *album_name, *date, *track_number;
-    const gchar *genre, *user_comment;
-#ifdef ALL_VORBIS_TAGS
-    const gchar *description, *version, *isrc, *copyright, *organization;
-    const gchar *location;
-#endif
-    const gchar *rg_track_gain, *rg_album_gain, *rg_track_peak, *rg_album_peak;
-
-    GHashTable *comment_hash;
-
-    vcedit_state *state;
-    vorbis_comment *comment;
-
-    if (!g_strncasecmp(vte.filename, "http://", 7))
-        return;
-    if (!g_strncasecmp(vte.filename, "https://", 8))
-        return;
-
-    state = vcedit_new_state();
-
-    g_mutex_lock(vf_mutex);
-    if (init_files(state) < 0) {
-        fail(_("Failed to modify tag (open)"));
-        goto close;
-    }
-
-    comment = vcedit_comments(state);
-    comment_hash = hash_table_from_vorbis_comment(comment);
-
-    track_name = gtk_entry_get_text(GTK_ENTRY(title_entry));
-    performer = gtk_entry_get_text(GTK_ENTRY(performer_entry));
-    album_name = gtk_entry_get_text(GTK_ENTRY(album_entry));
-    track_number = gtk_entry_get_text(GTK_ENTRY(tracknumber_entry));
-    genre = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(genre_combo)->entry));
-    date = gtk_entry_get_text(GTK_ENTRY(date_entry));
-    user_comment = gtk_entry_get_text(GTK_ENTRY(user_comment_entry));
-#ifdef ALL_VORBIS_TAGS
-    location = gtk_entry_get_text(GTK_ENTRY(location_entry));
-    description = gtk_entry_get_text(GTK_ENTRY(description_entry));
-    version = gtk_entry_get_text(GTK_ENTRY(version_entry));
-    isrc = gtk_entry_get_text(GTK_ENTRY(isrc_entry));
-    organization = gtk_entry_get_text(GTK_ENTRY(organization_entry));
-    copyright = gtk_entry_get_text(GTK_ENTRY(copyright_entry));
-#endif
-    rg_track_gain = gtk_entry_get_text(GTK_ENTRY(rg_track_entry));
-    rg_album_gain = gtk_entry_get_text(GTK_ENTRY(rg_album_entry));
-    rg_track_peak = gtk_entry_get_text(GTK_ENTRY(rg_track_peak_entry));
-    rg_album_peak = gtk_entry_get_text(GTK_ENTRY(rg_album_peak_entry));
-
-    comment_hash_add_tag(comment_hash, "title", track_name);
-    comment_hash_add_tag(comment_hash, "artist", performer);
-    comment_hash_add_tag(comment_hash, "album", album_name);
-    comment_hash_add_tag(comment_hash, "tracknumber", track_number);
-    comment_hash_add_tag(comment_hash, "genre", genre);
-    comment_hash_add_tag(comment_hash, "date", date);
-    comment_hash_add_tag(comment_hash, "comment", user_comment);
-
-#ifdef ALL_VORBIS_TAGS
-    comment_hash_add_tag(comment_hash, "location", location);
-    comment_hash_add_tag(comment_hash, "description", description);
-    comment_hash_add_tag(comment_hash, "version", version);
-    comment_hash_add_tag(comment_hash, "isrc", isrc);
-    comment_hash_add_tag(comment_hash, "organization", organization);
-    comment_hash_add_tag(comment_hash, "copyright", copyright);
-#endif
-
-    comment_hash_add_tag(comment_hash, "replaygain_track_gain", rg_track_gain);
-    comment_hash_add_tag(comment_hash, "replaygain_album_gain", rg_album_gain);
-    comment_hash_add_tag(comment_hash, "replaygain_track_peak", rg_track_peak);
-    comment_hash_add_tag(comment_hash, "replaygain_album_peak", rg_album_peak);
-
-    hash_table_to_vorbis_comment(comment, comment_hash);
-    g_hash_table_destroy(comment_hash);
-
-    if (close_files(state) < 0)
-        fail(_("Failed to modify tag (close)"));
-    else {
-        gtk_widget_set_sensitive(save_button, FALSE);
-        gtk_widget_set_sensitive(remove_button, TRUE);
-    }
-
-
-  close:
-    vcedit_clear(state);
-    g_mutex_unlock(vf_mutex);
-}
-
-static void
-remove_cb(GtkWidget * w, gpointer data)
-{
-    vcedit_state *state;
-    vorbis_comment *comment;
-
-    if (!g_strncasecmp(vte.filename, "http://", 7))
-        return;
-    if (!g_strncasecmp(vte.filename, "https://", 8))
-        return;
-
-    state = vcedit_new_state();
-
-    g_mutex_lock(vf_mutex);
-    if (init_files(state) < 0) {
-        fail(_("Failed to modify tag"));
-        goto close;
-    }
-
-    comment = vcedit_comments(state);
-
-    vorbis_comment_clear(comment);
-
-    if (close_files(state) < 0) {
-        fail(_("Failed to modify tag"));
-    }
-    else {
-        gtk_entry_set_text(GTK_ENTRY(title_entry), "");
-        gtk_entry_set_text(GTK_ENTRY(album_entry), "");
-        gtk_entry_set_text(GTK_ENTRY(performer_entry), "");
-        gtk_entry_set_text(GTK_ENTRY(tracknumber_entry), "");
-        gtk_entry_set_text(GTK_ENTRY(date_entry), "");
-        gtk_entry_set_text(GTK_ENTRY(genre_combo), "");
-        gtk_entry_set_text(GTK_ENTRY(user_comment_entry), "");
-    }
-
-  close:
-    vcedit_clear(state);
-    g_mutex_unlock(vf_mutex);
-/*     gtk_widget_destroy(window); */
-}
-
-static void
-rg_show_cb(GtkWidget * w, gpointer data)
-{
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rg_show_button))) {
-        gtk_widget_show(rg_frame);
-    }
-    else {
-        gtk_widget_hide(rg_frame);
-    }
-}
-
-static gint
-init_files(vcedit_state * state)
-{
-    if ((vte.in = aud_vfs_fopen(vte.filename, "rb")) == NULL) {
-#ifdef DEBUG
-        g_message("fileinfo.c: couldn't open file %s", vte.filename);
-#endif
-        return -1;
-    }
-
-    if (vcedit_open(state, vte.in) < 0) {
-#ifdef DEBUG
-        g_message("fileinfo.c: couldn't open file for editing %s",
-                  vte.filename);
-#endif
-        aud_vfs_fclose(vte.in);
-        return -1;
-    }
-
-#ifdef DEBUG
-    g_message("fileinfo.c: file successfully opened for editing %s",
-              vte.filename);
-#endif
-
-    return 0;
-}
-
-static gint
-close_files(vcedit_state * state)
-{
-    gint retval = 0, ofh;
-    gchar *tmpfn;
-    VFSFile *out;
-
-    tmpfn = g_strdup_printf("%s.XXXXXX", vte.filename);
-
-    if ((ofh = mkstemp(tmpfn)) < 0) {
-        g_free(tmpfn);
-        aud_vfs_fclose(vte.in);
-#ifdef DEBUG
-        g_critical("fileinfo.c: couldn't create temp file");
-#endif
-        return -1;
-    }
-    else {
-#ifdef DEBUG
-        g_message("fileinfo.c: created temp file %s", tmpfn);
-#endif
-    }
-
-    if ((out = aud_vfs_fopen(tmpfn, "wb")) == NULL) {
-        close(ofh);
-        remove(tmpfn);
-        g_free(tmpfn);
-        aud_vfs_fclose(vte.in);
-#ifdef DEBUG
-        g_critical("fileinfo.c: couldn't open temp file");
-#endif
-        return -1;
-    }
-    else {
-#ifdef DEBUG
-        g_message("fileinfo.c: opened temp file %s", tmpfn);
-#endif
-    }
-
-    if (vcedit_write(state, out) < 0) {
-#ifdef DEBUG
-        g_warning("vcedit_write: %s", state->lasterror);
-#endif
-        retval = -1;
-    }
-
-    aud_vfs_fclose(vte.in);
-
-    if (aud_vfs_fclose(out) != 0) {
-#ifdef DEBUG
-        g_critical("fileinfo.c: couldn't close out file");
-#endif
-        retval = -1;
-    }
-    else {
-#ifdef DEBUG
-        g_message("fileinfo.c: outfile closed");
-#endif
-    }
-
-    if (retval < 0 || rename(tmpfn, vte.filename) < 0) {
-        remove(tmpfn);
-        retval = -1;
-#ifdef DEBUG
-        g_critical("fileinfo.c: couldn't rename file");
-#endif
-    }
-    else {
-#ifdef DEBUG
-        g_message("fileinfo.c: file %s renamed successfully to %s", tmpfn,
-                  vte.filename);
-#endif
-    }
-
-    g_free(tmpfn);
-    return retval;
-}
-
-
-static void
-label_set_text(GtkLabel * label, const gchar * format, ...)
-{
-    va_list args;
-    gchar *text;
-
-    va_start(args, format);
-    text = g_strdup_vprintf(format, args);
-    va_end(args);
-
-    gtk_label_set_text(label, text);
-    g_free(text);
-}
-
-void
-change_buttons(void)
-{
-    gtk_widget_set_sensitive(GTK_WIDGET(save_button), TRUE);
-}
-
-
-/***********************************************************************/
-
-void
-vorbis_file_info_box(gchar * filename)
-{
-    gchar *filename_utf8, *title;
-    const gchar *rg_track_gain, *rg_track_peak;
-    const gchar *rg_album_gain, *rg_album_peak;
-
-    gint time, minutes, seconds, bitrate, rate, channels, filesize;
-    gsize i;
-
-    OggVorbis_File vf;
-    vorbis_info *vi;
-    vorbis_comment *comment = NULL;
-
-    VFSVorbisFile *fh = g_new0(VFSVorbisFile, 1);
-
-    gboolean clear_vf = FALSE;
-
-    GtkWidget *pixmapwid;
-    GdkPixbuf *pixbuf;
-    PangoAttrList *attrs;
-    PangoAttribute *attr;
-
-    GtkWidget *boxx;
-    GtkWidget *img;
-    GtkWidget *test_table;
-
-    static GtkWidget *info_frame, *info_box, *bitrate_label, *rate_label;
-    static GtkWidget *bitrate_label_val, *rate_label_val;
-
-    static GtkWidget *channel_label, *length_label, *filesize_label;
-    static GtkWidget *channel_label_val, *length_label_val,
-        *filesize_label_val;
-
-    static GtkWidget *filename_entry, *tag_frame;
-
-    g_free(vte.filename);
-    vte.filename = g_strdup(filename);
-
-    if (!window) {
-        GtkWidget *hbox, *label, *filename_hbox, *vbox, *left_vbox;
-        GtkWidget *table, *bbox, *cancel_button;
-
-        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-        gtk_window_set_type_hint(GTK_WINDOW(window),
-                                 GDK_WINDOW_TYPE_HINT_DIALOG);
-        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
-        g_signal_connect(G_OBJECT(window), "destroy",
-                         G_CALLBACK(gtk_widget_destroyed), &window);
-        gtk_container_set_border_width(GTK_CONTAINER(window), 10);
-
-        vbox = gtk_vbox_new(FALSE, 10);
-        gtk_container_add(GTK_CONTAINER(window), vbox);
-
-        filename_hbox = gtk_hbox_new(FALSE, 5);
-        gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0);
-
-        pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)
-                                              gnome_mime_audio_ogg_xpm);
-        pixmapwid = gtk_image_new_from_pixbuf(pixbuf);
-        gtk_misc_set_alignment(GTK_MISC(pixmapwid), 0, 0);
-        gtk_box_pack_start(GTK_BOX(filename_hbox), pixmapwid, FALSE, FALSE,
-                           0);
-
-        attrs = pango_attr_list_new();
-
-        attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
-        attr->start_index = 0;
-        attr->end_index = -1;
-        pango_attr_list_insert(attrs, attr);
-
-        label = gtk_label_new(_("Name:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, FALSE, 0);
-
-        filename_entry = gtk_entry_new();
-        gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
-        gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE,
-                           TRUE, 0);
-
-        hbox = gtk_hbox_new(FALSE, 10);
-        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
-
-        left_vbox = gtk_table_new(4, 7, FALSE);
-        gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0);
-
-        tag_frame = gtk_frame_new(_(" Ogg Vorbis Tag "));
-        gtk_table_attach(GTK_TABLE(left_vbox), tag_frame, 2, 4, 0, 1,
-                         GTK_FILL, GTK_FILL, 0, 4);
-
-        table = gtk_table_new(16, 6, FALSE);
-        gtk_container_set_border_width(GTK_CONTAINER(table), 5);
-        gtk_container_add(GTK_CONTAINER(tag_frame), table);
-
-        label = gtk_label_new(_("Title:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        title_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Artist:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        performer_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), performer_entry, 1, 4, 1, 2,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Album:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        album_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Comment:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        user_comment_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), user_comment_entry, 1, 4, 3,
-                         4, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Date:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        date_entry = gtk_entry_new();
-        gtk_widget_set_size_request(date_entry, 60, -1);
-        gtk_table_attach(GTK_TABLE(table), date_entry, 1, 2, 4, 5,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Track number:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        tracknumber_entry = gtk_entry_new_with_max_length(4);
-        gtk_widget_set_size_request(tracknumber_entry, 20, -1);
-        gtk_table_attach(GTK_TABLE(table), tracknumber_entry, 3, 4, 4,
-                         5, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Genre:"));
-        gtk_label_set_attributes(GTK_LABEL(label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        genre_combo = gtk_combo_new();
-        if (!genre_list) {
-            for (i = 0; i < G_N_ELEMENTS(vorbis_genres); i++)
-                genre_list = g_list_prepend(genre_list, _(vorbis_genres[i]));
-            genre_list = g_list_sort(genre_list, (GCompareFunc) g_strcasecmp);
-        }
-        gtk_combo_set_popdown_strings(GTK_COMBO(genre_combo), genre_list);
-        gtk_table_attach(GTK_TABLE(table), genre_combo, 1, 4, 5, 6,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-#ifdef ALL_VORBIS_TAGS
-        label = gtk_label_new(_("Description:"));
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        description_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), description_entry, 1, 4, 6,
-                         7, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Location:"));
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 7, 8,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        location_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), location_entry, 1, 4, 7, 8,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Version:"));
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 8, 9,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        version_entry = gtk_entry_new();
-        gtk_widget_set_size_request(version_entry, 60, -1);
-        gtk_table_attach(GTK_TABLE(table), version_entry, 1, 2, 8, 9,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("ISRC number:"));
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 2, 3, 8, 9,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        isrc_entry = gtk_entry_new();
-        gtk_widget_set_size_request(isrc_entry, 20, -1);
-        gtk_table_attach(GTK_TABLE(table), isrc_entry, 3, 4, 8, 9,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Organization:"));
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 9, 10,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        organization_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), organization_entry, 1, 4, 9,
-                         10, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        label = gtk_label_new(_("Copyright:"));
-        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 10, 11,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        copyright_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(table), copyright_entry, 1, 4, 10,
-                         11, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-#endif
-        boxx = gtk_hbutton_box_new();
-        gtk_hbutton_box_set_layout_default(GTK_BUTTONBOX_SPREAD);
-
-        remove_button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
-        g_signal_connect_swapped(G_OBJECT(remove_button),
-                                 "clicked", G_CALLBACK(remove_cb), NULL);
-        gtk_container_add(GTK_CONTAINER(boxx), remove_button);
-
-        save_button = gtk_button_new_from_stock(GTK_STOCK_SAVE);
-        g_signal_connect(G_OBJECT(save_button), "clicked",
-                         G_CALLBACK(save_cb), NULL);
-        gtk_container_add(GTK_CONTAINER(boxx), save_button);
-
-        gtk_table_attach(GTK_TABLE(table), boxx, 0, 5, 6, 7, GTK_FILL, 0,
-                         0, 8);
-
-        rg_show_button = gtk_toggle_button_new();
-        img = gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD,
-                                       GTK_ICON_SIZE_MENU);
-        gtk_container_add(GTK_CONTAINER(rg_show_button), img);
-        g_signal_connect(G_OBJECT(rg_show_button), "toggled",
-                         G_CALLBACK(rg_show_cb), NULL);
-
-        gtk_table_attach(GTK_TABLE(left_vbox), rg_show_button, 4, 5, 0, 2,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 5, 5);
-
-        rg_frame = gtk_frame_new(_(" Ogg Vorbis ReplayGain "));
-        gtk_table_attach(GTK_TABLE(left_vbox), rg_frame, 5, 6, 0, 4,
-                         GTK_FILL, GTK_FILL, 0, 4);
-        rg_table = gtk_table_new(16, 4, FALSE);
-        gtk_container_add(GTK_CONTAINER(rg_frame), GTK_WIDGET(rg_table));
-
-        rg_track_label = gtk_label_new(_("Track gain:"));
-        gtk_misc_set_alignment(GTK_MISC(rg_track_label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(rg_table), rg_track_label, 5, 6, 0, 1,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        rg_track_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(rg_table), rg_track_entry, 6, 7, 0,
-                         1, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        rg_track_peak_label = gtk_label_new(_("Track peak:"));
-        gtk_misc_set_alignment(GTK_MISC(rg_track_peak_label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(rg_table), rg_track_peak_label, 5, 6, 1,
-                         2, GTK_FILL, GTK_FILL, 5, 5);
-
-        rg_track_peak_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(rg_table), rg_track_peak_entry, 6, 7, 1,
-                         2, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-
-        rg_album_label = gtk_label_new(_("Album gain:"));
-        gtk_misc_set_alignment(GTK_MISC(rg_album_label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(rg_table), rg_album_label, 5, 6, 2, 3,
-                         GTK_FILL, GTK_FILL, 5, 5);
-
-        rg_album_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(rg_table), rg_album_entry, 6, 7, 2,
-                         3, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        rg_album_peak_label = gtk_label_new(_("Album peak:"));
-        gtk_misc_set_alignment(GTK_MISC(rg_album_peak_label), 1, 0.5);
-        gtk_table_attach(GTK_TABLE(rg_table), rg_album_peak_label, 5, 6, 3,
-                         4, GTK_FILL, GTK_FILL, 5, 5);
-
-        rg_album_peak_entry = gtk_entry_new();
-        gtk_table_attach(GTK_TABLE(rg_table), rg_album_peak_entry, 6, 7, 3,
-                         4, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-                         GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
-
-        bbox = gtk_hbutton_box_new();
-        gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
-        gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
-        gtk_table_attach(GTK_TABLE(left_vbox), bbox, 0, 4, 1, 2, GTK_FILL,
-                         0, 0, 8);
-
-        cancel_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
-        g_signal_connect_swapped(G_OBJECT(cancel_button),
-                                 "clicked",
-                                 G_CALLBACK(gtk_widget_destroy),
-                                 G_OBJECT(window));
-        GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
-        gtk_box_pack_start(GTK_BOX(bbox), cancel_button, TRUE, TRUE, 0);
-        gtk_widget_grab_default(cancel_button);
-
-
-        gtk_table_set_col_spacing(GTK_TABLE(left_vbox), 1, 10);
-
-
-        info_frame = gtk_frame_new(_(" Ogg Vorbis Info "));
-        gtk_table_attach(GTK_TABLE(left_vbox), info_frame, 0, 2, 0, 1,
-                         GTK_FILL, GTK_FILL, 0, 4);
-
-        info_box = gtk_vbox_new(FALSE, 5);
-        gtk_container_add(GTK_CONTAINER(info_frame), info_box);
-        gtk_container_set_border_width(GTK_CONTAINER(info_box), 10);
-        gtk_box_set_spacing(GTK_BOX(info_box), 0);
-
-        /* FIXME: Obvious... */
-        test_table = gtk_table_new(2, 10, FALSE);
-        gtk_container_set_border_width(GTK_CONTAINER(test_table), 0);
-        gtk_container_add(GTK_CONTAINER(info_box), test_table);
-
-
-        bitrate_label = gtk_label_new(_("Bit rate:"));
-        gtk_label_set_attributes(GTK_LABEL(bitrate_label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(bitrate_label), 1, 0.5);
-        gtk_label_set_justify(GTK_LABEL(bitrate_label), GTK_JUSTIFY_RIGHT);
-        gtk_table_attach(GTK_TABLE(test_table), bitrate_label, 0, 1, 0, 1,
-                         GTK_FILL, GTK_FILL, 5, 2);
-
-        bitrate_label_val = gtk_label_new("");
-        gtk_misc_set_alignment(GTK_MISC(bitrate_label_val), 0, 0);
-        gtk_label_set_justify(GTK_LABEL(bitrate_label_val), GTK_JUSTIFY_LEFT);
-        gtk_table_attach(GTK_TABLE(test_table), bitrate_label_val, 1, 2, 0,
-                         1, GTK_FILL, GTK_FILL, 10, 2);
-
-        rate_label = gtk_label_new(_("Sample rate:"));
-        gtk_label_set_attributes(GTK_LABEL(rate_label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(rate_label), 1, 0.5);
-        gtk_label_set_justify(GTK_LABEL(rate_label), GTK_JUSTIFY_RIGHT);
-        gtk_table_attach(GTK_TABLE(test_table), rate_label, 0, 1, 1, 2,
-                         GTK_FILL, GTK_FILL, 5, 2);
-
-        rate_label_val = gtk_label_new("");
-        gtk_misc_set_alignment(GTK_MISC(rate_label_val), 0, 0);
-        gtk_label_set_justify(GTK_LABEL(rate_label_val), GTK_JUSTIFY_LEFT);
-        gtk_table_attach(GTK_TABLE(test_table), rate_label_val, 1, 2, 1, 2,
-                         GTK_FILL, GTK_FILL, 10, 2);
-
-        channel_label = gtk_label_new(_("Channels:"));
-        gtk_label_set_attributes(GTK_LABEL(channel_label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(channel_label), 1, 0.5);
-        gtk_label_set_justify(GTK_LABEL(channel_label), GTK_JUSTIFY_RIGHT);
-        gtk_table_attach(GTK_TABLE(test_table), channel_label, 0, 1, 2, 3,
-                         GTK_FILL, GTK_FILL, 5, 2);
-
-        channel_label_val = gtk_label_new("");
-        gtk_misc_set_alignment(GTK_MISC(channel_label_val), 0, 0);
-        gtk_label_set_justify(GTK_LABEL(channel_label_val), GTK_JUSTIFY_LEFT);
-        gtk_table_attach(GTK_TABLE(test_table), channel_label_val, 1, 2, 2,
-                         3, GTK_FILL, GTK_FILL, 10, 2);
-
-        length_label = gtk_label_new(_("Length:"));
-        gtk_label_set_attributes(GTK_LABEL(length_label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(length_label), 1, 0.5);
-        gtk_label_set_justify(GTK_LABEL(length_label), GTK_JUSTIFY_RIGHT);
-        gtk_table_attach(GTK_TABLE(test_table), length_label, 0, 1, 3, 4,
-                         GTK_FILL, GTK_FILL, 5, 2);
-
-        length_label_val = gtk_label_new("");
-        gtk_misc_set_alignment(GTK_MISC(length_label_val), 0, 0);
-        gtk_label_set_justify(GTK_LABEL(length_label_val), GTK_JUSTIFY_LEFT);
-        gtk_table_attach(GTK_TABLE(test_table), length_label_val, 1, 2, 3,
-                         4, GTK_FILL, GTK_FILL, 10, 2);
-
-        filesize_label = gtk_label_new(_("File size:"));
-        gtk_label_set_attributes(GTK_LABEL(filesize_label), attrs);
-        gtk_misc_set_alignment(GTK_MISC(filesize_label), 1, 0.5);
-        gtk_label_set_justify(GTK_LABEL(filesize_label), GTK_JUSTIFY_RIGHT);
-        gtk_table_attach(GTK_TABLE(test_table), filesize_label, 0, 1, 4, 5,
-                         GTK_FILL, GTK_FILL, 5, 2);
-
-        filesize_label_val = gtk_label_new("");
-        gtk_misc_set_alignment(GTK_MISC(filesize_label_val), 0, 0);
-        gtk_label_set_justify(GTK_LABEL(filesize_label_val),
-                              GTK_JUSTIFY_LEFT);
-        gtk_table_attach(GTK_TABLE(test_table), filesize_label_val, 1, 2,
-                         4, 5, GTK_FILL, GTK_FILL, 10, 2);
-
-        pango_attr_list_unref(attrs);
-    }
-    else
-        gtk_window_present(GTK_WINDOW(window));
-
-    if (!g_strncasecmp(vte.filename, "http://", 7)
-        || !g_strncasecmp(vte.filename, "https://", 8))
-        gtk_widget_set_sensitive(tag_frame, FALSE);
-    else
-        gtk_widget_set_sensitive(tag_frame, TRUE);
-
-    gtk_label_set_text(GTK_LABEL(bitrate_label), _("Bit rate:"));
-    gtk_label_set_text(GTK_LABEL(bitrate_label_val), _("N/A"));
-
-    gtk_label_set_text(GTK_LABEL(rate_label), _("Sample rate:"));
-    gtk_label_set_text(GTK_LABEL(rate_label_val), _("N/A"));
-
-    gtk_label_set_text(GTK_LABEL(channel_label), _("Channels:"));
-    gtk_label_set_text(GTK_LABEL(channel_label_val), _("N/A"));
-
-    gtk_label_set_text(GTK_LABEL(length_label), _("Length:"));
-    gtk_label_set_text(GTK_LABEL(length_label_val), _("N/A"));
-
-    gtk_label_set_text(GTK_LABEL(filesize_label), _("File size:"));
-    gtk_label_set_text(GTK_LABEL(filesize_label_val), _("N/A"));
-
-    if ((fh->fd = aud_vfs_fopen(vte.filename, "r")) != NULL) {
-        g_mutex_lock(vf_mutex);
-
-        if (ov_open_callbacks(fh, &vf, NULL, 0, vorbis_callbacks) == 0) {
-            comment = ov_comment(&vf, -1);
-            if ((vi = ov_info(&vf, 0)) != NULL) {
-                bitrate = vi->bitrate_nominal / 1000;
-                rate = vi->rate;
-                channels = vi->channels;
-                clear_vf = TRUE;
-                gtk_widget_set_sensitive(GTK_WIDGET(save_button), FALSE);
-                gtk_widget_set_sensitive(GTK_WIDGET(remove_button), TRUE);
-            }
-            else {
-                bitrate = 0;
-                rate = 0;
-                channels = 0;
-                gtk_widget_set_sensitive(GTK_WIDGET(save_button), FALSE);
-                gtk_widget_set_sensitive(GTK_WIDGET(remove_button), FALSE);
-            }
-
-            time = ov_time_total(&vf, -1);
-            minutes = time / 60;
-            seconds = time % 60;
-            aud_vfs_fseek(fh->fd, 0, SEEK_END);
-            filesize = aud_vfs_ftell(fh->fd);
-
-            label_set_text(GTK_LABEL(bitrate_label_val),
-                           _("%d KBit/s (nominal)"), bitrate);
-            label_set_text(GTK_LABEL(rate_label_val), _("%d Hz"), rate);
-            label_set_text(GTK_LABEL(channel_label_val), _("%d"), channels);
-            label_set_text(GTK_LABEL(length_label_val),
-                           _("%d:%.2d"), minutes, seconds);
-            label_set_text(GTK_LABEL(filesize_label_val),
-                           _("%d Bytes"), filesize);
-
-        }
-        else
-            aud_vfs_fclose(fh->fd);
-    }
-
-    rg_track_gain = get_comment(comment, "replaygain_track_gain");
-    if (*rg_track_gain == '\0')
-        rg_track_gain = get_comment(comment, "rg_radio");   /* Old */
-
-    rg_album_gain = get_comment(comment, "replaygain_album_gain");
-    if (*rg_album_gain == '\0')
-        rg_album_gain = get_comment(comment, "rg_audiophile");  /* Old */
-
-    rg_track_peak = get_comment(comment, "replaygain_track_peak");
-    if (*rg_track_peak == '\0')
-        rg_track_peak = get_comment(comment, "rg_peak");    /* Old */
-
-    rg_album_peak = get_comment(comment, "replaygain_album_peak");  /* Old had no album peak */
-
-    /* Fill it all in .. */
-    gtk_entry_set_text(GTK_ENTRY(title_entry),
-                       get_comment(comment, "title"));
-    gtk_entry_set_text(GTK_ENTRY(performer_entry),
-                       get_comment(comment, "artist"));
-    gtk_entry_set_text(GTK_ENTRY(album_entry),
-                       get_comment(comment, "album"));
-    gtk_entry_set_text(GTK_ENTRY(user_comment_entry),
-                       get_comment(comment, "comment"));
-    gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(genre_combo)->entry), 
-                       get_comment(comment, "genre"));
-    gtk_entry_set_text(GTK_ENTRY(tracknumber_entry),
-                       get_comment(comment, "tracknumber"));
-    gtk_entry_set_text(GTK_ENTRY(date_entry),
-                       get_comment(comment, "date"));
-#ifdef ALL_VORBIS_TAGS
-    gtk_entry_set_text(GTK_ENTRY(version_entry),
-                       get_comment(comment, "version"));
-    gtk_entry_set_text(GTK_ENTRY(description_entry),
-                       get_comment(comment, "description"));
-    gtk_entry_set_text(GTK_ENTRY(organization_entry),
-                       get_comment(comment, "organization"));
-    gtk_entry_set_text(GTK_ENTRY(copyright_entry),
-                       get_comment(comment, "copyright"));
-    gtk_entry_set_text(GTK_ENTRY(isrc_entry),
-                       get_comment(comment, "isrc"));
-    gtk_entry_set_text(GTK_ENTRY(location_entry),
-                       get_comment(comment, "location"));
-#endif
-    {
-        gchar *realfn = NULL;
-        realfn = g_filename_from_uri(vte.filename, NULL, NULL);
-        filename_utf8 = aud_filename_to_utf8(realfn ? realfn : vte.filename);
-        g_free(realfn); realfn = NULL;
-    }
-
-    title = g_strdup_printf(_("%s - Audacious"), g_basename(filename_utf8));
-    gtk_window_set_title(GTK_WINDOW(window), title);
-    g_free(title);
-
-    gtk_entry_set_text(GTK_ENTRY(filename_entry), filename_utf8);
-    gtk_editable_set_position(GTK_EDITABLE(filename_entry), -1);
-
-    g_free(filename_utf8);
-
-    gtk_entry_set_text(GTK_ENTRY(rg_track_entry), rg_track_gain);
-    gtk_entry_set_text(GTK_ENTRY(rg_album_entry), rg_album_gain);
-    gtk_entry_set_text(GTK_ENTRY(rg_track_peak_entry), rg_track_peak);
-    gtk_editable_set_position(GTK_EDITABLE(rg_track_peak_entry), -1);
-    gtk_entry_set_text(GTK_ENTRY(rg_album_peak_entry), rg_album_peak);
-    gtk_editable_set_position(GTK_EDITABLE(rg_album_peak_entry), -1);
-
-/*    if (*rg_track_gain == '\0' && *rg_album_gain == '\0' &&
-        *rg_track_peak == '\0' && *rg_album_peak == '\0') {
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rg_show_button),
-                                     FALSE);
-    }
-    else
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rg_show_button),
-                                     TRUE);*/
-
-    /* ov_clear closes the file */
-    if (clear_vf) ov_clear(&vf);
-    g_mutex_unlock(vf_mutex);
-
-
-    gtk_widget_set_sensitive(tag_frame, aud_vfs_is_writeable(vte.filename));
-
-    g_signal_connect_swapped(title_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(performer_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(album_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(date_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(user_comment_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(tracknumber_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(GTK_COMBO(genre_combo)->entry, "changed",
-                             G_CALLBACK(change_buttons), save_button);
-    g_signal_connect_swapped(rg_track_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(rg_track_peak_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(rg_album_entry, "changed", change_buttons,
-                             save_button);
-    g_signal_connect_swapped(rg_album_peak_entry, "changed", change_buttons,
-                             save_button);
-
-    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
-    gtk_widget_show_all(window);
-    gtk_widget_hide(rg_frame);
-
-    gtk_widget_set_sensitive(save_button, FALSE);
-    gtk_widget_set_sensitive(remove_button, FALSE);
-
-    g_free(fh); // see vorbis.c ovcb_close() --yaz
-}
--- a/src/vorbis/ogg.xpm	Wed Dec 05 13:35:16 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,576 +0,0 @@
-/* XPM */
-static char * gnome_mime_audio_ogg_xpm[] = {
-"48 52 521 2",
-"  	c None",
-". 	c #000000",
-"+ 	c #232323",
-"@ 	c #1F1F1F",
-"# 	c #DADADA",
-"$ 	c #FFFFFF",
-"% 	c #F6F6F6",
-"& 	c #CFCFCF",
-"* 	c #707070",
-"= 	c #FEFEFE",
-"- 	c #FBFBFB",
-"; 	c #EDEDED",
-"> 	c #C0C0C0",
-", 	c #F7F7F7",
-"' 	c #D7D7D7",
-") 	c #F1F1F1",
-"! 	c #B7B7B7",
-"~ 	c #E2E2E2",
-"{ 	c #D2D2D2",
-"] 	c #AEAEAE",
-"^ 	c #070707",
-"/ 	c #ABABAB",
-"( 	c #FDFDFD",
-"_ 	c #FCFCFC",
-": 	c #B8B8B8",
-"< 	c #FAFAFA",
-"[ 	c #DCDCDC",
-"} 	c #A4A4A3",
-"| 	c #0E0E0E",
-"1 	c #B1B1B1",
-"2 	c #BEBEBE",
-"3 	c #F5F5F5",
-"4 	c #E5E5E5",
-"5 	c #C3C3C3",
-"6 	c #6F6F6F",
-"7 	c #2A2A2A",
-"8 	c #2C2C2C",
-"9 	c #2E2E2E",
-"0 	c #5B5B5B",
-"a 	c #F9F9F9",
-"b 	c #F5F5F4",
-"c 	c #B5B5B5",
-"d 	c #CBCBCB",
-"e 	c #A5A5A5",
-"f 	c #A9A9A9",
-"g 	c #CDCDCD",
-"h 	c #E9E9E9",
-"i 	c #525253",
-"j 	c #FBFCFD",
-"k 	c #F3F6F9",
-"l 	c #B7CADC",
-"m 	c #90A5B9",
-"n 	c #7E92A5",
-"o 	c #7E90A3",
-"p 	c #667684",
-"q 	c #657583",
-"r 	c #53606D",
-"s 	c #292A2A",
-"t 	c #FAFAF9",
-"u 	c #F4F4F4",
-"v 	c #ACACAC",
-"w 	c #ECECEC",
-"x 	c #C2C2C2",
-"y 	c #C9C9C8",
-"z 	c #A8A8A8",
-"A 	c #D5D5D5",
-"B 	c #BCBCBC",
-"C 	c #BDBDBD",
-"D 	c #F0F0F0",
-"E 	c #90969B",
-"F 	c #181818",
-"G 	c #212121",
-"H 	c #363636",
-"I 	c #292929",
-"J 	c #293036",
-"K 	c #4D5964",
-"L 	c #444445",
-"M 	c #FCFCFB",
-"N 	c #F4F4F3",
-"O 	c #515151",
-"P 	c #474747",
-"Q 	c #464645",
-"R 	c #464646",
-"S 	c #5D5D5C",
-"T 	c #E1E1E1",
-"U 	c #D1D1D1",
-"V 	c #959BA2",
-"W 	c #282828",
-"X 	c #858585",
-"Y 	c #595959",
-"Z 	c #2D2D2D",
-"` 	c #555F68",
-" .	c #F8F8F8",
-"..	c #F2F2F2",
-"+.	c #F3F3F3",
-"@.	c #AAAAAA",
-"#.	c #A0A09F",
-"$.	c #8A8A8A",
-"%.	c #7A7A7A",
-"&.	c #6C6C6C",
-"*.	c #454545",
-"=.	c #B0B0B0",
-"-.	c #939393",
-";.	c #F7F9FB",
-">.	c #1B1C1C",
-",.	c #333333",
-"'.	c #7F7F7F",
-").	c #BABABA",
-"!.	c #636363",
-"~.	c #5A6976",
-"{.	c #202020",
-"].	c #EFEFEF",
-"^.	c #F8F8F7",
-"/.	c #E7E7E7",
-"(.	c #C6C6C5",
-"_.	c #BABAB9",
-":.	c #6E6E6E",
-"<.	c #A5BACE",
-"[.	c #C1C1C1",
-"}.	c #373737",
-"|.	c #718498",
-"1.	c #F7F7F6",
-"2.	c #F6F6F5",
-"3.	c #EDEDEB",
-"4.	c #D3D3D3",
-"5.	c #989898",
-"6.	c #6D6D6D",
-"7.	c #94A9C0",
-"8.	c #353535",
-"9.	c #8195A8",
-"0.	c #505050",
-"a.	c #DADAD9",
-"b.	c #DDDDDC",
-"c.	c #F1F1F0",
-"d.	c #EDEDEC",
-"e.	c #E3E3E3",
-"f.	c #C9C9C9",
-"g.	c #979797",
-"h.	c #9B9B9B",
-"i.	c #FDFDFC",
-"j.	c #9C9EA0",
-"k.	c #A5B4C2",
-"l.	c #94A6B9",
-"m.	c #5A5D5F",
-"n.	c #C4D1DE",
-"o.	c #A5B5C3",
-"p.	c #8291A2",
-"q.	c #1A1D21",
-"r.	c #DEDEDE",
-"s.	c #F2F2F1",
-"t.	c #DDDDDD",
-"u.	c #F3F3F2",
-"v.	c #A1A1A1",
-"w.	c #676869",
-"x.	c #FBFCFC",
-"y.	c #CFD7DF",
-"z.	c #B2BFCC",
-"A.	c #C6C6C6",
-"B.	c #D9D9D9",
-"C.	c #BBBBBB",
-"D.	c #808589",
-"E.	c #F5F7FA",
-"F.	c #F3F5F8",
-"G.	c #AFBBC6",
-"H.	c #8F9DAB",
-"I.	c #4B535C",
-"J.	c #E0E0DF",
-"K.	c #E0E0E0",
-"L.	c #808283",
-"M.	c #FAFBFC",
-"N.	c #FBFBFC",
-"O.	c #9C9C9C",
-"P.	c #888888",
-"Q.	c #EAEAEA",
-"R.	c #8D9399",
-"S.	c #F6F7FA",
-"T.	c #F7F8FA",
-"U.	c #D1DAE3",
-"V.	c #B6C3CE",
-"W.	c #494F55",
-"X.	c #E6E6E5",
-"Y.	c #EFEFEE",
-"Z.	c #DEDEDD",
-"`.	c #DBDBDA",
-" +	c #E7E7E6",
-".+	c #AFAFAF",
-"++	c #656769",
-"@+	c #DAE1E8",
-"#+	c #DEE4E9",
-"$+	c #F5F7F8",
-"%+	c #EBEBEB",
-"&+	c #262626",
-"*+	c #929292",
-"=+	c #999999",
-"-+	c #828282",
-";+	c #82898F",
-">+	c #C2CCD5",
-",+	c #F3F5F7",
-"'+	c #B7C1CB",
-")+	c #404548",
-"!+	c #E4E4E3",
-"~+	c #F2F2F0",
-"{+	c #E4E4E4",
-"]+	c #E6E6E6",
-"^+	c #ADADAD",
-"/+	c #FBFBFA",
-"(+	c #54585C",
-"_+	c #C2CEDA",
-":+	c #C4CCD5",
-"<+	c #C4CBD2",
-"[+	c #DCAF00",
-"}+	c #FFDC00",
-"|+	c #878787",
-"1+	c #6E747B",
-"2+	c #99A5AF",
-"3+	c #9DA9B4",
-"4+	c #98A4AF",
-"5+	c #88939E",
-"6+	c #232426",
-"7+	c #E2E2E1",
-"8+	c #ECECEB",
-"9+	c #F0F0EF",
-"0+	c #DCDCDB",
-"a+	c #EFEFED",
-"b+	c #B2B2B2",
-"c+	c #D8D8D8",
-"d+	c #60666D",
-"e+	c #A6B2BD",
-"f+	c #A3ADB5",
-"g+	c #FFF793",
-"h+	c #FFF148",
-"i+	c #FFE957",
-"j+	c #EFE3A3",
-"k+	c #482D00",
-"l+	c #26282B",
-"m+	c #626F7B",
-"n+	c #616C78",
-"o+	c #4F5A63",
-"p+	c #1C2022",
-"q+	c #CFCFCE",
-"r+	c #DFDFDF",
-"s+	c #EAEAE9",
-"t+	c #EEEEED",
-"u+	c #EEEEEC",
-"v+	c #E9E9E8",
-"w+	c #5F6871",
-"x+	c #666D75",
-"y+	c #151616",
-"z+	c #995A00",
-"A+	c #FFF461",
-"B+	c #FFF1C1",
-"C+	c #FFF1B5",
-"D+	c #FFE600",
-"E+	c #E1B500",
-"F+	c #593800",
-"G+	c #30383F",
-"H+	c #CBC7C0",
-"I+	c #0B0D0E",
-"J+	c #B9B9B9",
-"K+	c #CCCCCB",
-"L+	c #DEDEDC",
-"M+	c #EEEEEE",
-"N+	c #DADAD8",
-"O+	c #E8E8E8",
-"P+	c #A6A6A5",
-"Q+	c #EBC200",
-"R+	c #FFEB84",
-"S+	c #FFE71C",
-"T+	c #AF6800",
-"U+	c #C99300",
-"V+	c #610000",
-"W+	c #E3E1DC",
-"X+	c #ADADAC",
-"Y+	c #E3E3E2",
-"Z+	c #D7D7D6",
-"`+	c #D3D3D2",
-" @	c #F9F9F8",
-".@	c #D0D0D0",
-"+@	c #DBDBDB",
-"@@	c #D4D4D3",
-"#@	c #C4C4C4",
-"$@	c #C8C8C8",
-"%@	c #DBC975",
-"&@	c #D8AA00",
-"*@	c #D9AB00",
-"=@	c #B57300",
-"-@	c #C08500",
-";@	c #E3B800",
-">@	c #2D0000",
-",@	c #E7E4E1",
-"'@	c #AFAFAE",
-")@	c #C2C2C1",
-"!@	c #D2D2D0",
-"~@	c #E5E5E4",
-"{@	c #E0E0DE",
-"]@	c #D2D2D1",
-"^@	c #D6D6D5",
-"/@	c #E8E8E7",
-"(@	c #A7A7A7",
-"_@	c #E9D677",
-":@	c #CC9A00",
-"<@	c #DFB300",
-"[@	c #E7BE00",
-"}@	c #EDD700",
-"|@	c #EEE3AD",
-"1@	c #666666",
-"2@	c #8D8D8D",
-"3@	c #E6E4E0",
-"4@	c #BAB5AB",
-"5@	c #76736D",
-"6@	c #CDCDCC",
-"7@	c #CECECC",
-"8@	c #D1D1D0",
-"9@	c #EBEBEA",
-"0@	c #B6B6B5",
-"a@	c #3F3F3F",
-"b@	c #818181",
-"c@	c #E4E3E3",
-"d@	c #B2B2B1",
-"e@	c #C5C5C3",
-"f@	c #D5D5D4",
-"g@	c #EAEAE8",
-"h@	c #D4D4D4",
-"i@	c #757575",
-"j@	c #676767",
-"k@	c #CACACA",
-"l@	c #DBD8D3",
-"m@	c #CDC9C2",
-"n@	c #454544",
-"o@	c #BABAB8",
-"p@	c #CBCBC9",
-"q@	c #D8D8D7",
-"r@	c #E1E1E0",
-"s@	c #E9E9E7",
-"t@	c #969696",
-"u@	c #646464",
-"v@	c #7D7C79",
-"w@	c #F7F6F6",
-"x@	c #79776F",
-"y@	c #252525",
-"z@	c #B3B3B2",
-"A@	c #C5C5C5",
-"B@	c #C7C7C7",
-"C@	c #2F2F2F",
-"D@	c #AFACA6",
-"E@	c #161615",
-"F@	c #A5A5A4",
-"G@	c #B7B7B6",
-"H@	c #E6E6E4",
-"I@	c #E8E8E6",
-"J@	c #B0B0AF",
-"K@	c #B4B4B3",
-"L@	c #BFBFBE",
-"M@	c #656564",
-"N@	c #898989",
-"O@	c #8E8E8E",
-"P@	c #191919",
-"Q@	c #E4E2DF",
-"R@	c #87847C",
-"S@	c #3A3A3A",
-"T@	c #B1B1B0",
-"U@	c #C3C3C2",
-"V@	c #E7E7E5",
-"W@	c #CECECD",
-"X@	c #D9D9D8",
-"Y@	c #B6B6B6",
-"Z@	c #F3F3F0",
-"`@	c #ABABAA",
-" #	c #BFBFBF",
-".#	c #DDDDDB",
-"+#	c #BCBCBB",
-"@#	c #C8C8C7",
-"##	c #B3B3B3",
-"$#	c #EFEDEB",
-"%#	c #706E67",
-"&#	c #242424",
-"*#	c #A8A8A6",
-"=#	c #E5E5E3",
-"-#	c #B9B9B8",
-";#	c #B3B3B1",
-">#	c #6B6B6B",
-",#	c #F5F4F3",
-"'#	c #999998",
-")#	c #CCCCCA",
-"!#	c #D9D9D7",
-"~#	c #DFDFDE",
-"{#	c #151515",
-"]#	c #9F9F9F",
-"^#	c #7D7A73",
-"/#	c #A3A3A2",
-"(#	c #B8B8B6",
-"_#	c #CACAC8",
-":#	c #E3E3E1",
-"<#	c #414141",
-"[#	c #E1E0DF",
-"}#	c #F0EFED",
-"|#	c #9A9791",
-"1#	c #1B1B1A",
-"2#	c #A1A1A0",
-"3#	c #C6C6C4",
-"4#	c #D4D4D2",
-"5#	c #E2E2E0",
-"6#	c #E4E4E2",
-"7#	c #EBEBE9",
-"8#	c #565656",
-"9#	c #959595",
-"0#	c #FCF8E8",
-"a#	c #F9F3DB",
-"b#	c #1C0000",
-"c#	c #F7EFC6",
-"d#	c #A49F8F",
-"e#	c #F2F1F0",
-"f#	c #E5E3E0",
-"g#	c #AFAFAD",
-"h#	c #C1C1C0",
-"i#	c #D1D1CF",
-"j#	c #DBDBD9",
-"k#	c #D9D2BB",
-"l#	c #FFEA66",
-"m#	c #D8B400",
-"n#	c #B4B4B4",
-"o#	c #BAB8B4",
-"p#	c #6E6B62",
-"q#	c #CCC9C2",
-"r#	c #FAF3D8",
-"s#	c #FFED92",
-"t#	c #FBD700",
-"u#	c #F7D300",
-"v#	c #D7B300",
-"w#	c #616161",
-"x#	c #565248",
-"y#	c #23211D",
-"z#	c #ECECEA",
-"A#	c #D4CDA8",
-"B#	c #FFE400",
-"C#	c #F2CF00",
-"D#	c #EECB00",
-"E#	c #D7B400",
-"F#	c #7B7870",
-"G#	c #D5D4D1",
-"H#	c #D4D3D1",
-"I#	c #7A776F",
-"J#	c #827F78",
-"K#	c #DBDAD8",
-"L#	c #E1E1DF",
-"M#	c #DFDFDD",
-"N#	c #A7A5A0",
-"O#	c #7C7C7C",
-"P#	c #DED086",
-"Q#	c #EAC700",
-"R#	c #C9A700",
-"S#	c #D9D9D6",
-"T#	c #8D8A84",
-"U#	c #5C584F",
-"V#	c #8E8B85",
-"W#	c #D8D7D5",
-"X#	c #DDDCDA",
-"Y#	c #908E87",
-"Z#	c #605C53",
-"`#	c #6B685F",
-" $	c #CBCAC7",
-".$	c #E7DDAA",
-"+$	c #FBE100",
-"@$	c #DCB900",
-"#$	c #947300",
-"$$	c #666259",
-"%$	c #67635A",
-"&$	c #69665D",
-"*$	c #141414",
-"=$	c #A99500",
-"-$	c #DCB800",
-";$	c #D3B000",
-">$	c #CFAC00",
-",$	c #AF8A00",
-"'$	c #836300",
-")$	c #333332",
-"!$	c #575349",
-"~$	c #57544A",
-"{$	c #8D8D8C",
-"]$	c #50504F",
-"^$	c #7C7C7B",
-"/$	c #787877",
-"($	c #7B7B79",
-"_$	c #6D6D6C",
-":$	c #5C5C5B",
-"<$	c #656158",
-"[$	c #59564C",
-"}$	c #C4C4C2",
-"|$	c #A9A9A8",
-"1$	c #A7A7A6",
-"2$	c #A7A7A5",
-"3$	c #AAAAA9",
-"4$	c #AEAEAC",
-"5$	c #D9D8D6",
-"6$	c #8D8A83",
-"7$	c #8E8C85",
-"8$	c #6D6A61",
-"9$	c #C7C7C6",
-"0$	c #C1C1BF",
-"a$	c #BCBCBA",
-"b$	c #BBBBBA",
-"c$	c #BDBDBC",
-"d$	c #7B7770",
-"e$	c #D5D4D2",
-"f$	c #EDECEB",
-"g$	c #7C7971",
-"h$	c #D7D6D3",
-"i$	c #F3F2F2",
-"j$	c #FDFCFC",
-"k$	c #BFBDBA",
-"l$	c #CBCBCA",
-"m$	c #CDCDCB",
-"n$	c #CFCFCD",
-"o$	c #D0D0CE",
-"p$	c #D8D8D6",
-"q$	c #A2A2A1",
-"r$	c #A1A19F",
-"s$	c #A0A09E",
-"t$	c #A3A3A1",
-"u$	c #9A9A9A",
-"v$	c #8C8C8C",
-"  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @                       ",
-". # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % & * .                   ",
-". $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ = = = = = = = = = = = = - % ; > .                 ",
-". $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ = = = = = = = = = = = = = = , ' $ ) ! .               ",
-". $ $ $ $ $ $ $ ~ $ $ $ $ $ $ $ $ $ $ = = = = = = = = = = = = = = = = , { $ $ ; ] ^             ",
-". $ $ $ $ $ $ $ / $ $ $ $ $ $ $ $ = = = = ( ( _ _ _ _ _ ( ( = = = ( ( % : < ( $ [ } |           ",
-". $ $ $ $ $ $ $ 1 2 $ $ $ $ $ = 3 4 5 6 . . . + 7 8 9 8 0 a < _ ( ( ( b c < a _ $ d e .         ",
-". $ $ $ $ $ $ $ 1 f 2 g $ = = , h i j k l m n n o p q r r s , t _ _ _ u v w 5 d : x y z .       ",
-". $ $ $ $ $ $ $ 1 A B C C = = D i j E . . . . F G 9 H I J K L u _ _ M N / O P Q R R S f .       ",
-". $ $ $ $ $ $ $ 1 = = T C = = U j V . W . . . . . . X Y Z J ` 0 u  .a ..+.> @.#.$.%.&.*..       ",
-". $ $ $ $ $ $ = =.= = = T = = -.;.>.Z . . . . ,.'.).'.. !.. ~.{.].b ^.a - , , /.(.y _.%..       ",
-". $ $ $ $ = = = =.= = ( ( ( ( :.<.. . . . . . . . : [.. . }.|.9 /.D % % ^.1.2.3 3 3 3.f .       ",
-". $ $ = 4./ 5./ f ( ( ( ( a % 6.7.. . . . . . . . . Z . . 8.9.0.a.b.c.u , 3 3 b d.+.+.1 .       ",
-". $ = = z e.f.g.h.( i._ <  .j.k.l.. . . . . . . . . . . m.n.o.p.q.r.; s.b b u N t.u.u.c .       ",
-". $ ( ( z v g.g.v._ _ _ - w.x.y.z.. . A.B.$.. . C.f.. . D.E.F.G.H.I./.D +.N u.u.r.J.s.c .       ",
-". $ ( i.{ f g.f K._ M - % L.M.N.y.. O.; ; ' P.r.h Q.x . R.S.T.U.V.W.X.Y.s.u.....Z.`. +.+.       ",
-". $ _ _ _ _ M - - - - - ^.++@+#+$+. %+2 &+*+=+A.. -++.. ;+>+,+,+'+)+!+; D s.~+c.b.{+]+^+.       ",
-". $ M M - - - - /+/+< < 3 (+_+:+<+. t./ . [+}+-.. |+... 1+2+3+4+5+6+7+8+9+~+D D 0+Y.a+b+.       ",
-". $ - - - /+/+< < < < t ^.c+d+e+f+. 8 [+g+h+i+}+}+j+k+. l+m+n+o+p+q+r+s+a+9+9+Y.a.t+u+c .       ",
-". $ /+< < < < < 1.J.Q.a ) % v+w+x+y+z+A+B+C+D+}+}+}+E+F+. G+H+I+J+K+L+ +d.; M+t+N+d.d.c .       ",
-". $ < < t t a a +.f.{ b.Z.O+) {+P+. . [+Q+R+S+}+[+T+U+V+. . W+G X+y B.Y+7+Z+`+Z+Z+w 8+c .       ",
-". $ t a a a a  @.@r., O++@@@c+#@$@. . %@&@*@T+=@-@;@>@. =+. ,@{.'@)@`+J.!@~@{@]@`+8+8+c .       ",
-". $ a  @ @ @ . .f.^@b./@1.u T : (@. v.M+_@:@<@[@}@|@1@. 2@u 3@4@5@).6@`.7@0+8@]@4.9@9@c .       ",
-". $  . . . .1./@6@% /.[ `.7+@@0@Y a@U ) ) O+# M+w h r+b@. . I c@4@d@e@@@Z+!@q+f@Y+s+g@c .       ",
-". $ ^.1.1.1.% h@A b b N s.r.B i@. j@4.D { O+{ O+k@B.x #@. . b l@m@n@o@p@q@r@ +v+v+v+s@c .       ",
-". $ % % % 2.2.6@X.+.+...Y.b.t@. u@c+3 ,  .g %++.].{+4.' X . . v@w@x@y@)@!@0+Y+ +s@s@s@c .       ",
-". $ 2.2.y z@! A@t+u.u.c.8+f . . f.{+, <  ./., 3 ) M+T [ B@. C@w@D@E@F@G@f.q@r@H@ +/@I@c .       ",
-". $ 3 u J@& K@L@t+..c.t+v+M@. N@) 3  .- - a t.3 ) M+%+/.{+O@. P@Q@R@S@T@U@4.t.!+V@I@I@c .       ",
-". $ N N W@C.C.X@s.c.Z+C Y@. . A ) 3 , < a r+w 3 ) M+%+/.e..+I Z@R@. g.`@ #8@.#7+X. +H@c .       ",
-". $ ..s.s.s.s.c.c.D +#@###. . k@D +.3 , , B.3 +.D ; Q.]+e..@. N@$#%#&#*#+#W@`.7+=#H@~@c .       ",
-". $ s.s.s.c.9+9+9+Y.@@-#;#. . X M+) +.3 3 B.+.) M+%+O+4 T [.>#,#R@. '#e _.)#!#~#Y+~@~@c .       ",
-". $ ) c.9+9+9+9+Y.d.g@Y+_.. . . : ' 4 ) ) [ D ].w h ]+e.K.O@{#]#Q@^#&#/#(#_#^@Z.:#=#=#c .       ",
-". $ 9+9+].Y.Y.Y.u+s+~@8@. . . . . . <#[.M+K.].%+h /.{+[#. . I }#|#1#y@2#z@3#4#.#5#6#6#c .       ",
-". $ Y.Y.Y.Y.a+d.7#!+^+8#9#0#a#. . . . . k@e.{+O+]+{+~ b#c#d#. . e#f#4@{.g#h#i#j#{@5#6#c .       ",
-". $ Y.Y.t+t+u+s+X.J.. . k#l#}+m#. . . . n#/.c+o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#p#",
-". $ t+t+3.8+9@s@Y+. q#r#s#}+t#u#v#. w#x e.e.r.o#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#y#",
-". $ 3.8+z#9@s+/@r@7 A#B#}+t#u#C#D#E#. U K.K.r+o#x#F#G#9@( z#H#I#x#J#K#L#_ M#N#x#J#K#L#_ M#N#x#y#",
-". $ z#9@9@9@g@X.~#O#. P#t#u#C#D#Q#R#. g. #g 2 o#x#S#$ T#U#V#$ W#x#X#$ Y#Z#`# $x#X#$ Y#Z#`# $x#y#",
-". $ 7#7#s+s+v+X.~#. .$+$u#C#D#Q#@$#$. . . . . o#x#, $ $$x#%$$ w@x#^.$ &$x#x#x#x#^.$ &$x#x#x#x#y#",
-". $ s+s+s+g@s@~@~#*$=$-$E#;$>$,$'$. )$. . . . o#x#$ $ !$x#~$$ = x#$ $ x#$ $ $ x#$ $ x#$ $ $ x#y#",
-". $ g@v+v+v+/@~@{@{$. . . . . . . ]$^$/$($_$:$o#x#, $ <$x#%$$ w@x#, $ [$x#$ $ x#, $ [$x#$ $ x#y#",
-". $ v+v+v+I@ +~@r@`.i#}$-#.+|$1$2$1$3$4$J@1 d@o#x#5$$ 6$U#7$$ W#x#S#$ 8$x#$ $ x#S#$ 8$x#$ $ x#y#",
-". $ s@ + + + +H@:#L+Z+q+9$0$a$_._.b$c$0$U@}$e@o#x#d$e$f$= d.G#I#x#g$h$i$j$z#k$x#g$h$i$j$z#k$x#y#",
-". $  +V@V@V@X.X.!+r@.#!#`+q+K+l$l$m$n$o$!@`+`+o#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#x#y#",
-". $ V@X.X.X.H@H@=#6#J.b.`.N+!#p$p$!#N+j#`.j#j#p#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#y#",
-". $ X.H@H@H@H@~@!+6#:#5#L#{@{@M#M#{@{@{@{@{@L#{@P+q$q$2#2#2#r$s$s$r$r$2#q$t$t$t$t$t$t$2@.       ",
-". # H@H@H@=#6#6#6#6#6#6#6#6#6#6#Y+:#:#:#:#:#:#:#:#5#5#5#5#L#L#L#L#L#L#L#L#L#L#L#L#L#L#u$.       ",
-". x c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c u$v$.       ",
-"  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       ",
-"                                                                                                ",
-"                                                                                                ",
-"                                                                                                "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vorbis/vcupdate.c	Wed Dec 19 17:51:50 2007 +0200
@@ -0,0 +1,251 @@
+/* Audacious - Cross-platform multimedia player
+ * Copyright (C) 2005-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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <audacious/plugin.h>
+#include <audacious/strings.h>
+#include <audacious/util.h>
+#include <audacious/i18n.h>
+
+#include <mowgli.h>
+
+#include "vorbis.h"
+#include "vcedit.h"
+
+static gboolean write_and_pivot_files(vcedit_state * state);
+
+extern GMutex *vf_mutex;
+
+static mowgli_dictionary_t *
+dictionary_from_vorbis_comment(vorbis_comment * vc)
+{
+    mowgli_dictionary_t *dict;
+    gint i;
+    gchar *val;
+
+    dict = mowgli_dictionary_create(g_ascii_strcasecmp);
+
+    for (i = 0; i < vc->comments; i++) {
+        gchar **frags;
+
+        AUDDBG("%s\n", vc->user_comments[i]);
+        frags = g_strsplit(vc->user_comments[i], "=", 2);
+      
+        /* FIXME: need more rigorous checks to guard against
+           borqued comments */
+
+        /* No RHS? */
+        val = frags[1] ? frags[1] : "";
+
+        mowgli_dictionary_add(dict, frags[0], g_strdup(val));
+
+        g_strfreev(frags); /* Don't use g_free() for string lists! --eugene */
+    }
+
+    return dict;
+}
+
+static void
+dictionary_to_vorbis_comment(vorbis_comment * vc, mowgli_dictionary_t * dict)
+{
+    mowgli_dictionary_iteration_state_t state;
+    gchar *field;
+    
+    vorbis_comment_clear(vc);
+  
+    MOWGLI_DICTIONARY_FOREACH(field, &state, dict) {
+        vorbis_comment_add_tag(vc, state.cur->key, field);
+    }
+}
+
+static void
+insert_str_tuple_field_to_dictionary(Tuple *tuple, int fieldn, mowgli_dictionary_t *dict, char *key)
+{
+    
+    if(mowgli_dictionary_find(dict, key) != NULL) g_free(mowgli_dictionary_delete(dict, key));
+    
+    gchar *tmp = (gchar*)aud_tuple_get_string(tuple, fieldn, NULL);
+    if(tmp != NULL && strlen(tmp) != 0) mowgli_dictionary_add(dict, key, g_strdup(tmp));
+}
+
+static void
+insert_int_tuple_field_to_dictionary(Tuple *tuple, int fieldn, mowgli_dictionary_t *dict, char *key)
+{
+    int val;
+
+    if(mowgli_dictionary_find(dict, key) != NULL) g_free(mowgli_dictionary_delete(dict, key));
+    
+    if(aud_tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_INT && (val = aud_tuple_get_int(tuple, fieldn, NULL)) >= 0) {
+        gchar *tmp = g_strdup_printf("%d", val);
+        mowgli_dictionary_add(dict, key, tmp);
+    }
+}
+
+static void
+destroy_cb(mowgli_dictionary_elem_t *delem, void *privdata)
+{
+    g_free(delem->data);
+}
+
+gboolean
+vorbis_update_song_tuple (Tuple *tuple, VFSFile *fd)
+{
+
+    vcedit_state *state;
+    vorbis_comment *comment;
+    mowgli_dictionary_t *dict;
+    gboolean ret;
+
+    if(!tuple || !fd) return FALSE;
+    
+    g_mutex_lock(vf_mutex);
+
+    state = vcedit_new_state();
+
+    if(vcedit_open(state, fd) < 0) {
+        vcedit_clear(state);
+        g_mutex_unlock(vf_mutex);
+        return FALSE;
+    }
+    
+    comment = vcedit_comments(state);
+    dict = dictionary_from_vorbis_comment(comment);
+
+    insert_str_tuple_field_to_dictionary(tuple, FIELD_TITLE, dict, "title");
+    insert_str_tuple_field_to_dictionary(tuple, FIELD_ARTIST, dict, "artist");
+    insert_str_tuple_field_to_dictionary(tuple, FIELD_ALBUM, dict, "album");
+    insert_str_tuple_field_to_dictionary(tuple, FIELD_COMMENT, dict, "comment");
+    insert_str_tuple_field_to_dictionary(tuple, FIELD_GENRE, dict, "genre");
+    
+    insert_int_tuple_field_to_dictionary(tuple, FIELD_YEAR, dict, "date");
+    insert_int_tuple_field_to_dictionary(tuple, FIELD_TRACK_NUMBER, dict, "tracknumber");
+    
+    dictionary_to_vorbis_comment(comment, dict);
+    mowgli_dictionary_destroy(dict, destroy_cb, NULL);
+    
+    ret = write_and_pivot_files(state);
+
+    vcedit_clear(state);
+    g_mutex_unlock(vf_mutex);
+
+    return ret;
+}
+
+/* from stdio VFS plugin */
+static gchar *
+aud_vfs_stdio_urldecode_path(const gchar * encoded_path)
+{
+    const gchar *cur, *ext;
+    gchar *path, *tmp;
+    gint realchar;
+
+    if (!encoded_path)
+        return NULL;
+
+    if (!aud_str_has_prefix_nocase(encoded_path, "file:"))
+        return NULL;
+
+    cur = encoded_path + 5;
+
+    if (aud_str_has_prefix_nocase(cur, "//localhost"))
+        cur += 11;
+
+    if (*cur == '/')
+        while (cur[1] == '/')
+            cur++;
+
+    tmp = g_malloc0(strlen(cur) + 1);
+
+    while ((ext = strchr(cur, '%')) != NULL) {
+        strncat(tmp, cur, ext - cur);
+        ext++;
+        cur = ext + 2;
+        if (!sscanf(ext, "%2x", &realchar)) {
+            /* Assume it is a literal '%'.  Several file
+             * managers send unencoded file: urls on drag
+             * and drop. */
+            realchar = '%';
+            cur -= 2;
+        }
+        tmp[strlen(tmp)] = realchar;
+    }
+
+    path = g_strconcat(tmp, cur, NULL);
+    g_free(tmp);
+    return path;
+}
+
+gboolean
+write_and_pivot_files(vcedit_state * state)
+{
+    gint retval;
+    gchar *tmpfn, *unq_tmpfn, *unq_in;
+    VFSFile *out;
+    
+    tmpfn = g_strdup_printf("%s.XXXXXX", ((VFSFile*)state->in)->uri);
+    mktemp(tmpfn);
+
+    AUDDBG("creating temp file: %s\n", tmpfn);
+
+    if ((out = aud_vfs_fopen(tmpfn, "wb")) == NULL) {
+        g_free(tmpfn);
+        AUDDBG("fileinfo.c: couldn't create temp file, %s\n", tmpfn);
+        return FALSE;
+    }
+
+    if (vcedit_write(state, out) < 0) {
+        g_free(tmpfn);
+        aud_vfs_fclose(out);
+        AUDDBG("vcedit_write: %s\n", state->lasterror);
+        return FALSE;
+    }
+
+    aud_vfs_fclose(out);
+
+    unq_tmpfn = aud_vfs_stdio_urldecode_path(tmpfn);
+    unq_in = aud_vfs_stdio_urldecode_path(((VFSFile*)state->in)->uri);
+
+    if((retval = rename(unq_tmpfn, unq_in)) == 0) {
+        AUDDBG("fileinfo.c: file %s renamed successfully to %s\n", unq_tmpfn, unq_in);
+    } else {
+        remove(unq_tmpfn);
+        AUDDBG("fileinfo.c: couldn't rename file\n");
+    }
+
+    g_free(unq_in);
+    g_free(unq_tmpfn);
+    g_free(tmpfn);
+
+    return retval == 0;
+}
+
--- a/src/vorbis/vorbis.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/vorbis/vorbis.c	Wed Dec 19 17:51:50 2007 +0200
@@ -108,10 +108,10 @@
     .pause = vorbis_pause,
     .seek = vorbis_seek,
     .cleanup = vorbis_cleanup,
-    .file_info_box = vorbis_file_info_box,       /* file info box, tag editing */
     .get_song_tuple = get_song_tuple,
     .is_our_file_from_vfs = vorbis_check_fd,
     .vfs_extensions = vorbis_fmts,
+    .update_song_tuple = vorbis_update_song_tuple,
 };
 
 InputPlugin *vorbis_iplist[] = { &vorbis_ip, NULL };
@@ -538,8 +538,10 @@
         if (!rg_peak_str)
             rg_peak_str = vorbis_comment_query(comment, "rg_peak", 0);  /* Old */
 
-        if (rg_peak_str)
+        if (rg_peak_str) {
             rg_peak = atof(rg_peak_str);
+            rg_peak = rg_peak == 0.0 ? 1.0 : rg_peak; /* be aware of incorrect formatted strings --eugene */
+        }
         else
             rg_peak = 1;
 
@@ -618,7 +620,7 @@
     VFSVorbisFile *vfd = (VFSVorbisFile *) vorbisfile->datasource;
     Tuple *tuple = NULL;
     gint length;
-    vorbis_comment *comment;
+    vorbis_comment *comment = NULL;
 
     tuple = aud_tuple_new_from_filename(filename);
 
@@ -629,6 +631,8 @@
 
     /* associate with tuple */
     aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, length);
+    /* maybe, it would be better to display nominal bitrate (like in main win), not average? --eugene */
+    aud_tuple_associate_int(tuple, FIELD_BITRATE, NULL, ov_bitrate(vorbisfile, -1)/1000);
 
     if ((comment = ov_comment(vorbisfile, -1))) {
         gchar *tmps;
@@ -641,18 +645,20 @@
 
         if ((tmps = vorbis_comment_query(comment, "tracknumber", 0)) != NULL)
             aud_tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, atoi(tmps));
+    }
 
-        aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossy");
+    aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossy");
 
-        if (comment && comment->vendor)
-        {
-            gchar *codec = g_strdup_printf("Ogg Vorbis [%s]", comment->vendor);
-            aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, codec);
-            g_free(codec);
-        }
-        else
-            aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, "Ogg Vorbis");
+    if (comment && comment->vendor)
+    {
+        gchar *codec = g_strdup_printf("Ogg Vorbis [%s]", comment->vendor);
+        aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, codec);
+        g_free(codec);
     }
+    else
+        aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, "Ogg Vorbis");
+    
+    aud_tuple_associate_string(tuple, FIELD_MIMETYPE, NULL, "application/ogg");
 
     return tuple;
 }
--- a/src/vorbis/vorbis.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/vorbis/vorbis.h	Wed Dec 19 17:51:50 2007 +0200
@@ -14,7 +14,7 @@
 
 void vorbis_configure(void);
 
-void vorbis_file_info_box(char *filename);
+gboolean vorbis_update_song_tuple (Tuple *tuple, VFSFile *fd);
 
 char *convert_to_utf8(const char *string);
 char *convert_from_utf8(const char *string);
--- a/src/vtx/lh5dec.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/vtx/lh5dec.c	Wed Dec 19 17:51:50 2007 +0200
@@ -92,7 +92,10 @@
     start[i] >>= jutbits;
     weight[i] = 1U << (tablebits - i);
   }
-  while (i <= 16) weight[i++] = 1U << (16 - i);
+  while (i <= 16) {
+      weight[i] = 1U << (16 - i);
+      i++;
+  }
 
   i = start[tablebits + 1] >> jutbits;
   if (i != (unsigned short)(1U << 16)) {
--- a/src/vtx/vtx.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/vtx/vtx.c	Wed Dec 19 17:51:50 2007 +0200
@@ -96,7 +96,6 @@
 vtx_get_song_tuple_from_vtx(const gchar *filename, ayemu_vtx_t *in)
 {
   Tuple *out = aud_tuple_new_from_filename(filename);
-  gchar *string;
 
   aud_tuple_associate_string(out, FIELD_ARTIST, NULL, in->hdr.author);
   aud_tuple_associate_string(out, FIELD_TITLE, NULL, in->hdr.title);
@@ -159,7 +158,7 @@
 	  }
 	else
 	  {			/* get next AY register frame */
-	    if (ayemu_vtx_get_next_frame (&vtx, regs) == 0)
+	    if (ayemu_vtx_get_next_frame (&vtx, (char *)regs) == 0)
 	      {
 		playback->eof = TRUE;
 		donow = need;
--- a/src/vtx/vtxfile.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/vtx/vtxfile.c	Wed Dec 19 17:51:50 2007 +0200
@@ -192,11 +192,11 @@
   aud_vfs_fclose (vtx->fp);
   vtx->fp = NULL;
   if ((vtx->regdata = (char *) malloc (vtx->hdr.regdata_size)) == NULL) {
-    fprintf (stderr, "ayemu_vtx_load_data: Can allocate %d bytes for unpack register data\n", vtx->hdr.regdata_size);
+    fprintf (stderr, "ayemu_vtx_load_data: Can allocate %d bytes for unpack register data\n", (int)(vtx->hdr.regdata_size));
     free (packed_data);
     return NULL;
   }
-  lh5_decode (packed_data, vtx->regdata, vtx->hdr.regdata_size, packed_size);
+  lh5_decode ((unsigned char *)packed_data, (unsigned char *)(vtx->regdata), vtx->hdr.regdata_size, packed_size);
   free (packed_data);
   vtx->pos = 0;
   return vtx->regdata;
--- a/src/wavpack/libwavpack.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/wavpack/libwavpack.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -1,3 +1,5 @@
+// #define AUD_DEBUG 1
+
 #include <string>
 
 #include <assert.h>
@@ -24,12 +26,6 @@
 #define M_LN10   2.3025850929940456840179914546843642
 #endif
 
-#ifdef DEBUG
-# define DBG(format, args...) fprintf(stderr, format, ## args)
-#else
-# define DBG(format, args...)
-#endif
-
 #define BUFFER_SIZE 256 // read buffer size, in samples
 
 static void wv_load_config();
@@ -42,7 +38,7 @@
 static int wv_get_time(InputPlayback *);
 static void wv_get_song_info(char *, char **, int *);
 static char *generate_title(const char *, WavpackContext *ctx);
-static double isSeek;
+static int isSeek;
 static short paused;
 static bool killDecodeThread;
 static bool AudioError;
@@ -305,11 +301,10 @@
 static void *
 DecodeThread(InputPlayback *playback)
 {
-    ape_tag tag;
+    int bps;
+#ifdef AUD_DEBUG
     char *filename = playback->filename;
-    int bps_updateCounter = 0;
-    int bps;
-    int i;
+#endif
     WavpackDecoder d(&mod);
 
     if (!d.attach_to_play(playback)) {
@@ -317,25 +312,26 @@
         return end_thread();
     }
     bps = WavpackGetBytesPerSample(d.ctx) * d.num_channels;
-    DBG("reading %s at %d rate with %d channels\n", filename, d.sample_rate, d.num_channels);
+    AUDDBG("reading %s at %d rate with %d channels\n", filename, d.sample_rate, d.num_channels);
 
     if (!d.open_audio()) {
-        DBG("error opening audio channel\n");
+        AUDDBG("error opening audio channel\n");
         killDecodeThread = true;
         AudioError = true;
         openedAudio = false;
     }
     else {
-        DBG("opened audio channel\n");
+        AUDDBG("opened audio channel\n");
         openedAudio = true;
     }
     unsigned status;
+#if 0
     char *display = generate_title(filename, d.ctx);
     int length = (int) (1000 * WavpackGetNumSamples(d.ctx));
-
+#endif
     while (!killDecodeThread) {
         if (isSeek != -1) {
-            DBG("seeking to position %d\n", isSeek);
+            AUDDBG("seeking to position %d\n", isSeek);
             WavpackSeekSample(d.ctx, (int)(isSeek * d.sample_rate));
             isSeek = -1;
         }
@@ -477,12 +473,14 @@
     }
 
     int sample_rate = WavpackGetSampleRate(d.ctx);
+#ifdef AUD_DEBUG
     int num_channels = WavpackGetNumChannels(d.ctx);
-    DBG("reading %s at %d rate with %d channels\n", filename, sample_rate, num_channels);
+#endif
+    AUDDBG("reading %s at %d rate with %d channels\n", filename, sample_rate, num_channels);
 
     *length = (int)(WavpackGetNumSamples(d.ctx) / sample_rate) * 1000,
     *title = generate_title(filename, d.ctx);
-    DBG("title for %s = %s\n", filename, *title);
+    AUDDBG("title for %s = %s\n", filename, *title);
 }
 
 static int
--- a/src/wavpack/tags.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/wavpack/tags.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -9,6 +9,35 @@
 #include <audacious/plugin.h>
 #include "tags.h"
 
+static const char*  GenreList [] = {
+    "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
+    "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
+    "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
+    "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient",
+    "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical",
+    "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
+    "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative",
+    "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
+    "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
+    "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap",
+    "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave",
+    "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal",
+    "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll",
+    "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Fast-Fusion",
+    "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
+    "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock",
+    "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
+    "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony",
+    "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club",
+    "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul",
+    "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
+    "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
+    "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat", "Christian Gangsta",
+    "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
+    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
+    "SynthPop"
+};
+
 struct APETagFooterStruct {
     unsigned char ID[8];
     unsigned char Version[4];
--- a/src/wavpack/tags.h	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/wavpack/tags.h	Wed Dec 19 17:51:50 2007 +0200
@@ -20,35 +20,6 @@
     int     _genre;
 } ape_tag;
 
-static const char*  GenreList [] = {
-    "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
-    "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
-    "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
-    "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient",
-    "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical",
-    "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
-    "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative",
-    "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
-    "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
-    "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap",
-    "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave",
-    "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal",
-    "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll",
-    "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Fast-Fusion",
-    "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
-    "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock",
-    "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
-    "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony",
-    "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club",
-    "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul",
-    "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
-    "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
-    "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat", "Christian Gangsta",
-    "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
-    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
-    "SynthPop"
-};
-
 int utf8ToUnicode ( const char* lpMultiByteStr, wchar_t* lpWideCharStr, int cmbChars );
 
 int GetTageType ( FILE *fp );
--- a/src/wavpack/ui.cxx	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/wavpack/ui.cxx	Wed Dec 19 17:51:50 2007 +0200
@@ -1,3 +1,5 @@
+// #define AUD_DEBUG 1
+
 #include <assert.h>
 #include <string.h>
 #include <stdio.h>
@@ -21,8 +23,6 @@
 #define M_LN10   2.3025850929940456840179914546843642
 #endif
 
-#define DBG(format, args...) fprintf(stderr, format, ## args)
-
 void load_tag(ape_tag *tag, WavpackContext *ctx);
 gboolean clipPreventionEnabled;
 gboolean dynBitrateEnabled;
@@ -118,10 +118,12 @@
         printf("wavpack: Error opening file: \"%s: %s\"\n", fn, error_buff);
         return;
     }
+#ifdef AUD_DEBUG
     int sample_rate = WavpackGetSampleRate(ctx);
     int num_channels = WavpackGetNumChannels(ctx);
+#endif
     load_tag(&tag, ctx);
-    DBG("opened %s at %d rate with %d channels\n", fn, sample_rate, num_channels);
+    AUDDBG("opened %s at %d rate with %d channels\n", fn, sample_rate, num_channels);
 
     filename = g_strdup(fn);
     static GtkWidget *info_frame, *info_box, *bitrate_label, *rate_label;
--- a/src/xspf/xspf.c	Wed Dec 05 13:35:16 2007 +0200
+++ b/src/xspf/xspf.c	Wed Dec 19 17:51:50 2007 +0200
@@ -18,6 +18,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
+/* #define AUD_DEBUG 1 */
+
 #include <config.h>
 
 #include <glib.h>
@@ -73,19 +76,12 @@
     { FIELD_YEAR,         "year",         TUPLE_INT,      TRUE,   CMP_DEF },
     { FIELD_DATE,         "date",         TUPLE_STRING,   TRUE,   CMP_DEF },
     { FIELD_GENRE,        "genre",        TUPLE_STRING,   TRUE,   CMP_DEF },
+    { FIELD_MTIME,        "mtime",        TUPLE_INT,      TRUE,   CMP_DEF },
     { FIELD_FORMATTER,    "formatter",    TUPLE_STRING,   TRUE,   CMP_DEF },
 };
 
 static const gint xspf_nentries = (sizeof(xspf_entries) / sizeof(xspf_entry_t));
 
-/* we need encoding conversion */
-#ifdef DEBUG
-#  define XSDEBUG(...) { g_print("xspf[%s:%d]: ", __FUNCTION__, (int) __LINE__); g_print(__VA_ARGS__); }
-#else
-#  define XSDEBUG(...) /* stub */
-#endif
-
-
 static gboolean is_uri(gchar *uri)
 {
     if (strstr(uri, "://"))
@@ -170,6 +166,7 @@
                             break;
                         
                         case TUPLE_INT:
+                            AUDDBG("field=%s val=%s\n", xspf_entries[i].xspfName, str);
                             aud_tuple_associate_int(tuple, xspf_entries[i].tupleField, NULL, atol((char *)str));
                             break;
                         
@@ -186,29 +183,24 @@
     }
 
     if (location) {
-        gchar *realfn = NULL, *scratch = NULL;
+        gchar *scratch = NULL;
 
         /* filename and path in tuple must be unescaped. */
-        scratch = g_filename_from_uri(location, NULL, NULL);
-        realfn = aud_str_to_utf8(scratch ? scratch : location);
-        g_free(scratch);
-
-        scratch = g_path_get_basename(realfn);
+        scratch = aud_uri_to_display_basename(location);
         aud_tuple_associate_string(tuple, FIELD_FILE_NAME, NULL, scratch);
         g_free(scratch);
 
-        scratch = g_path_get_dirname(realfn);
+        scratch = aud_uri_to_display_dirname(location);
         aud_tuple_associate_string(tuple, FIELD_FILE_PATH, NULL, scratch);
         g_free(scratch);
 
-        aud_tuple_associate_string(tuple, FIELD_FILE_EXT, NULL, strrchr(realfn, '.'));
+        aud_tuple_associate_string(tuple, FIELD_FILE_EXT, NULL, strrchr(location, '.'));
 
-        XSDEBUG("tuple->file_name = %s\n", aud_tuple_get_string(tuple, FIELD_FILE_NAME, NULL));
-        XSDEBUG("tuple->file_path = %s\n", aud_tuple_get_string(tuple, FIELD_FILE_PATH, NULL));
+        AUDDBG("tuple->file_name = %s\n", aud_tuple_get_string(tuple, FIELD_FILE_NAME, NULL));
+        AUDDBG("tuple->file_path = %s\n", aud_tuple_get_string(tuple, FIELD_FILE_PATH, NULL));
 
         /* add file to playlist */
         aud_playlist_load_ins_file_tuple(playlist, location, filename, pos, tuple);
-        g_free(realfn);
         pos++;
     }
 
@@ -259,7 +251,7 @@
 
     g_return_if_fail(filename != NULL);
 
-    XSDEBUG("filename='%s', pos=%d\n", filename, pos);
+    AUDDBG("filename='%s', pos=%d\n", filename, pos);
 
     doc = xmlRecoverFile(filename);
     if (doc == NULL)
@@ -273,7 +265,7 @@
             
             base = (gchar *)xmlNodeGetBase(doc, nptr);
 
-            XSDEBUG("base @1 = %s\n", base);
+            AUDDBG("base = %s\n", base);
             
             // if filename is specified as a base, ignore it.
             tmp = xmlURIUnescapeString(base, -1, NULL);
@@ -285,7 +277,7 @@
                 g_free(tmp);
             }
             
-            XSDEBUG("base @2 = %s\n", base);
+            AUDDBG("base = %s\n", base);
             
             for (nptr2 = nptr->children; nptr2 != NULL; nptr2 = nptr2->next) {
 
@@ -359,7 +351,7 @@
     gchar *base = NULL;
     Playlist *playlist = aud_playlist_get_active();
 
-    XSDEBUG("filename='%s', pos=%d\n", filename, pos);
+    AUDDBG("filename='%s', pos=%d\n", filename, pos);
 
     doc = xmlNewDoc((xmlChar *)"1.0");
     doc->charset = XML_CHAR_ENCODING_UTF8;
@@ -407,7 +399,7 @@
                 g_free(base);
                 base = tmp;
                 baselen = tmplen;
-                XSDEBUG("base='%s', baselen=%d\n", base, baselen);
+                AUDDBG("base='%s', baselen=%d\n", base, baselen);
             } else
                 g_free(tmp);
         }
@@ -424,7 +416,7 @@
             }
 
             if (!is_uri(base)) {
-                XSDEBUG("base is not uri. something is wrong.\n");
+                AUDDBG("base is not uri. something is wrong.\n");
                 tmp = g_strdup_printf("file://%s", base);
                 xmlSetProp(rootnode, (xmlChar *)"xml:base", (xmlChar *)tmp);
                 g_free(tmp);
@@ -471,14 +463,14 @@
         location = xmlNewNode(NULL, (xmlChar *)"location");
 
         if (is_uri(entry->filename)) {   /* uri */
-            XSDEBUG("filename is uri\n");
+            AUDDBG("filename is uri\n");
             filename = g_strdup(entry->filename + baselen); // entry->filename is always uri now.
         } else {                  /* local file (obsolete) */
             gchar *tmp = (gchar *) xspf_path_to_uri((const xmlChar *)entry->filename + baselen);
             if (base) { /* relative */
                 filename = g_strdup_printf("%s", tmp);
             } else {
-                XSDEBUG("absolute and local (obsolete)\n");
+                AUDDBG("absolute and local (obsolete)\n");
                 filename = g_filename_to_uri(tmp, NULL, NULL);
             }
             g_free(tmp);
@@ -525,9 +517,6 @@
                     xspf_add_node(track, xs->type, xs->isMeta, xs->xspfName, scratch, scratchi);
             }
 
-            /* Write mtime unconditionally to support staticlist */
-            xspf_add_node(track, TUPLE_INT, TRUE, "mtime", NULL,
-                aud_tuple_get_int(entry->tuple, FIELD_MTIME, NULL));
         } else {
 
             if (entry->title != NULL && g_utf8_validate(entry->title, -1, NULL))