changeset 116:a578bf9b2851 trunk

[svn] - iris vis plugin port
author nenolod
date Tue, 24 Oct 2006 21:25:31 -0700
parents 2e77e3fdd3c1
children 614e390341f4
files ChangeLog configure.ac src/iris/3Dstuff.c src/iris/Makefile src/iris/color.c src/iris/config.c src/iris/config.h src/iris/iris.c src/iris/iris.h src/iris/particle.h src/iris/theme.c src/iris/theme_flash.c src/iris/theme_float.c src/iris/theme_fountain.c src/iris/theme_knot.c src/iris/theme_original.c src/iris/theme_pinwheel.c src/iris/theme_pipes.c src/iris/theme_pyramid.c src/iris/theme_spectrotoy.c src/iris/theme_spectrum.c src/iris/theme_squarefield.c src/iris/theme_waves.c src/iris/transition.c
diffstat 24 files changed, 7531 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Oct 24 19:50:04 2006 -0700
+++ b/ChangeLog	Tue Oct 24 21:25:31 2006 -0700
@@ -1,3 +1,11 @@
+2006-10-25 02:50:04 +0000  William Pitcock <nenolod@nenolod.net>
+  revision [230]
+  - make sure the tuple data is copied, not referenced (oops)
+  
+  trunk/src/wavpack/libwavpack.cxx |   18 ++++++++----------
+  1 file changed, 8 insertions(+), 10 deletions(-)
+
+
 2006-10-25 02:43:30 +0000  William Pitcock <nenolod@nenolod.net>
   revision [228]
   - tuple support
--- a/configure.ac	Tue Oct 24 19:50:04 2006 -0700
+++ b/configure.ac	Tue Oct 24 21:25:31 2006 -0700
@@ -824,6 +824,18 @@
 	INPUT_PLUGINS="$INPUT_PLUGINS timidity"
 fi
 
+dnl *** Iris
+
+AC_ARG_ENABLE(iris,
+[  --disable-iris          disable iris plugin. (default=enabled)],
+[enable_iris=$enableval],
+[enable_iris=yes]
+)
+
+if test "$enable_iris" = "yes"; then
+	VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS iris"
+fi
+
 dnl FreeBSD newpcm driver detection
 
 AC_CACHE_CHECK(for FreeBSD newpcm driver, beep_cv_newpcm_driver,
@@ -1127,6 +1139,7 @@
 echo "  -------------"
 echo "  Blur Scope:                             yes"
 echo "  Paranormal Visualization Library:       $have_paranormal"
+echo "  IRIS 3D:                                $enable_iris"
 echo
 echo "  Container"
 echo "  ---------"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/3Dstuff.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,51 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "iris.h"
+
+
+void
+bar_top_or_bottom (GLfloat height, xz * xz1, xz * xz2, xz * xz3, xz * xz4)
+{
+  glVertex3f (xz1->x, height, xz1->z);
+  glVertex3f (xz2->x, height, xz2->z);
+  glVertex3f (xz4->x, height, xz4->z);
+  glVertex3f (xz3->x, height, xz3->z);
+}
+
+
+void
+bar_side (GLfloat height, xz * xz1, xz * xz2)
+{
+  glVertex3f (xz1->x, height, xz1->z);
+  glVertex3f (xz1->x, 0, xz1->z);
+  glVertex3f (xz2->x, 0, xz2->z);
+
+  glVertex3f (xz2->x, height, xz2->z);
+}
+
+
+void
+bar_full (GLfloat height, xz * xz1, xz * xz2, xz * xz3, xz * xz4)
+{
+  bar_top_or_bottom (height, xz1, xz2, xz3, xz4);
+  bar_side (height, xz1, xz2);
+  bar_side (height, xz3, xz4);
+  bar_side (height, xz1, xz2);
+  bar_side (height, xz3, xz4);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/Makefile	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,34 @@
+include ../../mk/rules.mk
+include ../../mk/init.mk
+
+OBJECTIVE_LIBS = libiris$(SHARED_SUFFIX)
+
+LIBDIR = $(plugindir)/$(VISUALIZATION_PLUGIN_DIR)
+
+LIBADD = $(GTK_LIBS)
+
+SOURCES = \
+	3Dstuff.c		\
+	color.c			\
+	config.c		\
+	iris.c			\
+	theme.c			\
+	theme_flash.c		\
+	theme_float.c		\
+	theme_fountain.c	\
+	theme_knot.c		\
+	theme_original.c	\
+	theme_pinwheel.c	\
+	theme_pipes.c		\
+	theme_pyramid.c		\
+	theme_spectrotoy.c	\
+	theme_spectrum.c	\
+	theme_squarefield.c	\
+	theme_waves.c		\
+	transition.c
+
+OBJECTS = ${SOURCES:.c=.o}
+
+CFLAGS += $(PICFLAGS) -D_REENTRANT $(GTK_CFLAGS) $(ARCH_DEFINES) -I../../intl -I../..
+
+include ../../mk/objective.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/color.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,55 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include "iris.h"
+
+void
+get_color (GLfloat * red, GLfloat * green, GLfloat * blue, GLfloat * signal)
+{
+  switch (config.color_mode)
+    {
+    case 0:
+      {
+	*red = config.color_red;
+	*green = config.color_green;
+	*blue = config.color_blue;
+	break;
+      }
+    case 1:
+      {
+	*red =
+	  config.color1_red +
+	  ((*signal) * (config.color2_red - config.color1_red));
+	*green =
+	  config.color1_green +
+	  ((*signal) * (config.color2_green - config.color1_green));
+	*blue =
+	  config.color1_blue +
+	  ((*signal) * (config.color2_blue - config.color1_blue));
+	break;
+      }
+    case 2:
+      {
+	*red = 1.0 * rand () / (RAND_MAX + 1.0);
+	*green = 1.0 * rand () / (RAND_MAX + 1.0);
+	*blue = 1.0 * rand () / (RAND_MAX + 1.0);
+	break;
+      }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/config.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,1289 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <audacious/configdb.h>
+#include <GL/gl.h>
+#include "iris.h"
+#include "config.h"
+
+iris_config config;
+iris_config newconfig;
+GLWindow GLWin;
+
+static char section_name[] = "iris";
+
+GtkWidget *config_window;
+
+GtkWidget *preview_color_one_color;
+GtkWidget *preview_color_two_colors_1;
+GtkWidget *preview_color_two_colors_2;
+GtkWidget *preview_background;
+GtkWidget *preview_flash;
+
+static GtkWidget *config_ctree;
+static GtkWidget *config_notebook;
+static gint config_page;
+
+static gboolean
+check_cfg_version (ConfigDb * db)
+{
+  char *vstr;
+
+  if (bmp_cfg_db_get_string (db, "iris", "version", &vstr))
+    if (!strcmp (vstr, VERSION))
+      return FALSE;
+  return TRUE;
+}
+
+
+void
+iris_set_default_prefs (void)
+{
+  int i;
+
+  for (i = 0; i < THEME_NUMBER; i++)
+    {
+      theme_config_global_default (i);
+      if (theme[i].config_default != NULL)
+	theme[i].config_default ();
+    }
+
+  config.bgc_red = 0.0;
+  config.bgc_green = 0.0;
+  config.bgc_blue = 0.0;
+
+  config.bgc_random = FALSE;
+
+  config.color_red = 0.0;
+  config.color_green = 0.0;
+  config.color_blue = 1.0;
+
+  config.color_random = TRUE;
+
+  config.color1_red = 1.0;
+  config.color1_green = 0.0;
+  config.color1_blue = 0.0;
+
+  config.color2_red = 0.0;
+  config.color2_green = 1.0;
+  config.color2_blue = 0.0;
+
+  config.color12_random = TRUE;
+
+  config.color_flash_red = 1.0;
+  config.color_flash_green = 1.0;
+  config.color_flash_blue = 1.0;
+
+  config.color_mode = 1;
+
+  config.color_beat = TRUE;
+
+  config.flash_speed = 5;
+
+  config.fps = 50;
+
+  config.change_theme_on_beat = FALSE;
+
+  config.fs_width = 640;
+  config.fs_height = 480;
+
+  config.window_width = 640;
+  config.window_height = 480;
+
+  config.fullscreen = FALSE;
+
+  config.transition = TRUE;
+  config.trans_duration = 10.0;
+}
+
+
+void
+iris_config_read (void)
+{
+  ConfigDb *db;
+
+  db = bmp_cfg_db_open();
+  
+  /* Check the config version string. If the string is too old, default values
+   * are installed. If the string returns NULL, iris has not been run before,
+   * and default values are installed. */
+  if (check_cfg_version (db))
+  {
+    printf("Bad iris plugin version detected in config, using default configuration\n");
+    iris_set_default_prefs ();
+  }
+  else
+  {
+    int i;
+
+    /* load config of all the theme */
+    for (i = 0; i < THEME_NUMBER; i++)
+    {
+      theme_config_global_read (db, section_name, i);
+      if (theme[i].config_read != NULL)
+      theme[i].config_read (db, section_name);
+    }
+
+    bmp_cfg_db_get_float  (db, section_name, "bgc_red", &config.bgc_red);
+    bmp_cfg_db_get_float  (db, section_name, "bgc_green", &config.bgc_green);
+    bmp_cfg_db_get_float  (db, section_name, "bgc_blue", &config.bgc_blue);
+    bmp_cfg_db_get_bool   (db, section_name, "bgc_random", &config.bgc_random);
+    bmp_cfg_db_get_float  (db, section_name, "color_red", &config.color_red);
+    bmp_cfg_db_get_float  (db, section_name, "color_green", &config.color_green);
+    bmp_cfg_db_get_float  (db, section_name, "color_blue", &config.color_blue);
+    bmp_cfg_db_get_bool	  (db, section_name, "color_random", &config.color_random);
+    bmp_cfg_db_get_float  (db, section_name, "color1_red", &config.color1_red);
+    bmp_cfg_db_get_float  (db, section_name, "color1_green", &config.color1_green);
+    bmp_cfg_db_get_float  (db, section_name, "color1_blue", &config.color1_blue);
+    bmp_cfg_db_get_float  (db, section_name, "color2_red", &config.color2_red);
+    bmp_cfg_db_get_float  (db, section_name, "color2_green", &config.color2_green);
+    bmp_cfg_db_get_float  (db, section_name, "color2_blue", &config.color2_blue);
+    bmp_cfg_db_get_bool	  (db, section_name, "color12_random", &config.color12_random);
+    bmp_cfg_db_get_float  (db, section_name, "color_flash_red", &config.color_flash_red);
+    bmp_cfg_db_get_float  (db, section_name, "color_flash_green", &config.color_flash_green);
+    bmp_cfg_db_get_float  (db, section_name, "color_flash_blue", &config.color_flash_blue);
+    bmp_cfg_db_get_int	  (db, section_name, "color_mode", &config.color_mode);
+    bmp_cfg_db_get_bool	  (db, section_name, "color_beat", &config.color_beat);
+    bmp_cfg_db_get_int	  (db, section_name, "flash_speed", &config.flash_speed);
+    bmp_cfg_db_get_int	  (db, section_name, "fps", &config.fps);
+    bmp_cfg_db_get_bool	  (db, section_name, "change_theme_on_beat", &config.change_theme_on_beat);
+    bmp_cfg_db_get_int	  (db, section_name, "fs_width", &config.fs_width);
+    bmp_cfg_db_get_int	  (db, section_name, "fs_height", &config.fs_height);
+    bmp_cfg_db_get_int	  (db, section_name, "window_width", &config.window_width);
+    bmp_cfg_db_get_int	  (db, section_name, "window_height", &config.window_height);
+    bmp_cfg_db_get_bool	  (db, section_name, "fullscreen", &config.fullscreen);
+    bmp_cfg_db_get_bool	  (db, section_name, "transition", &config.transition);
+    bmp_cfg_db_get_float  (db, section_name, "trans_duration", &config.trans_duration);
+  }
+  bmp_cfg_db_close(db);
+}
+
+
+void
+iris_config_write (iris_config * config)
+{
+  ConfigDb *db;
+  int i;
+
+  db = bmp_cfg_db_open();
+  
+  /* save config of all the theme */
+  for (i = 0; i < THEME_NUMBER; i++)
+    {
+      theme_config_global_write (db, section_name, i);
+      if (theme[i].config_write != NULL)
+	theme[i].config_write (db, section_name);
+    }
+
+  /* Save the current configuration in the "iris" section */
+  bmp_cfg_db_set_string	(db, section_name, "version", VERSION);
+  bmp_cfg_db_set_float	(db, section_name, "bgc_red", config->bgc_red);
+  bmp_cfg_db_set_float	(db, section_name, "bgc_green", config->bgc_green);
+  bmp_cfg_db_set_float	(db, section_name, "bgc_blue", config->bgc_blue);
+  bmp_cfg_db_set_bool	(db, section_name, "bgc_random", config->bgc_random);
+  bmp_cfg_db_set_float	(db, section_name, "color_red", config->color_red);
+  bmp_cfg_db_set_float	(db, section_name, "color_green", config->color_green);
+  bmp_cfg_db_set_float	(db, section_name, "color_blue", config->color_blue);
+  bmp_cfg_db_set_bool	(db, section_name, "color_random", config->color_random);
+  bmp_cfg_db_set_float	(db, section_name, "color1_red", config->color1_red);
+  bmp_cfg_db_set_float	(db, section_name, "color1_green", config->color1_green);
+  bmp_cfg_db_set_float	(db, section_name, "color1_blue", config->color1_blue);
+  bmp_cfg_db_set_float	(db, section_name, "color2_red", config->color2_red);
+  bmp_cfg_db_set_float	(db, section_name, "color2_green", config->color2_green);
+  bmp_cfg_db_set_float	(db, section_name, "color2_blue", config->color2_blue);
+  bmp_cfg_db_set_bool	(db, section_name, "color12_random", config->color12_random);
+  bmp_cfg_db_set_float	(db, section_name, "color_flash_red", config->color_flash_red);
+  bmp_cfg_db_set_float	(db, section_name, "color_flash_green", config->color_flash_green);
+  bmp_cfg_db_set_float	(db, section_name, "color_flash_blue", config->color_flash_blue);
+  bmp_cfg_db_set_int	(db, section_name, "color_mode", config->color_mode);
+  bmp_cfg_db_set_bool	(db, section_name, "color_beat", config->color_beat);
+  bmp_cfg_db_set_int	(db, section_name, "flash_speed", config->flash_speed);
+  bmp_cfg_db_set_int	(db, section_name, "fps", config->fps);
+  bmp_cfg_db_set_bool	(db, section_name, "change_theme_on_beat", config->change_theme_on_beat);
+  bmp_cfg_db_set_int	(db, section_name, "fs_width", config->fs_width);
+  bmp_cfg_db_set_int	(db, section_name, "fs_height", config->fs_height);
+  bmp_cfg_db_set_int	(db, section_name, "window_width", config->window_width);
+  bmp_cfg_db_set_int	(db, section_name, "window_height", config->window_height);
+  bmp_cfg_db_set_bool	(db, section_name, "fullscreen", config->fullscreen);
+  bmp_cfg_db_set_bool	(db, section_name, "transition", config->transition);
+  bmp_cfg_db_set_float	(db, section_name, "trans_duration", config->trans_duration);
+
+  /* write out the XMMS config file */
+  bmp_cfg_db_close(db);
+}
+
+
+static void
+set_color_preview (GLfloat red, GLfloat green, GLfloat blue,
+		   GtkWidget * preview)
+{
+  unsigned int a;
+  guchar buf[3 * 32];
+  char r, g, b;
+  char s[3];
+
+  // how to convert a float into a char ?
+  sprintf (s, "%.0f", red * 255);
+  r = (unsigned char) atoi (s);
+  sprintf (s, "%.0f", green * 255);
+  g = (unsigned char) atoi (s);
+  sprintf (s, "%.0f", blue * 255);
+  b = (unsigned char) atoi (s);
+
+  for (a = 0; a < 32; a++)
+    {
+      buf[3 * a] = (char) r;
+      buf[3 * a + 1] = (char) g;
+      buf[3 * a + 2] = (char) b;
+    }
+
+  for (a = 0; a < 16; a++)
+    gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, a, 32);
+
+  gtk_widget_draw (preview, NULL);
+}
+
+
+static void
+csel_ok (GtkWidget * w, GtkWidget * csel)
+{
+  gdouble a[3];
+
+  gtk_color_selection_get_color (GTK_COLOR_SELECTION
+				 (GTK_COLOR_SELECTION_DIALOG (csel)->
+				  colorsel), &a[0]);
+
+  gtk_widget_destroy (csel);
+}
+
+
+static void
+csel_ok2 (GtkWidget * csel, gpointer data)
+{
+  gdouble a[3];
+
+  gtk_color_selection_get_color (GTK_COLOR_SELECTION
+				 (GTK_COLOR_SELECTION_DIALOG (csel)->
+				  colorsel), &a[0]);
+
+  switch ((int) data)
+    {
+    case 0:
+      {
+	newconfig.color_red = (GLfloat) a[0];
+	newconfig.color_green = (GLfloat) a[1];
+	newconfig.color_blue = (GLfloat) a[2];
+	set_color_preview (newconfig.color_red, newconfig.color_green,
+			   newconfig.color_blue, preview_color_one_color);
+	break;
+      }
+    case 1:
+      {
+	newconfig.color1_red = (GLfloat) a[0];
+	newconfig.color1_green = (GLfloat) a[1];
+	newconfig.color1_blue = (GLfloat) a[2];
+	set_color_preview (newconfig.color1_red, newconfig.color1_green,
+			   newconfig.color1_blue, preview_color_two_colors_1);
+	break;
+      }
+    case 2:
+      {
+	newconfig.color2_red = (GLfloat) a[0];
+	newconfig.color2_green = (GLfloat) a[1];
+	newconfig.color2_blue = (GLfloat) a[2];
+	set_color_preview (newconfig.color2_red, newconfig.color2_green,
+			   newconfig.color2_blue, preview_color_two_colors_2);
+	break;
+      }
+    case 3:
+      {
+	newconfig.bgc_red = (GLfloat) a[0];
+	newconfig.bgc_green = (GLfloat) a[1];
+	newconfig.bgc_blue = (GLfloat) a[2];
+	set_color_preview (newconfig.bgc_red, newconfig.bgc_green,
+			   newconfig.bgc_blue, preview_background);
+	break;
+      }
+    case 4:
+      {
+	newconfig.color_flash_red = (GLfloat) a[0];
+	newconfig.color_flash_green = (GLfloat) a[1];
+	newconfig.color_flash_blue = (GLfloat) a[2];
+	set_color_preview (newconfig.color_flash_red,
+			   newconfig.color_flash_green,
+			   newconfig.color_flash_blue, preview_flash);
+	break;
+      }
+    }
+
+  gtk_widget_destroy (csel);
+}
+
+
+static void
+apply_clicked (void)
+{
+  gint i;
+
+  memcpy (&config, &newconfig, sizeof (iris_config));
+  for (i = 0; i < THEME_NUMBER; i++)
+    {
+      memcpy (theme[i].config->global, theme[i].config_new->global,
+	      sizeof (config_global));
+      theme_config_apply (i);
+    }
+}
+
+
+static void
+cancel_clicked (GtkWidget * w, GtkWidget * window)
+{
+  gtk_widget_destroy (window);
+  config_window = NULL;
+}
+
+
+static void
+csel_deleteevent (GtkWidget * w, GtkWidget * csel)
+{
+  gtk_widget_destroy (csel);
+}
+
+
+static void
+ok_clicked (GtkWidget * w, GtkWidget * window)
+{
+  apply_clicked ();
+  iris_config_write (&newconfig);
+  cancel_clicked (w, window);
+}
+
+
+static void
+color_clicked (GtkWidget * w, gpointer data)
+{
+  GtkWidget *csel;
+  gdouble a[3];
+
+  switch ((int) data)
+    {
+    case 0:
+      {
+	a[0] = (gdouble) newconfig.color_red;
+	a[1] = (gdouble) newconfig.color_green;
+	a[2] = (gdouble) newconfig.color_blue;
+	break;
+      }
+    case 1:
+      {
+	a[0] = (gdouble) newconfig.color1_red;
+	a[1] = (gdouble) newconfig.color1_green;
+	a[2] = (gdouble) newconfig.color1_blue;
+	break;
+      }
+    case 2:
+      {
+	a[0] = (gdouble) newconfig.color2_red;
+	a[1] = (gdouble) newconfig.color2_green;
+	a[2] = (gdouble) newconfig.color2_blue;
+	break;
+      }
+    case 3:
+      {
+	a[0] = (gdouble) newconfig.bgc_red;
+	a[1] = (gdouble) newconfig.bgc_green;
+	a[2] = (gdouble) newconfig.bgc_blue;
+	break;
+      }
+    case 4:
+      {
+	a[0] = (gdouble) newconfig.color_flash_red;
+	a[1] = (gdouble) newconfig.color_flash_green;
+	a[2] = (gdouble) newconfig.color_flash_blue;
+	break;
+      }
+    }
+
+  csel = gtk_color_selection_dialog_new ("Please choose a color");
+  /*gtk_window_set_modal (GTK_WINDOW
+			(&(GTK_COLOR_SELECTION_DIALOG (csel)->window)), TRUE);
+  gtk_window_set_transient_for (GTK_WINDOW
+				(&
+				 (GTK_COLOR_SELECTION_DIALOG (csel)->window)),
+				GTK_WINDOW (config_window)); */
+  gtk_widget_hide (GTK_COLOR_SELECTION_DIALOG (csel)->help_button);
+  gtk_widget_hide (GTK_COLOR_SELECTION_DIALOG (csel)->cancel_button);
+  gtk_color_selection_set_color (GTK_COLOR_SELECTION
+				 (GTK_COLOR_SELECTION_DIALOG (csel)->
+				  colorsel), &a[0]);
+  gtk_widget_show (csel);
+
+  gtk_signal_connect (GTK_OBJECT
+		      (GTK_COLOR_SELECTION_DIALOG (csel)->ok_button),
+		      "clicked", GTK_SIGNAL_FUNC (csel_ok), csel);
+  gtk_signal_connect (GTK_OBJECT (csel), "delete_event",
+		      GTK_SIGNAL_FUNC (csel_deleteevent), csel);
+  gtk_signal_connect (GTK_OBJECT (csel), "destroy",
+		      GTK_SIGNAL_FUNC (csel_ok2), data);
+}
+
+
+void
+colormode_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.color_mode = (unsigned int) data;
+}
+
+
+void
+colorbeat_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.color_beat = !newconfig.color_beat;
+}
+
+
+void
+theme_beat_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.change_theme_on_beat = !newconfig.change_theme_on_beat;
+}
+
+
+void
+color_random_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.color_random = !newconfig.color_random;
+}
+
+
+void
+color12_random_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.color12_random = !newconfig.color12_random;
+}
+
+
+void
+bgc_random_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.bgc_random = !newconfig.bgc_random;
+}
+
+
+void
+wireframe_toggled (GtkWidget * widget, gpointer * data)
+{
+  newconfig.wireframe = !newconfig.wireframe;
+}
+
+
+void
+fullscreen_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.fullscreen = !newconfig.fullscreen;
+}
+
+void
+transition_toggled (GtkWidget * widget, gpointer data)
+{
+  newconfig.transition = !newconfig.transition;
+}
+
+static void
+combo_fs_activated (GtkWidget * widget, gpointer data)
+{
+  sscanf (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (data)->entry)), "%dx%d",
+	  &newconfig.fs_width, &newconfig.fs_height);
+}
+
+
+static void
+value_flash_speed (GtkAdjustment * adj)
+{
+  newconfig.flash_speed = (int) adj->value;
+}
+
+static void
+value_trans_duration (GtkAdjustment * adj)
+{
+  newconfig.trans_duration = (int) adj->value;
+}
+
+static void
+conf_closed (GtkWidget * w, GdkEvent * e, GtkWidget ** window)
+{
+  gtk_widget_destroy (*window);
+  *window = NULL;
+}
+
+
+static void
+priority_value_changed (GtkAdjustment * adj, gint i)
+{
+  theme[i].config_new->global->priority = adj->value / 100.0;
+}
+
+
+static void
+create_config_color (GtkWidget * vbox_container)
+{
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GSList *group;
+
+  GtkWidget *radio_button_one_color;
+  GtkWidget *button_color_one_color;
+  //  GtkWidget *preview_color_one_color; must be static
+
+  GtkWidget *radio_button_two_colors;
+  GtkWidget *button_color_two_colors_1;
+  GtkWidget *button_color_two_colors_2;
+  //  GtkWidget *preview_color_two_colors_1; must be static
+  //  GtkWidget *preview_color_two_colors_2; must be static
+
+  GtkWidget *check_button;
+
+  GtkWidget *hseparator;
+
+  GtkWidget *label;
+  GtkWidget *button_background;
+  //  GtkWidget *preview_background; static
+
+  frame = gtk_frame_new ("color");
+  gtk_box_pack_start (GTK_BOX (vbox_container), frame, TRUE, TRUE, 0);
+  vbox = gtk_vbox_new (TRUE, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+  /* the first hbox: a radio button and a color selection/preview button */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 8);
+
+  radio_button_one_color =
+    gtk_radio_button_new_with_label (NULL, "one color");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_one_color, FALSE, FALSE,
+		      4);
+  gtk_widget_set_usize (radio_button_one_color, 100, 20);
+  gtk_widget_show (radio_button_one_color);
+
+  button_color_one_color = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button_color_one_color, FALSE, FALSE,
+		      4);
+  gtk_widget_show (button_color_one_color);
+  preview_color_one_color = gtk_preview_new (GTK_PREVIEW_COLOR);
+  gtk_preview_size (GTK_PREVIEW (preview_color_one_color), 32, 16);
+  gtk_widget_show (preview_color_one_color);
+  gtk_container_add (GTK_CONTAINER (button_color_one_color),
+		     preview_color_one_color);
+  set_color_preview (newconfig.color_red, newconfig.color_green,
+		     newconfig.color_blue, preview_color_one_color);
+  gtk_widget_set_usize (button_color_one_color, 50, 20);
+  gtk_signal_connect (GTK_OBJECT (button_color_one_color), "clicked",
+		      GTK_SIGNAL_FUNC (color_clicked), (gpointer) 0);
+
+  /* the second hbox: a radio button and two color selection/preview buttons */
+
+  hbox = gtk_hbox_new (FALSE, 3);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 8);
+
+  group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button_one_color));
+  radio_button_two_colors =
+    gtk_radio_button_new_with_label (group, "two colors");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button_two_colors),
+				TRUE);
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_two_colors, FALSE, FALSE,
+		      4);
+  gtk_widget_set_usize (radio_button_two_colors, 100, 20);
+  gtk_widget_show (radio_button_two_colors);
+
+  button_color_two_colors_1 = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button_color_two_colors_1, FALSE, FALSE,
+		      4);
+  gtk_widget_show (button_color_two_colors_1);
+  preview_color_two_colors_1 = gtk_preview_new (GTK_PREVIEW_COLOR);
+  gtk_preview_size (GTK_PREVIEW (preview_color_two_colors_1), 32, 16);
+  gtk_widget_show (preview_color_two_colors_1);
+  gtk_container_add (GTK_CONTAINER (button_color_two_colors_1),
+		     preview_color_two_colors_1);
+  set_color_preview (newconfig.color1_red, newconfig.color1_green,
+		     newconfig.color1_blue, preview_color_two_colors_1);
+  gtk_widget_set_usize (button_color_two_colors_1, 50, 20);
+
+  gtk_signal_connect (GTK_OBJECT (button_color_two_colors_1), "clicked",
+		      GTK_SIGNAL_FUNC (color_clicked), (gpointer) 1);
+
+  button_color_two_colors_2 = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button_color_two_colors_2, FALSE, FALSE,
+		      4);
+  gtk_widget_show (button_color_two_colors_2);
+  preview_color_two_colors_2 = gtk_preview_new (GTK_PREVIEW_COLOR);
+  gtk_preview_size (GTK_PREVIEW (preview_color_two_colors_2), 32, 16);
+  gtk_widget_show (preview_color_two_colors_2);
+  gtk_container_add (GTK_CONTAINER (button_color_two_colors_2),
+		     preview_color_two_colors_2);
+  set_color_preview (newconfig.color2_red, newconfig.color2_green,
+		     newconfig.color2_blue, preview_color_two_colors_2);
+  gtk_widget_set_usize (button_color_two_colors_2, 50, 20);
+
+  gtk_signal_connect (GTK_OBJECT (button_color_two_colors_2), "clicked",
+		      GTK_SIGNAL_FUNC (color_clicked), (gpointer) 2);
+
+  switch (newconfig.color_mode)
+    {
+    case 0:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_one_color), TRUE);
+	break;
+      }
+    case 1:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_two_colors), TRUE);
+      }
+    }
+
+  gtk_signal_connect (GTK_OBJECT (radio_button_one_color), "toggled",
+		      GTK_SIGNAL_FUNC (colormode_toggled), (gpointer) 0);
+  gtk_signal_connect (GTK_OBJECT (radio_button_two_colors), "toggled",
+		      GTK_SIGNAL_FUNC (colormode_toggled), (gpointer) 1);
+
+  check_button = gtk_check_button_new_with_label ("Random on beat");
+  gtk_widget_show (check_button);
+  gtk_box_pack_start (GTK_BOX (vbox), check_button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
+				newconfig.color12_random);
+  gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+		      GTK_SIGNAL_FUNC (color12_random_toggled), NULL);
+
+  hseparator = gtk_hseparator_new ();
+  gtk_widget_show (hseparator);
+  gtk_box_pack_start (GTK_BOX (vbox), hseparator, FALSE, FALSE, 4);
+
+  /* the third hbox: a color selection/preview button */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Background color");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  button_background = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button_background, FALSE, FALSE, 4);
+  gtk_widget_show (button_background);
+  preview_background = gtk_preview_new (GTK_PREVIEW_COLOR);
+  gtk_preview_size (GTK_PREVIEW (preview_background), 32, 16);
+  gtk_widget_show (preview_background);
+  gtk_container_add (GTK_CONTAINER (button_background), preview_background);
+  set_color_preview (newconfig.bgc_red, newconfig.bgc_green,
+		     newconfig.bgc_blue, preview_background);
+  gtk_widget_set_usize (button_background, 50, 20);
+
+  gtk_signal_connect (GTK_OBJECT (button_background), "clicked",
+		      GTK_SIGNAL_FUNC (color_clicked), (gpointer) 3);
+
+  check_button = gtk_check_button_new_with_label ("Random on beat");
+  gtk_widget_show (check_button);
+  gtk_box_pack_start (GTK_BOX (vbox), check_button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
+				newconfig.bgc_random);
+  gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+		      GTK_SIGNAL_FUNC (bgc_random_toggled), NULL);
+/*
+  check_button = gtk_check_button_new_with_label ("Wireframe");
+  gtk_widget_show (check_button);
+  gtk_box_pack_start (GTK_BOX (vbox), check_button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
+				newconfig.wireframe);
+  gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+		      GTK_SIGNAL_FUNC (wireframe_toggled), NULL);
+*/
+  /* end */
+
+}
+
+
+static void
+create_config_beat (GtkWidget * vbox_container)
+{
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+
+  GtkWidget *button_beat;
+  GtkWidget *button_theme_beat;
+
+  GtkWidget *label;
+  GtkWidget *button_flash;
+  GtkWidget *preview_flash;
+
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  frame = gtk_frame_new ("beat");
+  gtk_box_pack_start (GTK_BOX (vbox_container), frame, TRUE, TRUE, 0);
+  vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+  /* the first hbox: two buttons */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button_beat = gtk_check_button_new_with_label ("Flash on beat");
+  gtk_widget_show (button_beat);
+  gtk_box_pack_start (GTK_BOX (hbox), button_beat, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_beat),
+				newconfig.color_beat);
+  gtk_signal_connect (GTK_OBJECT (button_beat), "toggled",
+		      GTK_SIGNAL_FUNC (colorbeat_toggled), NULL);
+
+  button_theme_beat =
+    gtk_check_button_new_with_label ("Change theme on beat");
+  gtk_widget_show (button_theme_beat);
+  gtk_box_pack_start (GTK_BOX (hbox), button_theme_beat, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_theme_beat),
+				newconfig.change_theme_on_beat);
+  gtk_signal_connect (GTK_OBJECT (button_theme_beat), "toggled",
+		      GTK_SIGNAL_FUNC (theme_beat_toggled), NULL);
+
+  /* the second hbox: a label and a color selection/preview button */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Flash color");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  button_flash = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button_flash, FALSE, FALSE, 4);
+  gtk_widget_show (button_flash);
+  preview_flash = gtk_preview_new (GTK_PREVIEW_COLOR);
+  gtk_preview_size (GTK_PREVIEW (preview_flash), 32, 16);
+  gtk_widget_show (preview_flash);
+  gtk_container_add (GTK_CONTAINER (button_flash), preview_flash);
+  set_color_preview (newconfig.color_flash_red, newconfig.color_flash_green,
+		     newconfig.color_flash_blue, preview_flash);
+  gtk_widget_set_usize (button_flash, 50, 20);
+  gtk_signal_connect (GTK_OBJECT (button_flash), "clicked",
+		      GTK_SIGNAL_FUNC (color_clicked), (gpointer) 4);
+
+  /* the third hbox: a label and a horizontal scale */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Flash duration (in frames)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment = gtk_adjustment_new (newconfig.flash_speed, 1, 50, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_LEFT);
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_flash_speed), NULL);
+
+  label =
+    gtk_label_new
+    ("Image are drawn at a rate of 50 frames per second.\n So a flash of 50 frames lasts 1 second.");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+}
+
+
+static void
+create_config_fs (GtkWidget * vbox_container)
+{
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+
+  GtkWidget *button_fs;
+  GtkWidget *combobox_fs;
+
+  GtkWidget *label;
+
+  char str[10];
+
+  frame = gtk_frame_new ("fullscreen");
+  gtk_box_pack_start (GTK_BOX (vbox_container), frame, TRUE, TRUE, 0);
+  vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+  /* the first hbox: a button */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button_fs = gtk_check_button_new_with_label ("Start in fullscreen mode");
+  gtk_widget_show (button_fs);
+  gtk_box_pack_start (GTK_BOX (hbox), button_fs, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_fs),
+				newconfig.fullscreen);
+  gtk_signal_connect (GTK_OBJECT (button_fs), "toggled",
+		      GTK_SIGNAL_FUNC (fullscreen_toggled), NULL);
+
+  /* the second hbox: a label combobox */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Fullscreen resolution");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  combobox_fs = gtk_combo_new ();
+
+  gtk_combo_set_popdown_strings (GTK_COMBO (combobox_fs), GLWin.glist);
+
+  gtk_box_pack_start (GTK_BOX (hbox), combobox_fs, FALSE, FALSE, 4);
+  gtk_widget_show (combobox_fs);
+
+  gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combobox_fs)->entry), "changed",
+		      GTK_SIGNAL_FUNC (combo_fs_activated), combobox_fs);
+  gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combobox_fs)->entry), FALSE);
+  sprintf (str, "%dx%d", newconfig.fs_width, newconfig.fs_height);
+  gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combobox_fs)->entry), str);
+
+  label = gtk_label_new
+    ("Use the f key in the GL window\nto switch to fullscreen and back.\n\
+Use the esc key to quit the plugin.\n\
+\n\
+If you use the sawfish window manager,\n\
+you may have problem going fullscreen.\n\
+In this case, switch to a console and\n\
+type \'killall xmms\'.");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+}
+
+static void
+create_config_transition (GtkWidget * vbox_container)
+{
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+
+  GtkWidget *button_ts;
+  GtkWidget *label;
+
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  frame = gtk_frame_new ("transition");
+  gtk_box_pack_start (GTK_BOX (vbox_container), frame, TRUE, TRUE, 0);
+  vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+  /* the first hbox: a button */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button_ts =
+    gtk_check_button_new_with_label ("Use transitions on theme change");
+  gtk_widget_show (button_ts);
+  gtk_box_pack_start (GTK_BOX (hbox), button_ts, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_ts),
+				newconfig.transition);
+  gtk_signal_connect (GTK_OBJECT (button_ts), "toggled",
+		      GTK_SIGNAL_FUNC (transition_toggled), NULL);
+
+  label = gtk_label_new ("Chooses a random transition for now");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+
+  /* the second hbox: a label and a horizontal scale */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Transition duration (in miliseconds)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (newconfig.trans_duration, 1.0, 50.0, 1.0, 1.0, 1.0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_LEFT);
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_trans_duration), NULL);
+}
+
+static void
+create_config_glx_info (GtkWidget * vbox_container)
+{
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+
+  GtkWidget *label;
+  
+  frame = gtk_frame_new ("GLX informations");
+  gtk_box_pack_start (GTK_BOX (vbox_container), frame, TRUE, TRUE, 0);
+  vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  if (GLWin.ctx == NULL)
+    {
+      label = gtk_label_new ("Launch the plugin and reopen the configure window to see\n\
+informations about your GL setup.");
+      gtk_widget_show (label);
+      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+    }
+  else
+    {
+      char *string;
+      string = g_strconcat ("GLX version: ", g_strdup_printf ("%d.%d", GLWin.glxMajorVersion, GLWin.glxMinorVersion), NULL);
+      label = gtk_label_new (string);
+      free(string);
+      gtk_widget_show (label);
+      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+
+      if (GLWin.DRI)
+	string = g_strconcat ("Use DRI: ", "yes", NULL);
+      else
+	string = g_strconcat ("Use DRI: ", "no", NULL);	
+      label = gtk_label_new (string);
+      free(string);
+      gtk_widget_show (label);
+      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+
+      if (GLWin.DoubleBuffered)
+	string = g_strconcat ("Double buffered rendering: ", "yes", NULL);
+      else
+	string = g_strconcat ("Double buffered rendering: : ", "no", NULL);	
+      label = gtk_label_new (string);
+      free(string);
+      gtk_widget_show (label);
+      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+    }
+}
+
+static void
+create_config_theme (GtkWidget * vbox_container)
+{
+  GtkWidget *frame;
+  GtkWidget *hbox;
+  GtkWidget *table;
+  GtkWidget *label;
+  gint i, y;
+
+  frame = gtk_frame_new ("Themes priorities");
+  gtk_box_pack_start (GTK_BOX (vbox_container), frame, TRUE, TRUE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_container_add (GTK_CONTAINER (frame), hbox);
+
+  table = gtk_table_new (2, THEME_NUMBER, FALSE);
+  gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 12);
+
+  for (i = 0, y = 0; i < THEME_NUMBER; i++)
+    {
+      GtkObject *adjustment;
+      GtkWidget *hscale;
+
+      label = gtk_label_new (theme[i].name);
+      gtk_table_attach (GTK_TABLE (table), label, 0, 1, y, y + 1, GTK_EXPAND,
+			0, 0, 8);
+      adjustment =
+	gtk_adjustment_new (theme[i].config->global->priority * 100.0, 0.0,
+			    100.0, 1.0, 10.0, 0);
+      hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+      gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+      gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_LEFT);
+      gtk_table_attach (GTK_TABLE (table), hscale, 1, 2, y, y + 1,
+			GTK_EXPAND | GTK_FILL, 0, 0, 8);
+      gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+			  GTK_SIGNAL_FUNC (priority_value_changed),
+			  (void *) i);
+
+      y++;
+    }
+
+  gtk_widget_show (frame);
+}
+
+
+static void
+cb_select_monitor_config (GtkWidget * ctree, GtkCTreeNode * node)
+{
+  gint row;
+
+  if (!GTK_CLIST (ctree)->selection)
+    return;
+  row =
+    GPOINTER_TO_INT (gtk_ctree_node_get_row_data (GTK_CTREE (ctree), node));
+  gtk_notebook_set_page (GTK_NOTEBOOK (config_notebook), row);
+}
+
+
+static GtkWidget *
+create_config_page (GtkNotebook * notebook, gchar * text, GtkCTree * ctree,
+		    GtkCTreeNode * node_parent, GtkCTreeNode ** node_result)
+{
+  GtkWidget *vbox;
+  GtkCTreeNode *node;
+  gchar *title[1] = { text };
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  node = gtk_ctree_insert_node (ctree, node_parent, NULL, title, 0,
+				NULL, NULL, NULL, NULL, FALSE, FALSE);
+  gtk_ctree_node_set_row_data (ctree, node, GINT_TO_POINTER (config_page++));
+  gtk_notebook_append_page (notebook, vbox, NULL);
+  if (node_result)
+    *node_result = node;
+  return vbox;
+}
+
+
+void
+iris_first_init (void)
+{
+  static gboolean init;
+  int i;
+
+  if (!init)
+    {
+      theme_register ();
+      theme_config_init ();
+      /* here we collect information about resolutions supported by the display */
+      /* get a connection */
+      GLWin.dpy = XOpenDisplay (0);
+      GLWin.screen = DefaultScreen (GLWin.dpy);
+      XF86VidModeQueryVersion (GLWin.dpy, &GLWin.vidModeMajorVersion,
+			       &GLWin.vidModeMinorVersion);
+      XF86VidModeGetAllModeLines (GLWin.dpy, GLWin.screen, &GLWin.modeNum,
+				  &GLWin.modes);
+      /* save desktop-resolution before switching modes */
+      GLWin.deskMode = *(GLWin.modes[0]);
+
+      /* fill an array of string for the config combo box */
+      for (i = 0; i < GLWin.modeNum; i++)
+	GLWin.glist =
+	  g_list_append (GLWin.glist,
+			 g_strdup_printf ("%dx%d", GLWin.modes[i]->hdisplay,
+					  GLWin.modes[i]->vdisplay));
+
+      init = TRUE;
+      XCloseDisplay (GLWin.dpy);
+      }
+}
+
+void
+iris_configure (void)
+{
+  GtkWidget *config_vbox;
+
+  GtkWidget *vbox, *buttonbox, *ok, *apply, *cancel;
+  GtkWidget *config_hbox;
+  GtkWidget *config_scrolled;
+
+  gchar *title[1] = { "iris config" };
+  GtkCTreeNode *node;
+  GtkCTreeNode *node_themes;
+  gint i;
+
+  if (config_window)
+    return;
+  config_page = 0;
+
+  iris_first_init ();
+  iris_config_read ();
+  memcpy (&newconfig, &config, sizeof (iris_config));
+
+  config_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_signal_connect (GTK_OBJECT (config_window), "delete_event",
+		      GTK_SIGNAL_FUNC (conf_closed), &config_window);
+  gtk_container_set_border_width (GTK_CONTAINER (config_window), 6);
+  gtk_window_set_title (GTK_WINDOW (config_window), "iris configuration");
+
+  config_hbox = gtk_hbox_new (FALSE, 4);
+  gtk_container_add (GTK_CONTAINER (config_window), config_hbox);
+
+  config_scrolled = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (config_scrolled),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_box_pack_start (GTK_BOX (config_hbox), config_scrolled, TRUE, TRUE, 0);
+
+  config_vbox = gtk_vbox_new (FALSE, 4);
+  gtk_box_pack_start (GTK_BOX (config_hbox), config_vbox, TRUE, TRUE, 0);
+
+  config_ctree = gtk_ctree_new_with_titles (1, 0, title);
+  gtk_ctree_set_indent (GTK_CTREE (config_ctree), 16);
+  gtk_clist_column_titles_passive (GTK_CLIST (config_ctree));
+  gtk_widget_set_usize (config_ctree, 150, 0);
+  gtk_container_add (GTK_CONTAINER (config_scrolled), config_ctree);
+  gtk_signal_connect (GTK_OBJECT (config_ctree), "tree_select_row",
+		      (GtkSignalFunc) cb_select_monitor_config, NULL);
+  config_notebook = gtk_notebook_new ();
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (config_notebook), FALSE);
+  gtk_box_pack_start (GTK_BOX (config_vbox), config_notebook, TRUE, TRUE, 0);
+
+  vbox = create_config_page (GTK_NOTEBOOK (config_notebook), "Color",
+			     GTK_CTREE (config_ctree), NULL, &node);
+  create_config_color (vbox);
+  gtk_ctree_select (GTK_CTREE (config_ctree), node);
+
+  vbox = create_config_page (GTK_NOTEBOOK (config_notebook), "Beat",
+			     GTK_CTREE (config_ctree), NULL, NULL);
+  create_config_beat (vbox);
+
+  vbox = create_config_page (GTK_NOTEBOOK (config_notebook),
+			     "Transition", GTK_CTREE (config_ctree),
+			     NULL, NULL);
+  create_config_transition (vbox);
+
+  vbox = create_config_page (GTK_NOTEBOOK (config_notebook),
+			     "Fullscreen", GTK_CTREE (config_ctree),
+			     NULL, NULL);
+  create_config_fs (vbox);
+
+  vbox = create_config_page (GTK_NOTEBOOK (config_notebook), "Themes",
+			     GTK_CTREE (config_ctree), NULL, &node_themes);
+  create_config_theme (vbox);
+
+  for (i = 0; i < THEME_NUMBER; i++)
+    {
+      GtkWidget *tabs;
+      GtkWidget *vbox_1, *vbox_2, *vbox_3;
+      GtkWidget *label;
+      vbox =
+	create_config_page (GTK_NOTEBOOK (config_notebook),
+			    theme[i].name,
+			    GTK_CTREE (config_ctree), node_themes, &node);
+
+      tabs = gtk_notebook_new ();
+      gtk_box_pack_start (GTK_BOX (vbox), tabs, TRUE, TRUE, 4);
+
+      /* first tab : global conf tab */
+      vbox_1 = gtk_vbox_new (FALSE, 0);
+      gtk_container_border_width (GTK_CONTAINER (vbox_1), 0);
+      theme_config_global_widgets (vbox_1, i);
+
+      label = gtk_label_new ("global settings");
+      gtk_notebook_append_page (GTK_NOTEBOOK (tabs), vbox_1, label);
+
+      /* second tab : specific theme tab */
+      if (theme[i].config_create != NULL)
+	{
+	  vbox_2 = gtk_vbox_new (FALSE, 2);
+	  theme[i].config_create (vbox_2);
+
+	  label = gtk_label_new ("theme settings");
+	  gtk_notebook_append_page (GTK_NOTEBOOK (tabs), vbox_2, label);
+	}
+
+      /* third tab : info tab */
+      vbox_3 = gtk_vbox_new (FALSE, 0);
+      gtk_container_border_width (GTK_CONTAINER (vbox_3), 0);
+      theme_about (vbox_3, i);
+
+      label = gtk_label_new ("theme info");
+      gtk_notebook_append_page (GTK_NOTEBOOK (tabs), vbox_3, label);
+
+    }
+
+  vbox = create_config_page (GTK_NOTEBOOK (config_notebook),
+			     "GLX infos", GTK_CTREE (config_ctree),
+			     NULL, NULL);
+  create_config_glx_info (vbox);
+
+  //  vbox = create_config_page(GTK_NOTEBOOK(config_notebook), _("About"),
+  //                GTK_CTREE(config_ctree), NULL, NULL);
+  // create_config_about(vbox);
+
+  /* this is the box where are Ok, Cancel and Apply */
+  buttonbox = gtk_hbutton_box_new ();
+  gtk_box_pack_end (GTK_BOX (config_vbox), buttonbox, FALSE, FALSE, 8);
+  gtk_hbutton_box_set_layout_default (GTK_BUTTONBOX_END);
+  gtk_widget_show (buttonbox);
+
+  ok = gtk_button_new_with_label ("Quit\nand save");
+  GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
+  gtk_box_pack_end (GTK_BOX (buttonbox), ok, FALSE, FALSE, 8);
+  gtk_widget_show (ok);
+
+  cancel = gtk_button_new_with_label ("Quit\nwithout saving");
+  GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
+  gtk_box_pack_end (GTK_BOX (buttonbox), cancel, FALSE, FALSE, 8);
+  gtk_widget_show (cancel);
+
+  apply = gtk_button_new_with_label ("Apply");
+  GTK_WIDGET_SET_FLAGS (apply, GTK_CAN_DEFAULT);
+  gtk_box_pack_end (GTK_BOX (buttonbox), apply, FALSE, FALSE, 8);
+  gtk_widget_show (apply);
+
+  gtk_window_set_default (GTK_WINDOW (config_window), ok);
+
+  gtk_signal_connect (GTK_OBJECT (cancel), "clicked",
+		      GTK_SIGNAL_FUNC (cancel_clicked), config_window);
+  gtk_signal_connect (GTK_OBJECT (ok), "clicked",
+		      GTK_SIGNAL_FUNC (ok_clicked), config_window);
+  gtk_signal_connect (GTK_OBJECT (apply), "clicked",
+		      GTK_SIGNAL_FUNC (apply_clicked), config_window);
+
+  gtk_widget_show_all (config_window);
+}
+
+/* 
+** Saves all window attributes (goal)
+** saves only non-fullscreen window sizes for now
+** ADDME : window position
+*/
+void
+iris_save_window_attributes (void)
+{
+  XWindowAttributes attr;
+  if (!GLWin.fs)
+    {
+      XGetWindowAttributes (GLWin.dpy, GLWin.window, &attr);
+      config.window_width = attr.width;
+      config.window_height = attr.height;
+      iris_config_write (&config);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/config.h	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,64 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <GL/glx.h> header file. */
+#define HAVE_GL_GLX_H 1
+
+/* Define to 1 if you have the <GL/gl.h> header file. */
+#define HAVE_GL_GL_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "Iris"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Iris OpenGL XMMS Visualization"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Iris OpenGL XMMS Visualization"
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION 
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.12"
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/iris.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,1025 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <gtk/gtk.h>
+#include <math.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <X11/extensions/xf86vmode.h>
+#include <pthread.h>
+#ifdef HAVE_SCHED_SETSCHEDULER
+#include <sched.h>
+#endif
+#include <stdlib.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <audacious/plugin.h>
+#include <audacious/util.h>
+#include <audacious/beepctrl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+#define BEAT_MAX 100
+
+GLfloat y_angle = 45.0, y_speed = 0.5;
+GLfloat x_angle = 20.0, x_speed = 0.0;
+GLfloat z_angle = 0.0, z_speed = 0.0;
+static GLfloat scale;
+static GLfloat x_angle_wanted;
+
+GLWindow GLWin;
+
+/* attributes for a single buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListSgl[] = { GLX_RGBA, GLX_RED_SIZE, 4,
+  GLX_GREEN_SIZE, 4,
+  GLX_BLUE_SIZE, 4,
+  GLX_DEPTH_SIZE, 16,
+  None
+};
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+  GLX_RED_SIZE, 4,
+  GLX_GREEN_SIZE, 4,
+  GLX_BLUE_SIZE, 4,
+  GLX_DEPTH_SIZE, 16,
+  None
+};
+
+static gboolean going = FALSE;
+static gboolean initialized = FALSE;
+static gboolean grabbed_pointer = FALSE, firsttime = TRUE;
+static Atom wmDelete;
+static pthread_t draw_thread;
+
+datas_t datas;
+
+static int num_bands = NUM_BANDS;
+static int beat = 0;
+
+unsigned int transition_frames = 0;
+unsigned int max_transition_frames = 0;
+
+static void iris_init (void);
+static void iris_cleanup (void);
+static void iris_about (void);
+static void iris_playback_start (void);
+static void iris_playback_stop (void);
+static void iris_render_freq (gint16 data[][256]);
+
+static float dps = 0;
+
+gint beat_before = -1;
+
+extern iris_config newconfig;
+
+VisPlugin iris_vp = {
+  NULL,
+  NULL,
+  0,
+  NULL,				/* Description */
+  0,
+  1,
+  iris_init,			/* init */
+  iris_cleanup,			/* cleanup */
+  iris_about,			/* about */
+  iris_configure,		/* configure */
+  NULL,				/* disable_plugin */
+  iris_playback_start,		/* playback_start */
+  iris_playback_stop,		/* playback_stop */
+  NULL,				/* render_pcm */
+  iris_render_freq		/* render_freq */
+};
+
+
+void
+about_close_clicked (GtkWidget * w, GtkWidget ** window)
+{
+  gtk_widget_destroy (*window);
+  *window = NULL;
+}
+
+
+void
+about_closed (GtkWidget * w, GdkEvent * e, GtkWidget ** window)
+{
+  about_close_clicked (w, window);
+}
+
+
+static void
+iris_about (void)
+{
+  static GtkWidget *window_about = NULL;
+  GtkWidget *vbox, *button, *close, *label;
+
+  if (window_about)
+    return;
+
+  window_about = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window_about), "About IRIS plugin");
+  gtk_window_set_policy (GTK_WINDOW (window_about), FALSE, FALSE, FALSE);
+  gtk_window_set_position (GTK_WINDOW (window_about), GTK_WIN_POS_MOUSE);
+  vbox = gtk_vbox_new (FALSE, 4);
+  gtk_container_add (GTK_CONTAINER (window_about), vbox);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
+  gtk_widget_show (vbox);
+
+  label = gtk_label_new ("\n\
+Iris XMMS Plugin.\n\
+Copyright (C) 2001-2003, Cédric Delfosse.\n\
+\n\
+Email: <cdelfosse@free.fr> \n\
+Homepage: <http://cdelfosse.free.fr/xmms-iris/>\n\
+Development: <http://savannah.gnu.org/projects/iris/>\n\
+\n\
+Authors:\n\
+Cédric Delfosse\n\
+Marinus Schraal\n\
+Ron Lockwood-Childs\n\
+Ported to Audacious by Arthur Taylor\n\
+\n\
+This program is free software; you can redistribute it and/or modify\n\
+it under the terms of the GNU General Public License as published by\n\
+the Free Software Foundation; either version 2 of the License, or\n\
+(at your option) any later version.\n\
+\n\
+This program is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
+GNU General Public License for more details.\n\
+\n\
+You should have received a copy of the GNU General Public License\n\
+along with this program; if not, write to the Free Software\n\
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307\n\
+USA");
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 8);
+  gtk_widget_show (label);
+
+  button = gtk_hbutton_box_new ();
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 8);
+  gtk_widget_show (button);
+
+  close = gtk_button_new_with_label ("Close");
+  GTK_WIDGET_SET_FLAGS (close, GTK_CAN_DEFAULT);
+  gtk_window_set_default (GTK_WINDOW (window_about), close);
+  gtk_hbutton_box_set_layout_default (GTK_BUTTONBOX_END);
+  gtk_box_pack_end (GTK_BOX (button), close, FALSE, FALSE, 8);
+  gtk_widget_show (close);
+
+  gtk_signal_connect (GTK_OBJECT (close), "clicked",
+		      GTK_SIGNAL_FUNC (about_close_clicked), &window_about);
+  gtk_signal_connect (GTK_OBJECT (window_about), "delete-event",
+		      GTK_SIGNAL_FUNC (about_closed), &window_about);
+
+  gtk_widget_show (window_about);
+}
+
+
+/* Creates an empty cursor icon for when hovering over our window content */
+void
+hide_cursor ()
+{
+  Cursor no_ptr;
+  Pixmap bm_no;
+  Colormap cmap;
+  XColor black, dummy;
+
+  static unsigned char bm_no_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+  cmap = DefaultColormap (GLWin.dpy, DefaultScreen (GLWin.dpy));
+  XAllocNamedColor (GLWin.dpy, cmap, "black", &black, &dummy);
+  bm_no = XCreateBitmapFromData (GLWin.dpy, GLWin.window, bm_no_data, 8, 8);
+  no_ptr =
+    XCreatePixmapCursor (GLWin.dpy, bm_no, bm_no, &black, &black, 0, 0);
+  XDefineCursor (GLWin.dpy, GLWin.window, no_ptr);
+}
+
+
+/* this function creates our window and sets it up properly */
+static Window
+create_window (char *title)
+{
+  XVisualInfo *vi;
+  int i;
+
+  /* get a connection */
+  GLWin.dpy = XOpenDisplay (0);
+  if (GLWin.dpy == NULL)
+    g_log (NULL, G_LOG_LEVEL_CRITICAL,
+	   __FILE__ ": XOpenDisplay returns NULL");
+  GLWin.screen = DefaultScreen (GLWin.dpy);
+
+  /* get an appropriate visual */
+  vi = glXChooseVisual (GLWin.dpy, GLWin.screen, attrListDbl);
+  if (vi == NULL)
+    {
+      vi = glXChooseVisual (GLWin.dpy, GLWin.screen, attrListSgl);
+      GLWin.DoubleBuffered = 0;
+    }
+  else
+    GLWin.DoubleBuffered = 1;
+
+  if (vi == NULL)
+    g_log (NULL, G_LOG_LEVEL_CRITICAL,
+	   __FILE__ ": glXChooseVisual returns NULL");
+
+  glXQueryVersion (GLWin.dpy, &GLWin.glxMajorVersion, &GLWin.glxMinorVersion);
+  /* create a GLX context */
+  GLWin.ctx = glXCreateContext (GLWin.dpy, vi, 0, GL_TRUE);
+  if (GLWin.ctx == NULL)
+    g_log (NULL, G_LOG_LEVEL_CRITICAL,
+	   __FILE__ ": glXCreateContext can\'t create a rendering context");
+
+  /* create a color map */
+  GLWin.attr.colormap =
+    XCreateColormap (GLWin.dpy, RootWindow (GLWin.dpy, vi->screen),
+		     vi->visual, AllocNone);
+  GLWin.attr.border_pixel = 0;
+
+  if ((config.fullscreen && firsttime) || GLWin.fs)
+    {
+      int bestMode = 0;
+
+      GLWin.fs = True;
+      GLWin.fs_width = config.fs_width;
+      GLWin.fs_height = config.fs_height;
+      /* look for mode with requested resolution */
+      for (i = 0; i < GLWin.modeNum; i++)
+	{
+	  if ((GLWin.modes[i]->hdisplay == GLWin.fs_width)
+	      && (GLWin.modes[i]->vdisplay == GLWin.fs_height))
+	    {
+	      bestMode = i;
+	    }
+	}
+      XF86VidModeSwitchToMode (GLWin.dpy, GLWin.screen,
+			       GLWin.modes[bestMode]);
+      XF86VidModeSetViewPort (GLWin.dpy, GLWin.screen, 0, 0);
+      GLWin.fs_width = GLWin.modes[bestMode]->hdisplay;
+      GLWin.fs_height = GLWin.modes[bestMode]->vdisplay;
+
+      /* create a fullscreen window */
+      GLWin.attr.override_redirect = True;
+      GLWin.attr.event_mask =
+	ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
+      GLWin.window =
+	XCreateWindow (GLWin.dpy,
+		       RootWindow (GLWin.dpy, vi->screen), 0,
+		       0, GLWin.fs_width, GLWin.fs_height, 0, vi->depth,
+		       InputOutput, vi->visual,
+		       CWBorderPixel | CWColormap |
+		       CWEventMask | CWOverrideRedirect, &GLWin.attr);
+      XWarpPointer (GLWin.dpy, None, GLWin.window, 0, 0, 0, 0, 0, 0);
+      XMapRaised (GLWin.dpy, GLWin.window);
+      XGrabKeyboard (GLWin.dpy, GLWin.window, True, GrabModeAsync,
+		     GrabModeAsync, CurrentTime);
+      XGrabPointer (GLWin.dpy, GLWin.window, True, ButtonPressMask,
+		    GrabModeAsync, GrabModeAsync, GLWin.window,
+		    FALSE, CurrentTime);
+    }
+  else
+    {
+      XClassHint xclasshint={"xmms","visplugin"};
+      GLWin.window_width = config.window_width;
+      GLWin.window_height = config.window_height;
+      /* needed if those aren't set yet - ideally need a way to get the default values for these */
+      if (config.window_height == 0 || config.window_width == 0)
+	{
+	  config.window_width = 640;
+	  config.window_height = 480;
+	}
+
+      /* create a window in window mode */
+      GLWin.attr.event_mask =
+	ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
+      GLWin.window =
+	XCreateWindow (GLWin.dpy,
+		       RootWindow (GLWin.dpy, vi->screen), 0,
+		       0, GLWin.window_width, GLWin.window_height, 0,
+		       vi->depth, InputOutput, vi->visual,
+		       CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr);
+      XmbSetWMProperties(GLWin.dpy, GLWin.window, "iris","iris", NULL, 0, NULL, NULL, &xclasshint);
+
+      /* only set window title and handle wm_delete_events if in windowed mode */
+      wmDelete = XInternAtom (GLWin.dpy, "WM_DELETE_WINDOW", True);
+      XSetWMProtocols (GLWin.dpy, GLWin.window, &wmDelete, 1);
+      XSetStandardProperties (GLWin.dpy, GLWin.window, title,
+			      title, None, NULL, 0, NULL);
+      XMapRaised (GLWin.dpy, GLWin.window);
+    }
+  /* connect the glx-context to the window */
+  if (!glXMakeCurrent (GLWin.dpy, GLWin.window, GLWin.ctx))
+    g_log (NULL, G_LOG_LEVEL_CRITICAL,
+	   __FILE__ ": glXMakeCurrent returns an error");
+  if (glXIsDirect (GLWin.dpy, GLWin.ctx))
+    GLWin.DRI = 1;
+
+  hide_cursor ();
+
+  XFree (vi);
+  firsttime = FALSE;
+  return GLWin.window;
+}
+
+
+VisPlugin *
+get_vplugin_info (void)
+{
+  iris_vp.description = g_strdup_printf ("iris 3D analyzer %s", VERSION);
+  return &iris_vp;
+}
+
+
+static int
+detect_beat (gint32 loudness)
+{
+  static gint32 aged;		/* smoothed out oudness */
+  static gint32 lowest;		/* quietest point in current beat */
+  static int elapsed;		/* frames since last beat */
+  static int isquiet;		/* was previous frame quiet */
+  int detected_beat;
+
+  /* Incorporate the current loudness into history */
+  aged = (aged * 7 + loudness) >> 3;
+  elapsed++;
+
+  /* If silent, then clobber the beat */
+  if (aged < 2000 || elapsed > BEAT_MAX)
+    {
+      elapsed = 0;
+      lowest = aged;
+    }
+  else if (aged < lowest)
+    lowest = aged;
+
+  /* Beats are detected by looking for a sudden loudness after a lull.
+   * They are also limited to occur no more than once every 15 frames,
+   * so the beat flashes don't get too annoying.
+   */
+  detected_beat = (loudness * 4 > aged * 3 && aged * 2 > lowest * 3
+		   && elapsed > 15);
+  if (detected_beat)
+    lowest = aged, elapsed = 0;
+
+  /* Silence is computed from the aged loudness.  The quietref value is
+   * set to TRUE only at the start of silence, not throughout the silent
+   * period.  Also, there is some hysteresis so that silence followed
+   * by a slight noise and more silence won't count as two silent
+   * periods -- that sort of thing happens during many fade edits, so
+   * we have to account for it.
+   */
+  if (aged < (isquiet ? 1500 : 500))
+    /* Quiet now -- is this the start of quiet? */
+    isquiet = TRUE;
+  else
+    isquiet = FALSE;
+
+  /* return the result */
+  return detected_beat;
+}
+
+
+/* limit_rotation_speed keep rotation speed to at least dps_config
+   by second */
+static void
+limit_rotation_speed (gboolean init)
+{
+  static struct timeval tv_past;
+  struct timezone tz;
+  struct timeval tv_now;
+  float dps_config = 15;
+
+  if (!init)
+    {
+      long t;
+
+      gettimeofday (&tv_now, &tz);
+      t =
+	(tv_now.tv_sec - tv_past.tv_sec) * 10000000 + (tv_now.tv_usec -
+						       tv_past.tv_usec);
+      dps = y_speed * ((float) 1000000 / (float) t);
+      if (dps >= (float) dps_config)
+	y_speed -= 0.02;
+      else
+	y_speed += 0.02;
+
+      memcpy (&tv_past, &tv_now, sizeof (struct timeval));
+    }
+  else
+    gettimeofday (&tv_past, &tz);
+}
+
+
+/* limit_fps tries to keep the number of
+   frame per seconds to config.fps */
+static void
+limit_fps (gboolean init)
+{
+  static float fps = 0;
+  static struct timeval tv_past;
+  struct timezone tz;
+  struct timeval tv_now;
+  static int usec = 0;
+
+  if (init)
+    gettimeofday (&tv_past, &tz);
+  else
+    {
+      long t;
+
+      gettimeofday (&tv_now, &tz);
+      t =
+	(tv_now.tv_sec - tv_past.tv_sec) * 10000000 + (tv_now.tv_usec -
+						       tv_past.tv_usec);
+      fps = (float) 1000000 / (float) t;
+
+      if (fps >= (float) config.fps)
+	usec += 100;
+      else
+	{
+	  if (usec > 0)
+	    usec -= 100;
+	}
+      xmms_usleep (usec);
+      memcpy (&tv_past, &tv_now, sizeof (struct timeval));
+    }
+}
+
+static void
+init_general_draw_mode (int num)
+{
+  int transparency;
+  int wireframe;
+
+  if (theme[num].config->global->transparency != -1)
+    transparency = theme[num].config->global->transparency;
+  else
+    transparency = (int) (2.0 * rand () / (RAND_MAX + 1.0));
+
+  if (theme[num].config->global->wireframe != -1)
+    wireframe = theme[num].config->global->wireframe;
+  else
+    wireframe = (int) (2.0 * rand () / (RAND_MAX + 1.0));
+
+  if (transparency)
+    {
+      if (!glIsEnabled (GL_BLEND))
+	{
+	  glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+	  glEnable (GL_BLEND);
+	}
+      glDisable (GL_DEPTH_TEST);
+    }
+  else
+    {
+      if (glIsEnabled (GL_BLEND))
+	{
+	  glDisable (GL_BLEND);
+	}
+      glEnable (GL_DEPTH_TEST);
+    }
+
+  if (wireframe)
+    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+  else
+    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+  if (glIsEnabled(GL_TEXTURE_2D))
+    glDisable(GL_TEXTURE_2D);
+}
+
+
+static int
+compute_theme ()
+{
+  gfloat f_rand, f;
+  gint i;
+
+  for (i = 0, f_rand = 0.0; i < THEME_NUMBER; i++)
+    f_rand += theme[i].config->global->priority;
+  f_rand = f_rand * rand () / (RAND_MAX + 1.0);
+
+  i = 0;
+  f = 0;
+  while (i < THEME_NUMBER)
+    {
+      gfloat f_theme;
+      f_theme = theme[i].config->global->priority;
+      if (f_theme)
+	{
+	  f += f_theme;
+	  if (f_rand < f)
+	    break;
+	}
+      i++;
+    }
+
+  if (!f)
+    return (int) ((gfloat) THEME_NUMBER * rand () / (RAND_MAX + 1.0));
+  else
+    return i;
+}
+
+
+static int
+choose_theme (gboolean init)
+{
+  static long sec_btw_theme = 10 * 10000000;
+  static struct timeval tv_past;
+  struct timezone tz;
+  struct timeval tv_now;
+  static int th, th_tmp;
+
+  if (!init)
+    {
+      long t;
+
+      gettimeofday (&tv_now, &tz);
+      t =
+	(tv_now.tv_sec - tv_past.tv_sec) * 10000000 + (tv_now.tv_usec -
+						       tv_past.tv_usec);
+      if ((t > sec_btw_theme) || (beat && config.change_theme_on_beat))
+	{
+	  /* we come here if:
+	     - time for the theme is expired
+	     - a beat is detected and the change_theme_on_beat option is on
+	   */
+	  if (config.transition)
+	    {
+	      if (transition_frames == 0)
+		{
+		  th_tmp = compute_theme ();
+		  if (th != th_tmp)
+		    {
+		      transition_frames =
+			(unsigned int) config.fps * config.trans_duration /
+			10;
+		      max_transition_frames = transition_frames;
+		      memcpy (&tv_past, &tv_now, sizeof (struct timeval));
+		      init_theme_transition (transition_frames,
+					     max_transition_frames);
+		    }
+		}
+	    }
+	  else
+	    {
+	      th = compute_theme ();
+	      init_general_draw_mode (th);
+	      if (theme[th].init_draw_mode != NULL)
+		theme[th].init_draw_mode ();
+	      memcpy (&tv_past, &tv_now, sizeof (struct timeval));
+	      x_angle_wanted = theme[th].get_x_angle ();
+	      x_speed = copysign (0.08, x_angle_wanted - x_angle);
+	    }
+	}
+      /* change theme after half of the set frames have passed */
+      else if ((((int) max_transition_frames / 2) == transition_frames)
+	       && config.transition && (transition_frames != 0))
+	{
+	  th = th_tmp;
+	  init_general_draw_mode (th);
+	  if (theme[th].init_draw_mode != NULL)
+	    theme[th].init_draw_mode ();
+	  x_angle_wanted = theme[th].get_x_angle ();
+	  x_speed = copysign (0.08, x_angle_wanted - x_angle);
+	}
+    }
+  else
+    {
+      /* the first time choose_theme is called,
+         tv_past is initialized */
+      gettimeofday (&tv_past, &tz);
+      th = compute_theme ();
+      init_general_draw_mode (th);
+      if (theme[th].init_draw_mode != NULL)
+	theme[th].init_draw_mode ();
+    }
+
+  return (th);
+}
+
+
+static void
+draw_iris (void)
+{
+  int th;
+
+  limit_fps (FALSE);
+  th = choose_theme (FALSE);
+
+  if ((config.color_beat) && (beat_before > 0))
+    glClearColor (config.color_flash_red, config.color_flash_green,
+		  config.color_flash_blue, 1);
+  else
+    glClearColor (config.bgc_red, config.bgc_green, config.bgc_blue, 1);
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+  glTranslatef (0.0, -0.5, -7.0);
+  glRotatef (x_angle, 1.0, 0.0, 0.0);
+  glRotatef (y_angle, 0.0, 1.0, 0.0);
+  glRotatef (z_angle, 0.0, 0.0, 1.0);
+
+  if (transition_frames > 0 && config.transition)
+    {
+      theme_transition ();
+      transition_frames--;
+    }
+
+  theme[th].draw_one_frame (beat);
+
+  glEnd ();
+  glPopMatrix ();
+
+  glXSwapBuffers (GLWin.dpy, GLWin.window);
+}
+
+
+static gint
+disable_func (gpointer data)
+{
+  iris_vp.disable_plugin (&iris_vp);
+  return FALSE;
+}
+
+
+GLvoid
+init_gl (GLvoid)
+{
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glFrustum (-1, 1, -1.5, 1, 1.5, 12);
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+}
+
+
+GLvoid
+kill_gl_window (GLvoid)
+{
+  if (GLWin.ctx)
+    {
+      glXMakeCurrent (GLWin.dpy, None, NULL);
+      glXDestroyContext (GLWin.dpy, GLWin.ctx);
+      GLWin.ctx = NULL;
+    }
+  /* switch back to original desktop resolution if we were in fs */
+  if (GLWin.fs)
+    {
+      XF86VidModeSwitchToMode (GLWin.dpy, GLWin.screen, &GLWin.deskMode);
+      XF86VidModeSetViewPort (GLWin.dpy, GLWin.screen, 0, 0);
+    }
+}
+
+
+void *
+draw_thread_func (void *arg)
+{
+  Bool configured = FALSE;
+
+  g_log (NULL, G_LOG_LEVEL_DEBUG,  __FILE__ ": draw_thread_func: Starting.");
+
+  if ((GLWin.window = create_window ("Iris")) == 0)
+    {
+      g_log (NULL, G_LOG_LEVEL_CRITICAL,
+	     __FILE__ ": unable to create window");
+      pthread_exit (NULL);
+    }
+
+  init_gl ();
+  choose_theme (TRUE);
+
+
+#ifdef HAVE_SCHED_SETSCHEDULER
+  if (xmms_check_realtime_priority ())
+    {
+      struct sched_param sparam;
+      sparam.sched_priority = sched_get_priority_max (SCHED_OTHER);
+      pthread_setschedparam (pthread_self (), SCHED_OTHER, &sparam);
+    }
+#endif
+
+  while (going)			/* plugin enabled */
+    {
+      while (XPending (GLWin.dpy))
+	{
+	  XEvent event;
+	  KeySym keysym;
+	  char buf[16];
+
+	  XNextEvent (GLWin.dpy, &event);
+	  switch (event.type)
+	    {
+	    case Expose:
+	      if (event.xexpose.count != 0)
+		break;
+	      configured = TRUE;
+	      break;
+	    case ConfigureNotify:
+	      glViewport (0, 0, event.xconfigure.width,
+			  event.xconfigure.height);
+	      configured = TRUE;
+	      break;
+	    case KeyPress:
+
+	      XLookupString (&event.xkey, buf, 16, &keysym, NULL);
+	      switch (keysym)
+		{
+		case XK_Escape:
+
+		  /* Ugly hack to get the disable_plugin call in the main thread. */
+		  GDK_THREADS_ENTER ();
+		  gtk_idle_add (disable_func, NULL);
+		  GDK_THREADS_LEAVE ();
+		  break;
+		case XK_z:
+		  xmms_remote_playlist_prev (iris_vp.xmms_session);
+		  break;
+		case XK_x:
+		  xmms_remote_play (iris_vp.xmms_session);
+		  break;
+		case XK_c:
+		  xmms_remote_pause (iris_vp.xmms_session);
+		  break;
+		case XK_v:
+		  xmms_remote_stop (iris_vp.xmms_session);
+		  break;
+		case XK_b:
+		  xmms_remote_playlist_next (iris_vp.xmms_session);
+		  break;
+		case XK_Left:
+		  y_speed -= 0.1;
+		  if (y_speed < -3.0)
+		    y_speed = -3.0;
+		  break;
+		case XK_Right:
+		  y_speed += 0.1;
+		  if (y_speed > 3.0)
+		    y_speed = 3.0;
+		  break;
+		case XK_Return:
+		  x_speed = 0.0;
+		  y_speed = 0.3;
+		  z_speed = 0.0;
+		  x_angle = 70.0;
+		  y_angle = 45.0;
+		  z_angle = 0.0;
+		  break;
+		case XK_Tab:
+		  iris_configure ();
+		  break;
+		case XK_f:
+		  //iris_save_window_attributes ();
+		  kill_gl_window ();
+		  XCloseDisplay (GLWin.dpy);
+		  GLWin.fs = !GLWin.fs;
+		  create_window ("Iris");
+		  init_gl ();
+		  choose_theme (TRUE);
+		  break;
+		}
+
+	      break;
+	    case ClientMessage:
+	      if ((Atom) event.xclient.data.l[0] == wmDelete)
+		{
+		  GDK_THREADS_ENTER ();
+		  gtk_idle_add (disable_func, NULL);
+		  GDK_THREADS_LEAVE ();
+		}
+	      break;
+	    }
+	}
+      if (configured)
+	{
+	  limit_rotation_speed (FALSE);
+
+	  if ((x_angle > x_angle_wanted) && (x_speed > 0))
+	    x_angle = x_angle_wanted;
+	  else if ((x_angle < x_angle_wanted) && (x_speed < 0))
+	    x_angle = x_angle_wanted;
+
+	  x_angle += x_speed;
+	  if (x_angle > 85.0)
+	    x_angle = 85.0;
+	  else if (x_angle < 0.0)
+	    x_angle = 0.0;
+
+	  y_angle += y_speed;
+	  if (y_angle >= 360.0)
+	    y_angle -= 360.0;
+
+	  z_angle += z_speed;
+	  if (z_angle >= 360.0)
+	    z_angle -= 360.0;
+
+	  draw_iris ();
+	}
+    }
+
+  g_log (NULL, G_LOG_LEVEL_DEBUG,  __FILE__ ": draw_thread_func: Exiting.");
+  pthread_exit (NULL);
+}
+
+
+static void
+start_display (void)
+{
+  scale = 1.0 / log (256.0);
+
+  x_speed = 0.0;
+  y_speed = 0.3;
+  z_speed = 0.0;
+  x_angle = 45.0;
+  y_angle = 45.0;
+  z_angle = 0.0;
+
+  going = TRUE;
+  limit_fps (TRUE);
+  limit_rotation_speed (TRUE);
+  if (pthread_create (&draw_thread, NULL, draw_thread_func, NULL))
+    g_log (NULL, G_LOG_LEVEL_CRITICAL,  __FILE__ ": pthread_create: Can't create drawing thread.");
+   
+}
+
+
+static void
+stop_display (void)
+{
+  if (going)
+    {
+      going = FALSE;
+      pthread_join (draw_thread, NULL);
+    }
+
+  kill_gl_window ();
+
+  if (GLWin.window)
+    {
+      if (grabbed_pointer)
+	{
+	  XUngrabPointer (GLWin.dpy, CurrentTime);
+	  grabbed_pointer = FALSE;
+	}
+
+      XDestroyWindow (GLWin.dpy, GLWin.window);
+      GLWin.window = 0;
+    }
+  XCloseDisplay (GLWin.dpy);
+}
+
+
+static void
+iris_init (void)
+{
+  int i;
+  
+  initialized = TRUE;
+  iris_first_init ();
+  datas.loudness = 0;
+  /* if the config window is open, we don't want to trash the config the user
+   * has done */
+  if (!config_window)
+    iris_config_read ();
+  for (i = 0; i < THEME_NUMBER; i++)
+    if (theme[i].init != NULL)
+      theme[i].init ();
+  srand (666);
+  start_display ();
+}
+
+
+static void
+iris_cleanup (void)
+{
+  int i;
+
+  if(initialized)
+  {
+    stop_display ();
+    for (i = 0; i < THEME_NUMBER; i++)
+      if (theme[i].cleanup != NULL)
+	theme[i].cleanup ();
+  }
+}
+
+
+static void
+iris_playback_start (void)
+{
+}
+
+
+static void
+iris_playback_stop (void)
+{
+}
+
+
+static void
+iris_render_freq (gint16 data[2][256])
+{
+  GLfloat val;
+  static int angle = 0;
+  int i;
+
+  for (i = 0; i < num_bands; i++)
+    {
+      int y, c;
+      gint xscale[] =
+	{ 0, 1, 2, 3, 5, 7, 10, 14, 20, 28, 40, 54, 74, 101, 137, 156,
+	255
+      };
+      gint xscale8[] = { 0, 2, 5, 10, 20, 40, 74, 137, 255 };
+
+      if (num_bands == 16)
+	for (c = xscale[i], y = 0; c < xscale[i + 1]; c++)
+	  {
+	    if (data[0][c] > y)
+	      y = data[0][c];
+	  }
+      else
+	for (c = xscale8[i], y = 0; c < xscale8[i + 1]; c++)
+	  {
+	    if (data[0][c] > y)
+	      y = data[0][c];
+	  }
+
+      datas.loudness +=
+	(y / (xscale[i + 1] - xscale[i] + 1)) * (abs (i - NUM_BANDS / 2) +
+						 NUM_BANDS / 2) * (4 + i);
+
+      y >>= 7;
+      if (y > 0)
+	val = (log (y) * scale);
+      else
+	val = 0;
+      datas.data360[angle][i] = val;
+      datas.data1[i] = val;
+    }
+
+  datas.loudness /= (NUM_BANDS * 4);
+
+  beat = detect_beat (datas.loudness);
+  if (beat)
+    {
+      beat_before = config.flash_speed;
+      if (dps <= 90.0)
+	y_speed += 0.7;
+
+      if (config.bgc_random)
+	{
+	  config.bgc_red = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.bgc_green = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.bgc_blue = 1.0 * rand () / (RAND_MAX + 1.0);
+	}
+
+      if (config.color12_random)
+	{
+	  config.color1_red = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color1_green = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color1_blue = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color2_red = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color2_green = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color2_blue = 1.0 * rand () / (RAND_MAX + 1.0);
+	}
+
+      if (config.color_random)
+	{
+	  config.color_red = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color_green = 1.0 * rand () / (RAND_MAX + 1.0);
+	  config.color_blue = 1.0 * rand () / (RAND_MAX + 1.0);
+	}
+    }
+
+  if (beat_before > 0)
+    beat_before--;
+
+  angle++;
+  if (angle == 360)
+    angle = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/iris.h	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,198 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef IRIS_H
+
+#include <string.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <audacious/configdb.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/xf86vmode.h>
+
+typedef struct
+{
+
+  GLfloat bgc_red;
+  GLfloat bgc_green;
+  GLfloat bgc_blue;
+
+  GLfloat color_red;
+  GLfloat color_green;
+  GLfloat color_blue;
+
+  GLfloat color1_red;
+  GLfloat color1_green;
+  GLfloat color1_blue;
+
+  GLfloat color2_red;
+  GLfloat color2_green;
+  GLfloat color2_blue;
+
+  GLfloat color_flash_red;
+  GLfloat color_flash_green;
+  GLfloat color_flash_blue;
+
+  unsigned int color_mode;
+  unsigned int flash_speed;
+  unsigned int fps;
+
+  // in fullscreen, we are only interested in width and height
+  unsigned int fs_width;
+  unsigned int fs_height;
+
+  unsigned int window_width;
+  unsigned int window_height;
+
+  gboolean bgc_random;
+  gboolean color_random;
+  gboolean color12_random;
+  gboolean flash_random;
+  gboolean color_beat;
+  gboolean change_theme_on_beat;
+
+  gboolean fullscreen;
+  gboolean wireframe;
+
+  gboolean transition;
+  gfloat trans_duration;
+}
+iris_config;
+
+typedef struct
+{ 
+  gfloat priority; /* priority of the theme */
+  int transparency; /* transparency can be off (0), on (1) or random (-1) */
+  int wireframe; /* wireframe can be off (0), on (1) or random (-1) */
+}
+config_global; /* options implemented by all the themes */
+
+typedef struct
+{
+  config_global *global;
+  void *private; /* private config of the theme */
+}
+config_theme;
+
+typedef struct
+{
+  char *name; /* the name of the theme */
+  char *description; /* what the theme does */
+  char *author; /* who did the theme */
+  char *key; /* key used to get config items in ~/.xmms/config */
+  config_theme *config; /* where the theme config is */
+  config_theme *config_new; /* copy of the theme config used by the configuration widgets */
+  int config_private_size; /* size of the private theme config structure (we can't get it dynamically) */
+  void (*config_read) (ConfigDb * db, char *); /* read the private theme config and put it into the privateconfig */
+  void (*config_write) (ConfigDb * db, char *); /* write the private config into ~/.xmms/config */
+  void (*config_default) (void); /* put default values into private config */
+  void (*config_create) (GtkWidget *); /* create the Gtk widget (into a vbox) to configure the theme */
+  void (*init) (void); /* called once at iris init */
+  void (*cleanup) (void); /* called once at iris cleanup */
+  void (*init_draw_mode) (void); /* called once when iris switch to this theme */
+  GLfloat (*get_x_angle) (void); /* called once when iris switch to this theme to get a camera position to move */
+  void (*draw_one_frame) (gboolean beat); /* draw one frame of the theme */
+}
+iris_theme;
+
+#define NUM_BANDS 16
+typedef struct {
+  GLfloat data360[360][NUM_BANDS];
+  GLfloat data1[NUM_BANDS];
+  GLfloat loudness;
+}
+datas_t;
+
+typedef struct
+{
+  GLfloat x;
+  GLfloat z;
+}
+xz;
+
+/* stuff about our window grouped together */
+typedef struct
+{
+  // X stuff
+  Display *dpy;
+  int screen;
+  Window window;
+  GLXContext ctx;
+  XSetWindowAttributes attr;
+  Bool fs;
+  XF86VidModeModeInfo deskMode;
+  unsigned int window_x, window_y;
+  unsigned int window_width, window_height;
+  unsigned int fs_width, fs_height;
+
+  // rendering info
+  int glxMajorVersion;
+  int glxMinorVersion;
+  int vidModeMajorVersion;
+  int vidModeMinorVersion;
+  XF86VidModeModeInfo **modes;
+  int modeNum;
+  unsigned int depth;
+  gboolean DRI;
+  gboolean DoubleBuffered;
+  GList *glist;
+}
+GLWindow;
+
+/* config.c */
+extern GtkWidget *config_window;
+extern iris_config config;
+extern iris_config newconfig;
+extern GLWindow GLWin;
+extern datas_t datas;
+extern void iris_first_init (void);
+extern void iris_configure (void);
+extern void iris_config_read (void);
+extern void iris_config_write (iris_config *);
+extern void iris_set_default_prefs (void);
+extern void iris_save_window_attributes (void);
+extern GLvoid init_gl (GLvoid);
+
+/* color.c */
+extern void get_color (GLfloat *, GLfloat *, GLfloat *, GLfloat *);
+
+/* 3Dstuff.c */
+extern void bar_top_or_bottom (GLfloat height, xz * xz1, xz * xz2, xz * xz3,
+			       xz * xz4);
+extern void bar_side (GLfloat height, xz * xz1, xz * xz2);
+extern void bar_full (GLfloat height, xz * xz1, xz * xz2, xz * xz3, xz * xz4);
+
+/* theme.c */
+#define THEME_NUMBER 12
+extern void theme_register (void);
+extern iris_theme theme[THEME_NUMBER];
+extern void theme_config_init (void);
+extern void theme_config_global_default (int);
+extern void theme_config_global_read (ConfigDb *, char *, int);
+extern void theme_config_global_write (ConfigDb *, char *, int);
+extern void theme_config_apply(int num);
+extern void theme_config_global_widgets(GtkWidget *, int);
+extern void theme_about(GtkWidget *, int);
+
+/* transition.c */
+extern void init_theme_transition ();
+extern void theme_transition ();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/particle.h	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,169 @@
+/* GIMP RGBA C-Source image dump (particle.h) */
+
+static const struct
+{
+  guint width;
+  guint height;
+  guint bytes_per_pixel;	/* 3:RGB, 4:RGBA */
+  guint8 pixel_data[32 * 32 * 4 + 1];
+} particle_image =
+{
+32, 32, 4,
+    "\0\0\0\377\3\3\3\377\2\2\2\377\5\5\5\377\7\7\7\377\6\6\6\377\6\6\6\377\12"
+    "\12\12\377\13\13\13\377\11\11\11\377\12\12\12\377\12\12\12\377\14\14\14\377"
+    "\14\14\14\377\14\14\14\377\16\16\16\377\15\15\15\377\14\14\14\377\12\12\12"
+    "\377\13\13\13\377\13\13\13\377\11\11\11\377\12\12\12\377\12\12\12\377\10"
+    "\10\10\377\7\7\7\377\6\6\6\377\6\6\6\377\5\5\5\377\2\2\2\377\0\0\0\377\0"
+    "\0\0\377\4\4\4\377\3\3\3\377\4\4\4\377\7\7\7\377\6\6\6\377\10\10\10\377\11"
+    "\11\11\377\11\11\11\377\14\14\14\377\14\14\14\377\15\15\15\377\16\16\16\377"
+    "\20\20\20\377\21\21\21\377\20\20\20\377\22\22\22\377\20\20\20\377\21\21\21"
+    "\377\17\17\17\377\20\20\20\377\17\17\17\377\13\13\13\377\13\13\13\377\13"
+    "\13\13\377\14\14\14\377\11\11\11\377\6\6\6\377\6\6\6\377\6\6\6\377\4\4\4"
+    "\377\1\1\1\377\0\0\0\377\5\5\5\377\4\4\4\377\6\6\6\377\6\6\6\377\12\12\12"
+    "\377\12\12\12\377\11\11\11\377\14\14\14\377\15\15\15\377\20\20\20\377\20"
+    "\20\20\377\24\24\24\377\24\24\24\377\23\23\23\377\23\23\23\377\26\26\26\377"
+    "\25\25\25\377\23\23\23\377\21\21\21\377\24\24\24\377\22\22\22\377\17\17\17"
+    "\377\17\17\17\377\15\15\15\377\15\15\15\377\11\11\11\377\11\11\11\377\7\7"
+    "\7\377\7\7\7\377\6\6\6\377\3\3\3\377\3\3\3\377\6\6\6\377\6\6\6\377\6\6\6"
+    "\377\12\12\12\377\13\13\13\377\13\13\13\377\13\13\13\377\17\17\17\377\22"
+    "\22\22\377\24\24\24\377\22\22\22\377\30\30\30\377\30\30\30\377\31\31\31\377"
+    "\31\31\31\377\33\33\33\377\31\31\31\377\30\30\30\377\30\30\30\377\30\30\30"
+    "\377\25\25\25\377\25\25\25\377\23\23\23\377\22\22\22\377\17\17\17\377\13"
+    "\13\13\377\12\12\12\377\11\11\11\377\7\7\7\377\6\6\6\377\5\5\5\377\4\4\4"
+    "\377\7\7\7\377\6\6\6\377\12\12\12\377\11\11\11\377\14\14\14\377\15\15\15"
+    "\377\20\20\20\377\22\22\22\377\25\25\25\377\30\30\30\377\32\32\32\377\35"
+    "\35\35\377\34\34\34\377\34\34\34\377\36\36\36\377\40\40\40\377\36\36\36\377"
+    "\34\34\34\377\34\34\34\377\34\34\34\377\32\32\32\377\31\31\31\377\26\26\26"
+    "\377\25\25\25\377\22\22\22\377\16\16\16\377\12\12\12\377\12\12\12\377\12"
+    "\12\12\377\10\10\10\377\6\6\6\377\4\4\4\377\10\10\10\377\11\11\11\377\12"
+    "\12\12\377\13\13\13\377\16\16\16\377\21\21\21\377\22\22\22\377\25\25\25\377"
+    "\30\30\30\377\34\34\34\377\37\37\37\377!!!\377\"\"\"\377###\377###\377&&"
+    "&\377&&&\377$$$\377###\377\40\40\40\377!!!\377\35\35\35\377\34\34\34\377"
+    "\25\25\25\377\24\24\24\377\21\21\21\377\15\15\15\377\14\14\14\377\14\14\14"
+    "\377\12\12\12\377\6\6\6\377\6\6\6\377\10\10\10\377\12\12\12\377\12\12\12"
+    "\377\16\16\16\377\22\22\22\377\24\24\24\377\26\26\26\377\30\30\30\377\34"
+    "\34\34\377\37\37\37\377###\377&&&\377,,,\377+++\377,,,\377---\377---\377"
+    ",,,\377+++\377&&&\377)))\377$$$\377\34\34\34\377\34\34\34\377\27\27\27\377"
+    "\24\24\24\377\23\23\23\377\17\17\17\377\15\15\15\377\12\12\12\377\7\7\7\377"
+    "\6\6\6\377\12\12\12\377\12\12\12\377\16\16\16\377\21\21\21\377\22\22\22\377"
+    "\27\27\27\377\31\31\31\377\36\36\36\377!!!\377%%%\377(((\377111\377222\377"
+    "555\377;;;\377<<<\377999\377888\377333\377111\377---\377'''\377\"\"\"\377"
+    "\34\34\34\377\36\36\36\377\32\32\32\377\25\25\25\377\21\21\21\377\15\15\15"
+    "\377\11\11\11\377\12\12\12\377\7\7\7\377\13\13\13\377\14\14\14\377\17\17"
+    "\17\377\21\21\21\377\31\31\31\377\31\31\31\377\35\35\35\377!!!\377'''\377"
+    "+++\377111\377===\377EEE\377HHH\377MMM\377MMM\377JJJ\377III\377AAA\377AA"
+    "A\377888\377,,,\377%%%\377$$$\377\"\"\"\377\34\34\34\377\24\24\24\377\22"
+    "\22\22\377\17\17\17\377\13\13\13\377\12\12\12\377\11\11\11\377\13\13\13\377"
+    "\14\14\14\377\20\20\20\377\23\23\23\377\27\27\27\377\35\35\35\377$$$\377"
+    "(((\377...\377666\377===\377HHH\377WWW\377YYY\377]]]\377aaa\377\\\\\\\377"
+    "\\\\\\\377UUU\377OOO\377???\377444\377---\377+++\377\40\40\40\377\32\32\32"
+    "\377\27\27\27\377\23\23\23\377\22\22\22\377\15\15\15\377\11\11\11\377\13"
+    "\13\13\377\12\12\12\377\15\15\15\377\21\21\21\377\25\25\25\377\30\30\30\377"
+    "\37\37\37\377$$$\377...\377999\377???\377NNN\377XXX\377hhh\377rrr\377www"
+    "\377|||\377xxx\377ppp\377kkk\377\\\\\\\377JJJ\377FFF\377999\377***\377$$"
+    "$\377\36\36\36\377\30\30\30\377\25\25\25\377\24\24\24\377\20\20\20\377\14"
+    "\14\14\377\12\12\12\377\15\15\15\377\17\17\17\377\22\22\22\377\27\27\27\377"
+    "\34\34\34\377\40\40\40\377%%%\377...\377<<<\377MMM\377[[[\377lll\377~~~\377"
+    "\227\227\227\377\230\230\230\377\234\234\234\377\233\233\233\377\226\226"
+    "\226\377\205\205\205\377iii\377bbb\377PPP\377999\377---\377(((\377!!!\377"
+    "\35\35\35\377\32\32\32\377\25\25\25\377\21\21\21\377\13\13\13\377\12\12\12"
+    "\377\15\15\15\377\21\21\21\377\23\23\23\377\31\31\31\377\37\37\37\377!!!"
+    "\377(((\377444\377@@@\377QQQ\377ggg\377\200\200\200\377\231\231\231\377\254"
+    "\254\254\377\275\275\275\377\310\310\310\377\304\304\304\377\264\264\264"
+    "\377\227\227\227\377\212\212\212\377fff\377QQQ\377BBB\377:::\377///\377&"
+    "&&\377\36\36\36\377\32\32\32\377\26\26\26\377\21\21\21\377\14\14\14\377\12"
+    "\12\12\377\17\17\17\377\22\22\22\377\24\24\24\377\31\31\31\377\40\40\40\377"
+    "&&&\377---\377:::\377HHH\377XXX\377kkk\377\220\220\220\377\252\252\252\377"
+    "\324\324\324\377\363\363\363\377\370\370\370\377\366\366\366\377\335\335"
+    "\335\377\263\263\263\377\221\221\221\377www\377bbb\377PPP\377>>>\377000\377"
+    "&&&\377\37\37\37\377\32\32\32\377\26\26\26\377\23\23\23\377\15\15\15\377"
+    "\11\11\11\377\16\16\16\377\21\21\21\377\27\27\27\377\33\33\33\377\"\"\"\377"
+    "(((\377///\377<<<\377NNN\377bbb\377zzz\377\231\231\231\377\275\275\275\377"
+    "\361\361\361\377\375\375\375\377\376\376\376\377\376\376\376\377\370\370"
+    "\370\377\316\316\316\377\240\240\240\377\205\205\205\377bbb\377LLL\377<<"
+    "<\377...\377&&&\377\40\40\40\377\33\33\33\377\26\26\26\377\22\22\22\377\15"
+    "\15\15\377\12\12\12\377\16\16\16\377\22\22\22\377\24\24\24\377\32\32\32\377"
+    "\40\40\40\377$$$\377,,,\377:::\377LLL\377```\377|||\377\231\231\231\377\310"
+    "\310\310\377\372\372\372\377\375\375\375\377\376\376\376\377\376\376\376"
+    "\377\375\375\375\377\332\332\332\377\241\241\241\377\207\207\207\377fff\377"
+    "RRR\377@@@\377333\377+++\377\"\"\"\377\35\35\35\377\30\30\30\377\24\24\24"
+    "\377\17\17\17\377\14\14\14\377\16\16\16\377\22\22\22\377\25\25\25\377\30"
+    "\30\30\377\40\40\40\377$$$\377,,,\377;;;\377NNN\377eee\377\206\206\206\377"
+    "\246\246\246\377\327\327\327\377\374\374\374\377\375\375\375\377\376\376"
+    "\376\377\376\376\376\377\374\374\374\377\331\331\331\377\243\243\243\377"
+    "\210\210\210\377bbb\377OOO\377>>>\377...\377&&&\377\40\40\40\377\33\33\33"
+    "\377\27\27\27\377\22\22\22\377\15\15\15\377\12\12\12\377\16\16\16\377\22"
+    "\22\22\377\23\23\23\377\32\32\32\377\40\40\40\377'''\377000\377???\377UU"
+    "U\377hhh\377\200\200\200\377\237\237\237\377\270\270\270\377\344\344\344"
+    "\377\372\372\372\377\375\375\375\377\376\376\376\377\354\354\354\377\275"
+    "\275\275\377\227\227\227\377\200\200\200\377eee\377QQQ\377>>>\377...\377"
+    "%%%\377\40\40\40\377\33\33\33\377\26\26\26\377\22\22\22\377\15\15\15\377"
+    "\11\11\11\377\17\17\17\377\22\22\22\377\25\25\25\377\31\31\31\377\"\"\"\377"
+    "***\377333\377===\377JJJ\377^^^\377ooo\377\211\211\211\377\235\235\235\377"
+    "\271\271\271\377\327\327\327\377\342\342\342\377\335\335\335\377\302\302"
+    "\302\377\240\240\240\377\216\216\216\377kkk\377XXX\377CCC\377999\377///\377"
+    "&&&\377\"\"\"\377\33\33\33\377\26\26\26\377\22\22\22\377\14\14\14\377\12"
+    "\12\12\377\15\15\15\377\22\22\22\377\31\31\31\377\35\35\35\377\37\37\37\377"
+    "$$$\377,,,\377777\377AAA\377QQQ\377[[[\377ppp\377\212\212\212\377\231\231"
+    "\231\377\242\242\242\377\253\253\253\377\251\251\251\377\236\236\236\377"
+    "\215\215\215\377uuu\377bbb\377OOO\377<<<\377111\377)))\377\"\"\"\377\34\34"
+    "\34\377\32\32\32\377\27\27\27\377\21\21\21\377\16\16\16\377\12\12\12\377"
+    "\17\17\17\377\21\21\21\377\20\20\20\377\27\27\27\377\37\37\37\377$$$\377"
+    "&&&\377,,,\377888\377BBB\377RRR\377___\377kkk\377~~~\377\207\207\207\377"
+    "\220\220\220\377\220\220\220\377\203\203\203\377qqq\377___\377VVV\377FFF"
+    "\377777\377,,,\377%%%\377!!!\377\31\31\31\377\25\25\25\377\22\22\22\377\17"
+    "\17\17\377\14\14\14\377\11\11\11\377\12\12\12\377\16\16\16\377\22\22\22\377"
+    "\27\27\27\377\33\33\33\377\35\35\35\377\"\"\"\377(((\377///\377999\377EE"
+    "E\377LLL\377^^^\377ddd\377eee\377kkk\377lll\377ddd\377aaa\377OOO\377CCC\377"
+    "===\377000\377)))\377$$$\377\35\35\35\377\30\30\30\377\25\25\25\377\22\22"
+    "\22\377\16\16\16\377\12\12\12\377\13\13\13\377\13\13\13\377\15\15\15\377"
+    "\20\20\20\377\21\21\21\377\31\31\31\377\33\33\33\377\35\35\35\377$$$\377"
+    ")))\377111\377666\377@@@\377JJJ\377NNN\377PPP\377SSS\377XXX\377PPP\377JJ"
+    "J\377EEE\377777\377,,,\377+++\377%%%\377\40\40\40\377\32\32\32\377\26\26"
+    "\26\377\21\21\21\377\21\21\21\377\14\14\14\377\11\11\11\377\12\12\12\377"
+    "\13\13\13\377\11\11\11\377\14\14\14\377\21\21\21\377\23\23\23\377\27\27\27"
+    "\377\33\33\33\377\37\37\37\377&&&\377(((\377***\377444\377999\377<<<\377"
+    "===\377CCC\377EEE\377???\377999\377:::\377...\377(((\377!!!\377!!!\377\35"
+    "\35\35\377\31\31\31\377\24\24\24\377\21\21\21\377\16\16\16\377\12\12\12\377"
+    "\11\11\11\377\10\10\10\377\10\10\10\377\11\11\11\377\13\13\13\377\16\16\16"
+    "\377\22\22\22\377\25\25\25\377\30\30\30\377\33\33\33\377\"\"\"\377!!!\377"
+    "%%%\377***\377---\377000\377///\377333\377222\377444\377---\377,,,\377**"
+    "*\377\"\"\"\377\37\37\37\377\32\32\32\377\33\33\33\377\27\27\27\377\21\21"
+    "\21\377\17\17\17\377\16\16\16\377\12\12\12\377\11\11\11\377\6\6\6\377\10"
+    "\10\10\377\12\12\12\377\11\11\11\377\15\15\15\377\20\20\20\377\22\22\22\377"
+    "\23\23\23\377\30\30\30\377\32\32\32\377\35\35\35\377\40\40\40\377!!!\377"
+    "%%%\377(((\377&&&\377)))\377(((\377+++\377$$$\377!!!\377###\377\36\36\36"
+    "\377\30\30\30\377\30\30\30\377\24\24\24\377\22\22\22\377\20\20\20\377\15"
+    "\15\15\377\11\11\11\377\12\12\12\377\6\6\6\377\6\6\6\377\7\7\7\377\7\7\7"
+    "\377\11\11\11\377\12\12\12\377\16\16\16\377\17\17\17\377\22\22\22\377\23"
+    "\23\23\377\26\26\26\377\31\31\31\377\33\33\33\377\34\34\34\377!!!\377\40"
+    "\40\40\377\"\"\"\377\"\"\"\377\"\"\"\377&&&\377\36\36\36\377\35\35\35\377"
+    "\35\35\35\377\34\34\34\377\26\26\26\377\24\24\24\377\23\23\23\377\20\20\20"
+    "\377\15\15\15\377\14\14\14\377\13\13\13\377\7\7\7\377\5\5\5\377\6\6\6\377"
+    "\7\7\7\377\6\6\6\377\11\11\11\377\12\12\12\377\11\11\11\377\15\15\15\377"
+    "\16\16\16\377\21\21\21\377\22\22\22\377\26\26\26\377\26\26\26\377\30\30\30"
+    "\377\33\33\33\377\32\32\32\377\34\34\34\377\33\33\33\377\32\32\32\377\37"
+    "\37\37\377\31\31\31\377\31\31\31\377\27\27\27\377\30\30\30\377\21\21\21\377"
+    "\22\22\22\377\17\17\17\377\14\14\14\377\11\11\11\377\11\11\11\377\12\12\12"
+    "\377\6\6\6\377\6\6\6\377\4\4\4\377\6\6\6\377\6\6\6\377\5\5\5\377\7\7\7\377"
+    "\13\13\13\377\11\11\11\377\12\12\12\377\16\16\16\377\21\21\21\377\21\21\21"
+    "\377\20\20\20\377\22\22\22\377\30\30\30\377\26\26\26\377\27\27\27\377\30"
+    "\30\30\377\27\27\27\377\30\30\30\377\26\26\26\377\23\23\23\377\22\22\22\377"
+    "\20\20\20\377\20\20\20\377\16\16\16\377\14\14\14\377\11\11\11\377\11\11\11"
+    "\377\10\10\10\377\6\6\6\377\6\6\6\377\4\4\4\377\3\3\3\377\4\4\4\377\4\4\4"
+    "\377\4\4\4\377\7\7\7\377\10\10\10\377\12\12\12\377\10\10\10\377\11\11\11"
+    "\377\15\15\15\377\16\16\16\377\16\16\16\377\20\20\20\377\23\23\23\377\21"
+    "\21\21\377\23\23\23\377\22\22\22\377\22\22\22\377\21\21\21\377\22\22\22\377"
+    "\22\22\22\377\20\20\20\377\16\16\16\377\15\15\15\377\12\12\12\377\11\11\11"
+    "\377\12\12\12\377\7\7\7\377\6\6\6\377\7\7\7\377\5\5\5\377\4\4\4\377\1\1\1"
+    "\377\1\1\1\377\3\3\3\377\3\3\3\377\6\6\6\377\7\7\7\377\6\6\6\377\10\10\10"
+    "\377\12\12\12\377\12\12\12\377\11\11\11\377\13\13\13\377\16\16\16\377\16"
+    "\16\16\377\16\16\16\377\17\17\17\377\16\16\16\377\16\16\16\377\17\17\17\377"
+    "\17\17\17\377\15\15\15\377\14\14\14\377\12\12\12\377\11\11\11\377\12\12\12"
+    "\377\12\12\12\377\7\7\7\377\6\6\6\377\6\6\6\377\6\6\6\377\3\3\3\377\1\1\1"
+    "\377\1\1\1\377\0\0\0\377\0\0\0\377\2\2\2\377\4\4\4\377\7\7\7\377\6\6\6\377"
+    "\6\6\6\377\7\7\7\377\13\13\13\377\13\13\13\377\10\10\10\377\11\11\11\377"
+    "\11\11\11\377\11\11\11\377\15\15\15\377\13\13\13\377\14\14\14\377\11\11\11"
+    "\377\13\13\13\377\11\11\11\377\12\12\12\377\13\13\13\377\11\11\11\377\11"
+    "\11\11\377\6\6\6\377\7\7\7\377\4\4\4\377\5\5\5\377\3\3\3\377\1\1\1\377\0"
+    "\0\0\377\0\0\0\377",};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,308 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include "iris.h"
+
+/* declaration of all the themes start here */
+extern iris_theme theme_original;
+extern iris_theme theme_spectrum;
+extern iris_theme theme_spectrotoy;
+extern iris_theme theme_squarefield;
+extern iris_theme theme_waves;
+extern iris_theme theme_pyramid;
+extern iris_theme theme_knot;
+extern iris_theme theme_pinwheel;
+extern iris_theme theme_pipes;
+extern iris_theme theme_float;
+extern iris_theme theme_fountain;
+extern iris_theme theme_flash;
+
+/* this is the array where all the themes are */
+iris_theme theme[THEME_NUMBER];
+
+
+/* this initialize the theme registry */
+void
+theme_register (void)
+{
+  theme[0] = theme_original;
+  theme[1] = theme_spectrum;
+  theme[2] = theme_spectrotoy;
+  theme[3] = theme_squarefield;
+  theme[4] = theme_waves;
+  theme[5] = theme_pyramid;
+  theme[6] = theme_knot;
+  theme[7] = theme_pinwheel;
+  theme[8] = theme_pipes;
+  theme[9] = theme_float;
+  theme[10] = theme_fountain;
+  theme[11] = theme_flash;}
+
+
+/* allocate memory for the config struct of the themes */
+void
+theme_config_init (void)
+{
+  int i;
+
+  for (i = 0; i < THEME_NUMBER; i++)
+    {
+      theme[i].config->global = g_malloc (sizeof (config_global));
+      theme[i].config_new->global = g_malloc (sizeof (config_global));
+    }
+}
+
+
+/* set the default global config of a theme */
+void
+theme_config_global_default (int num)
+{
+  theme[num].config->global->priority = 1.0;	/* priority set to max */
+  theme[num].config->global->transparency = -1;	/* transparency random */
+  theme[num].config->global->wireframe = 0;	/* wireframe off */
+}
+
+
+/* read the global config of a theme
+   (priority, transparency, wireframe) */
+void
+theme_config_global_read (ConfigDb * db, char *section_name, int num)
+{
+  char *string;
+
+  string = g_strconcat (theme[num].key, "_", "priority", NULL);
+  bmp_cfg_db_get_float (db, section_name, string, &theme[num].config->global->priority);
+  g_free (string);
+
+  string = g_strconcat (theme[num].key, "_", "transparency", NULL);
+  bmp_cfg_db_get_int (db, section_name, string, &theme[num].config->global->transparency);
+  g_free (string);
+
+  string = g_strconcat (theme[num].key, "_", "wireframe", NULL);
+  bmp_cfg_db_get_int (db, section_name, string, &theme[num].config->global->wireframe);
+  g_free (string);
+}
+
+
+/* write the global config of a theme */
+void
+theme_config_global_write (ConfigDb * db, char *section_name, int num)
+{
+  char *string;
+
+  string = g_strconcat (theme[num].key, "_", "priority", NULL);
+  bmp_cfg_db_set_float (db, section_name, string, theme[num].config->global->priority);
+  g_free (string);
+
+  string = g_strconcat (theme[num].key, "_", "transparency", NULL);
+  bmp_cfg_db_set_int (db, section_name, string, theme[num].config->global->transparency);
+  g_free (string);
+
+  string = g_strconcat (theme[num].key, "_", "wireframe", NULL);
+  bmp_cfg_db_set_int (db, section_name, string, theme[num].config->global->wireframe);
+  g_free (string);
+}
+
+
+/* the following 6 functions are callbacks for the theme_config_global_widgets function */
+void
+on_rb_transparency_random (GtkWidget * widget, gpointer data)
+{
+  theme[(int) data].config_new->global->transparency = -1;
+}
+
+
+void
+on_rb_transparency_on (GtkWidget * widget, gpointer data)
+{
+  theme[(int) data].config_new->global->transparency = 1;
+}
+
+
+void
+on_rb_transparency_off (GtkWidget * widget, gpointer data)
+{
+  theme[(int) data].config_new->global->transparency = 0;
+}
+
+
+void
+on_rb_wireframe_random (GtkWidget * widget, gpointer data)
+{
+  theme[(int) data].config_new->global->wireframe = -1;
+}
+
+
+void
+on_rb_wireframe_on (GtkWidget * widget, gpointer data)
+{
+  theme[(int) data].config_new->global->wireframe = 1;
+}
+
+
+void
+on_rb_wireframe_off (GtkWidget * widget, gpointer data)
+{
+  theme[(int) data].config_new->global->wireframe = 0;
+}
+
+
+void
+theme_config_apply (int num)
+{
+  memcpy (theme[num].config->private, theme[num].config_new->private,
+	  theme[num].config_private_size);
+}
+
+
+/* create the config widgets of all the themes */
+void
+theme_config_global_widgets (GtkWidget * vbox, int num)
+{
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkWidget *radio_button_on1;
+  GtkWidget *radio_button_off1;
+  GtkWidget *radio_button_random1;
+  GSList *group;
+
+  memcpy (theme[num].config_new->global, theme[num].config->global,
+	  sizeof (config_global));
+
+  /* transparency mode */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Transparency");
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+  radio_button_random1 = gtk_radio_button_new_with_label (NULL, "Random");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_random1, FALSE, FALSE, 4);
+
+  group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button_random1));
+  radio_button_on1 = gtk_radio_button_new_with_label (group, "On");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_on1, FALSE, FALSE, 4);
+
+  group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button_on1));
+  radio_button_off1 = gtk_radio_button_new_with_label (group, "Off");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_off1, FALSE, FALSE, 4);
+
+  switch (theme[num].config->global->transparency)
+    {
+    case -1:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_random1), TRUE);
+	break;
+      }
+    case 0:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_off1), TRUE);
+	break;
+      }
+    case 1:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_on1), TRUE);
+      }
+    }
+
+  gtk_signal_connect (GTK_OBJECT (radio_button_random1), "toggled",
+		      GTK_SIGNAL_FUNC (on_rb_transparency_random),
+		      (gpointer) num);
+  gtk_signal_connect (GTK_OBJECT (radio_button_off1), "toggled",
+		      GTK_SIGNAL_FUNC (on_rb_transparency_off),
+		      (gpointer) num);
+  gtk_signal_connect (GTK_OBJECT (radio_button_on1), "toggled",
+		      GTK_SIGNAL_FUNC (on_rb_transparency_on),
+		      (gpointer) num);
+
+  /* wireframe mode */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Wireframe");
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+  radio_button_random1 = gtk_radio_button_new_with_label (NULL, "Random");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_random1, FALSE, FALSE, 4);
+
+  group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button_random1));
+  radio_button_on1 = gtk_radio_button_new_with_label (group, "On");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_on1, FALSE, FALSE, 4);
+
+  group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button_on1));
+  radio_button_off1 = gtk_radio_button_new_with_label (group, "Off");
+  gtk_box_pack_start (GTK_BOX (hbox), radio_button_off1, FALSE, FALSE, 4);
+
+  switch (theme[num].config->global->wireframe)
+    {
+    case -1:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_random1), TRUE);
+	break;
+      }
+    case 0:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_off1), TRUE);
+	break;
+      }
+    case 1:
+      {
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+				      (radio_button_on1), TRUE);
+      }
+    }
+
+  gtk_signal_connect (GTK_OBJECT (radio_button_random1), "toggled",
+		      GTK_SIGNAL_FUNC (on_rb_wireframe_random),
+		      (gpointer) num);
+  gtk_signal_connect (GTK_OBJECT (radio_button_off1), "toggled",
+		      GTK_SIGNAL_FUNC (on_rb_wireframe_off), (gpointer) num);
+  gtk_signal_connect (GTK_OBJECT (radio_button_on1), "toggled",
+		      GTK_SIGNAL_FUNC (on_rb_wireframe_on), (gpointer) num);
+
+}
+
+
+/* create the theme about vbox */
+void
+theme_about (GtkWidget * vbox_about, int num)
+{
+  GtkWidget *label;
+  GtkWidget *vbox;
+
+  vbox = gtk_vbox_new (FALSE, 4);
+  label = gtk_label_new (g_strconcat ("Theme name: ", theme[num].name, NULL));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+
+  label =
+    gtk_label_new (g_strconcat ("Theme author: ", theme[num].author, NULL));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+
+  label =
+    gtk_label_new (g_strconcat
+		   ("Theme description: ", theme[num].description, NULL));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+
+  gtk_box_pack_start (GTK_BOX (vbox_about), vbox, FALSE, FALSE, 4);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_flash.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,486 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2004 Marc Pompl (marc.pompl@lynorics.de)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+#include "particle.h"
+
+static GLuint texture[1];     /* Storage For Our Particle Texture                   */
+
+static gboolean flash_already_initialized = FALSE;
+
+static float flash_timer = 0; /* timer for flash */
+
+static struct
+{
+  gboolean flash_on_beat;
+  int flash_timer;
+  GLfloat speed;
+  GLfloat r1, r2, r3;
+  GLfloat m,n,o;
+  GLfloat f,g,h;
+  GLfloat t;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  (config_global *) NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  (config_global *) NULL,
+  &conf_private_new
+};
+
+static char flash_flash_on_beat[] = "flashlight_flash_on_beat";
+static char flash_flash_timer[] = "flashlight_flash_timer";
+static char flash_speed[] = "flashlight_speed";
+
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+static void init_draw_mode (void);
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+iris_theme theme_flash = {
+  "Flash light",
+  "flash lights moving by a lissajou figure\n",
+  "Marc Pompl (marc.pompl@lynorics.de)",
+  "flashlight",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  init_draw_mode,
+  get_x_angle,
+  draw_one_frame
+};
+
+/* Create our particle structure */
+typedef struct
+{
+    GLint   active; /* Active (Yes/No) */
+    GLfloat life;   /* Particle Life   */
+    GLfloat fade;   /* Fade Speed      */
+
+    GLfloat r;      /* Red Value       */
+    GLfloat g;      /* Green Value     */
+    GLfloat b;      /* Blue Value      */
+
+    GLfloat fr;      /* Red Flash Value       */
+    GLfloat fg;      /* Green Flash Value     */
+    GLfloat fb;      /* Blue Flash Value      */
+
+    GLfloat x;      /* X Position      */
+    GLfloat y;      /* Y Position      */
+    GLfloat z;      /* Z Position      */
+
+    GLfloat xi;     /* X Direction     */
+    GLfloat yi;     /* Y Direction     */
+    GLfloat zi;     /* Z Direction     */
+
+    GLfloat xg;     /* X Gravity       */
+    GLfloat yg;     /* Y Gravity       */
+    GLfloat zg;     /* Z Gravity       */
+} particle;
+
+/* Rainbow of colors */
+static GLfloat flash_colors[16][3] =
+{
+  { 1.0f,  0.5f,  0.5f},
+	{ 1.0f,  0.75f, 0.5f},
+	{ 1.0f,  1.0f,  0.5f},
+
+	{ 0.75f, 1.0f,  0.5f},
+
+	{ 0.5f,  1.0f,  0.5f},
+	{ 0.5f,  1.0f,  0.75f},
+	{ 0.5f,  1.0f,  1.0f},
+
+	{ 0.5f,  0.75f, 1.0f},
+  { 0.5f,  0.5f,  1.0f},
+	{ 0.75f, 0.5f,  1.0f},
+
+	{ 1.0f,  0.5f,  1.0f},
+	{ 1.0f,  0.5f,  0.75f},
+	{ 0.75f, 0.5f,  0.75f},
+
+	{ 0.5f,  0.5f,  0.5f},
+	{ 0.75f, 0.75f, 0.75f},
+	{ 1.0f,  1.0f,  1.0f},
+};
+
+/* Our beloved array of particles */
+static particle particles[NUM_BANDS];
+
+void FlashColor( int num )
+{
+	GLfloat dr;
+	GLfloat dg;
+	GLfloat db;
+	dr = 1-particles[num].r;
+	dg = 1-particles[num].g;
+	db = 1-particles[num].b;
+	particles[num].fr = 1-dr*dr;
+	particles[num].fg = 1-dg*dg;
+	particles[num].fb = 1-db*db;
+}
+
+/* function to "load" a GL texture */
+void flash_loadTexture( )
+{
+	    /* Create The Texture */
+	    glGenTextures( 1, &texture[0] );
+
+	    /* Typical Texture Generation Using Data From The Bitmap */
+	    glBindTexture( GL_TEXTURE_2D, texture[0] );
+
+	    /* Generate The Texture */
+	    glTexImage2D( GL_TEXTURE_2D, 0, 3, particle_image.width,
+			  particle_image.height, 0, GL_RGBA,
+			  GL_UNSIGNED_BYTE, particle_image.pixel_data );
+
+	    /* Linear Filtering */
+	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+}
+
+/* function to reset one particle to initial state */
+void ResetFlash( int num, GLfloat xDir, GLfloat yDir, GLfloat zDir )
+{
+    /* Make the particels active */
+    particles[num].active = TRUE;
+    /* Give the particles life */
+    particles[num].life = 1.0f;
+    /* Random Fade Speed */
+    particles[num].fade = ( GLfloat )( rand( ) *150 )/ (RAND_MAX + 1.0) / 1000.0f + 0.003f;
+    /* Select Red Rainbow Color */
+    particles[num].r = flash_colors[num][0];
+    /* Select Green Rainbow Color */
+    particles[num].g = flash_colors[num][1];
+    /* Select Blue Rainbow Color */
+    particles[num].b = flash_colors[num][2];
+    /* Set the position on the X axis */
+    particles[num].x = 0.0f;
+    /* Set the position on the Y axis */
+    particles[num].y = 0.0f;
+    /* Set the position on the Z axis */
+    particles[num].z = 0.0f;
+    /* Random Speed On X Axis */
+    particles[num].xi = xDir;
+    /* Random Speed On Y Axi */
+    particles[num].yi = yDir;
+    /* Random Speed On Z Axis */
+    particles[num].zi = zDir;
+    /* Set Horizontal Pull To Zero */
+    particles[num].xg = 0.0f;
+    /* Set Vertical Pull Downward */
+    particles[num].yg = -0.8f;
+    /* Set Pull On Z Axis To Zero */
+    particles[num].zg = 0.0f;
+		FlashColor(num);
+}
+
+static void initFlash ( int num, GLfloat value )
+{
+	GLfloat xi, yi, zi;
+	xi = num;
+	yi = 0;
+	zi = 0;
+	ResetFlash( num, xi, yi, zi );
+}
+
+static void
+init_draw_mode ()
+{
+	int loop;
+	conf.global->transparency = TRUE;
+	//conf.global->wireframe = FALSE;
+
+	flash_loadTexture();
+    /* Enable smooth shading */
+    glShadeModel( GL_SMOOTH );
+
+    /* Set the background black */
+    //glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+
+    /* Depth buffer setup */
+    //glClearDepth( 1.0f );
+
+    /* Enables Depth Testing */
+    glDisable( GL_DEPTH_TEST );
+
+    /* Enable Blending */
+    glEnable( GL_BLEND );
+
+			glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+		/* Type Of Blending To Perform */
+    glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+
+    /* Really Nice Perspective Calculations */
+    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+    /* Really Nice Point Smoothing */
+    glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
+
+    /* Enable Texture Mapping */
+  glEnable( GL_TEXTURE_2D );
+    /* Select Our Texture */
+    glBindTexture( GL_TEXTURE_2D, texture[0] );
+		if (!flash_already_initialized)
+		{
+			for (loop=0; loop<NUM_BANDS; loop++)
+			{
+				initFlash(loop,0);
+			}
+			conf_private.f = 1;
+			conf_private.g = 1;
+			conf_private.h = 2;
+			conf_private.m = conf_private.n = conf_private.o = 0;
+			conf_private.t = 0.0f;
+		}
+		flash_already_initialized = TRUE;
+}
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (15.0 + (int) (40.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+static void
+draw_one_frame (gboolean beat)
+{
+	int loop;
+	if (beat)
+		flash_timer = conf_private.flash_timer;
+	conf_private.t += conf_private.speed;
+		/* Modify each of the particles */
+    for ( loop = 0; loop < NUM_BANDS; loop++ )
+	{
+		    GLfloat x;
+		    GLfloat y;
+		    GLfloat z;
+				/* compute the position by a lissajou */
+			GLfloat t1 = (GLfloat)((conf_private.t+loop)/2);
+			conf_private.r1 = (GLfloat)(cos(t1)*sin(t1-loop)*5.0f);
+			conf_private.r2 = (GLfloat)(sin(t1)*cos(t1)*5.0f);
+			conf_private.r3 = (GLfloat)(cos(t1+conf_private.t)*sin(t1+loop)*5.0f);
+			x = (conf_private.r1*cos(conf_private.m*t1+conf_private.f));
+			y = (conf_private.r2*sin(conf_private.n*t1+conf_private.g));
+			z = (conf_private.r3*sin(conf_private.o*t1+conf_private.h));
+
+	    if (particles[loop].active)
+		{
+				/* Draw The Particle Using Our RGB Values,
+		     * Fade The Particle Based On It's Life
+		     */
+				if ((conf_private.flash_on_beat) && (flash_timer>0))
+		    	glColor4f( particles[loop].fr,
+			       particles[loop].fg,
+			       particles[loop].fb,
+			       1.0f );
+				else
+				{
+		    	glColor4f( particles[loop].r,
+			       particles[loop].g,
+			       particles[loop].b,
+			       1.0f );
+				}
+
+				/* Build Quad From A Triangle Strip */
+		    glBegin( GL_TRIANGLE_STRIP );
+		      /* Top Right */
+		      glTexCoord2d( 1, 1 );
+		      glVertex3f( x + datas.data1[loop], y + datas.data1[loop], z );
+		      /* Top Left */
+		      glTexCoord2d( 0, 1 );
+		      glVertex3f( x - datas.data1[loop], y + datas.data1[loop], z );
+		      /* Bottom Right */
+		      glTexCoord2d( 1, 0 );
+		      glVertex3f( x + datas.data1[loop], y - datas.data1[loop], z );
+		      /* Bottom Left */
+		      glTexCoord2d( 0, 0 );
+		      glVertex3f( x - datas.data1[loop], y - datas.data1[loop], z );
+		    glEnd( );
+
+		    glBegin( GL_TRIANGLE_STRIP );
+		      /* Top Right */
+		      glTexCoord2d( 1, 1 );
+		      glVertex3f( x, y + datas.data1[loop], z+datas.data1[loop] );
+		      /* Top Left */
+		      glTexCoord2d( 0, 1 );
+		      glVertex3f( x, y + datas.data1[loop], z-datas.data1[loop] );
+		      /* Bottom Right */
+		      glTexCoord2d( 1, 0 );
+		      glVertex3f( x, y - datas.data1[loop], z+datas.data1[loop] );
+		      /* Bottom Left */
+		      glTexCoord2d( 0, 0 );
+		      glVertex3f( x, y - datas.data1[loop], z-datas.data1[loop] );
+		    glEnd( );
+
+		    glBegin( GL_TRIANGLE_STRIP );
+		      /* Top Right */
+		      glTexCoord2d( 1, 1 );
+		      glVertex3f( x+datas.data1[loop], y, z+datas.data1[loop] );
+		      /* Top Left */
+		      glTexCoord2d( 0, 1 );
+		      glVertex3f( x+datas.data1[loop], y, z-datas.data1[loop] );
+		      /* Bottom Right */
+		      glTexCoord2d( 1, 0 );
+		      glVertex3f( x-datas.data1[loop], y, z+datas.data1[loop] );
+		      /* Bottom Left */
+		      glTexCoord2d( 0, 0 );
+		      glVertex3f( x-datas.data1[loop], y, z-datas.data1[loop] );
+		    glEnd( );
+			}
+		}
+
+	if (flash_timer>0)
+		flash_timer --;
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+	config_default();
+  bmp_cfg_db_get_bool (db, section_name, flash_flash_on_beat, &conf_private.flash_on_beat);
+  bmp_cfg_db_get_int (db, section_name, flash_flash_timer, &conf_private.flash_timer);
+  bmp_cfg_db_get_float (db, section_name, flash_speed, &conf_private.speed);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_bool (db, section_name, flash_flash_on_beat, conf_private.flash_on_beat);
+  bmp_cfg_db_set_int (db, section_name, flash_flash_timer, conf_private.flash_timer);
+  bmp_cfg_db_set_float (db, section_name, flash_speed, conf_private.speed);
+}
+
+
+static void
+config_default ()
+{
+	conf_private.flash_on_beat = TRUE;
+	conf_private.flash_timer = 8;
+	conf_private.speed = 0.01f;
+}
+
+void
+flash_flash_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.flash_on_beat = !conf_private_new.flash_on_beat;
+}
+
+static void
+flash_value_flash (GtkAdjustment * adj)
+{
+  conf_private_new.flash_timer = (int)adj->value;
+}
+
+static void
+value_speed (GtkAdjustment * adj)
+{
+  conf_private_new.speed = (GLfloat) (adj->value/1000);
+}
+
+static void
+config_create (GtkWidget * vbox)
+{
+    GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private_new));
+
+/* flash on beat */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Flash on beats");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.flash_on_beat);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (flash_flash_toggled), NULL);
+
+  /* number of frame for the flash to propagate */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Flash propagation timer (in frames)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.flash_timer, 1, 50, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (flash_value_flash), NULL);
+
+  /* speed */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Speed");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.speed*1000, 1, 100, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_speed), NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_float.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,367 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* New Theme created by Ron Lockwood-Childs
+ * Looks best when alpha blending is OFF
+ */
+
+/* $Id: theme_float.c,v 1.1 2002/10/27 19:21:06 cedric Exp $ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+#define HISTORY_SIZE 16
+#define HALF_BOX   0.15
+#define HALF_BOX_Y (HALF_BOX * 2)
+#define FAR_LEFT   -3.0
+#define FAR_BACK   -3.0
+#define BOTTOM     -2.6
+
+
+typedef struct
+{
+    GLfloat xc;
+    GLfloat yc;
+    GLfloat zc;
+} triple;
+
+static struct
+{
+  int wave_speed;
+  gfloat num_blocks;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+static gfloat speed_to_phase(int speed);
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+
+
+static char float_numblocks[] = "float_numblocks";
+static char float_wavespeed[] = "float_wavespeed";
+
+
+iris_theme theme_float = {
+  "Floaters",
+  "A spectrum of floating blocks (alpha blend off for best effect)",
+  "Ron Lockwood-Childs",
+  "float",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+static GLfloat data2[NUM_BANDS][HISTORY_SIZE];	// previous freq band data
+static GLfloat phase[HISTORY_SIZE];	// previous angle data
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (80.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+static void
+draw_one_frame (gboolean beat)
+{
+  int t1, t2;			// loop vars
+  GLfloat red, green, blue;
+  GLfloat y_color = 0.0;
+  triple ulf, urf, llf, lrf, ulb, urb, llb, lrb;
+  GLfloat basis[NUM_BANDS];
+  int box_height;
+  int i;
+
+  /* shift all data when a new datarow arrives */
+  for (t2 = (HISTORY_SIZE-1); t2 > 0; t2--)
+  {
+        for (t1 = 0; t1 < NUM_BANDS; t1++)
+        {
+            data2[t1][t2] = data2[t1][t2-1];
+        }
+        phase[t2] = phase[t2-1];
+  }
+  for (t1 = 0; t1 < NUM_BANDS; t1++)
+  {
+      data2[t1][0] = datas.data1[t1];
+      phase[0] = phase[1] + speed_to_phase(conf_private.wave_speed);
+  }
+
+  glBegin (GL_QUADS);
+
+  for (t2 = (HISTORY_SIZE-1); t2 >= 0; t2--)
+  {
+      for (t1 = 0; t1 < NUM_BANDS; t1++)
+	  {
+          basis[t1] = BOTTOM + sin( phase[t2] + (speed_to_phase(conf_private.wave_speed) * t1));
+          box_height = (int)ceilf( data2[t1][t2] * conf_private.num_blocks );
+
+          for (i = 0; i < box_height; i++)
+          {
+              if (i < (box_height-1))
+              {
+                  y_color = (GLfloat)i * (1.0 / (GLfloat)conf_private.num_blocks);
+              }
+              else
+              {
+                  y_color = data2[t1][t2];
+              }
+	          get_color (&red, &green, &blue, &y_color);	// box color
+	          glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+
+              ulf.xc = FAR_LEFT + (HALF_BOX * 3 * t1) - HALF_BOX;
+              ulf.yc = basis[t1] + (HALF_BOX_Y * 3 * i) + HALF_BOX_Y;
+              ulf.zc = (FAR_BACK + t2 * HALF_BOX * 3) - HALF_BOX;
+
+              urf.xc = FAR_LEFT + (HALF_BOX * 3 * t1) + HALF_BOX;
+              urf.yc = basis[t1] + (HALF_BOX_Y * 3 * i) + HALF_BOX_Y;
+              urf.zc = (FAR_BACK + t2 * HALF_BOX * 3) - HALF_BOX;
+
+              lrf.xc = FAR_LEFT + (HALF_BOX * 3 * t1) + HALF_BOX;
+              lrf.yc = basis[t1] + (HALF_BOX_Y * 3 * i) - HALF_BOX_Y;
+              lrf.zc = (FAR_BACK + t2 * HALF_BOX * 3) - HALF_BOX;
+
+              llf.xc = FAR_LEFT + (HALF_BOX * 3 * t1) - HALF_BOX;
+              llf.yc = basis[t1] + (HALF_BOX_Y * 3 * i) - HALF_BOX_Y;
+              llf.zc = (FAR_BACK + t2 * HALF_BOX * 3) - HALF_BOX;
+
+              ulb.xc = FAR_LEFT + (HALF_BOX * 3 * t1) - HALF_BOX;
+              ulb.yc = basis[t1] + (HALF_BOX_Y * 3 * i) + HALF_BOX_Y;
+              ulb.zc = (FAR_BACK + t2 * HALF_BOX * 3) + HALF_BOX;
+
+              urb.xc = FAR_LEFT + (HALF_BOX * 3 * t1) + HALF_BOX;
+              urb.yc = basis[t1] + (HALF_BOX_Y * 3 * i) + HALF_BOX_Y;
+              urb.zc = (FAR_BACK + t2 * HALF_BOX * 3) + HALF_BOX;
+
+              lrb.xc = FAR_LEFT + (HALF_BOX * 3 * t1) + HALF_BOX;
+              lrb.yc = basis[t1] + (HALF_BOX_Y * 3 * i) - HALF_BOX_Y;
+              lrb.zc = (FAR_BACK + t2 * HALF_BOX * 3) + HALF_BOX;
+
+              llb.xc = FAR_LEFT + (HALF_BOX * 3 * t1) - HALF_BOX;
+              llb.yc = basis[t1] + (HALF_BOX_Y * 3 * i) - HALF_BOX_Y;
+              llb.zc = (FAR_BACK + t2 * HALF_BOX * 3) + HALF_BOX;
+
+	          // now start drawin'
+	          // start with the front, then left, back, right, finally the top
+
+	          // "front"
+	          glVertex3f (ulf.xc, ulf.yc, ulf.zc);	// "top-left"
+
+	          glVertex3f (urf.xc, urf.yc, urf.zc);	// "top-right"
+
+	          glVertex3f (lrf.xc, lrf.yc, lrf.zc);	// "bottom-right"
+
+	          glVertex3f (llf.xc, llf.yc, llf.zc);	// "bottom-left"
+
+	          // "back"
+	          glVertex3f (ulb.xc, ulb.yc, ulb.zc);	// "top-left"
+
+	          glVertex3f (urb.xc, urb.yc, urb.zc);	// "top-right"
+
+	          glVertex3f (lrb.xc, lrb.yc, lrb.zc);	// "bottom-right"
+
+	          glVertex3f (llb.xc, llb.yc, llb.zc);	// "bottom-left"
+
+	          // "left"
+              glVertex3f( llb.xc, llb.yc, llb.zc);    // "bottom-in"
+
+              glVertex3f( llf.xc, llf.yc, llf.zc);    // "bottom-out"
+
+              glVertex3f( ulf.xc, ulf.yc, ulf.zc);    // "top-out"
+
+              glVertex3f( ulb.xc, ulb.yc, ulb.zc);    // "top-in"
+
+              // "top"
+              glVertex3f( ulb.xc, ulb.yc, ulb.zc);    // "left-in"
+
+              glVertex3f( ulf.xc, ulf.yc, ulf.zc);    // "left-out"
+
+              glVertex3f( urf.xc, urf.yc, urf.zc);    // "right-out"
+
+              glVertex3f( urb.xc, urb.yc, urb.zc);    // "right-in"
+
+              // "right"
+              glVertex3f( urb.xc, urb.yc, urb.zc);    // "top-in"
+
+              glVertex3f( urf.xc, urf.yc, urf.zc);    // "top-out"
+
+              glVertex3f( lrf.xc, lrf.yc, lrf.zc);    // "bottom-out"
+
+              glVertex3f( lrb.xc, lrb.yc, lrb.zc);    // "bottom-in"
+
+              // "bottom"
+              glVertex3f( lrb.xc, lrb.yc, lrb.zc);    // "right-in"
+
+              glVertex3f( lrf.xc, lrf.yc, lrf.zc);    // "right-out"
+
+              glVertex3f( llf.xc, llf.yc, llf.zc);    // "left-out"
+
+              glVertex3f( llb.xc, llb.yc, llb.zc);    // "left-in"
+          }
+      }
+  }
+
+  glEnd ();
+
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_get_float (db, section_name, float_numblocks, &conf_private.num_blocks);
+  bmp_cfg_db_get_int (db, section_name, float_wavespeed, &conf_private.wave_speed);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_float (db, section_name, float_numblocks, conf_private.num_blocks);
+  bmp_cfg_db_set_int (db, section_name, float_wavespeed, conf_private.wave_speed);
+}
+
+
+static void
+config_default ()
+{
+  conf_private.num_blocks = 8.0;
+  conf_private.wave_speed = 4;
+}
+
+
+static void
+blocks_changed (GtkAdjustment * adj)
+{
+  conf_private_new.num_blocks = (int) adj->value;
+}
+
+
+// speeds: pi/8, pi/12, pi/16, pi/20, pi/24, pi/28, pi/32,0
+static gfloat speed_to_phase(int speed)
+{
+  gfloat phase;
+
+  if (speed == 0)
+  {
+    phase = 0;
+  }
+  else
+  {
+    phase = M_PI_4/(9-speed);
+  }
+
+  return phase;
+}
+
+static void
+speed_changed (GtkWidget *menuitem, gpointer data)
+{
+  conf_private_new.wave_speed = GPOINTER_TO_INT(data);
+}
+
+
+
+static void
+config_create (GtkWidget * vbox)
+{
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+  GtkWidget *menu;
+  GtkWidget *menuitem;
+  GtkWidget *optionmenu;
+  gchar *speeds[8] = {"0","1","2","3","4","5","6","7"};
+  int i;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private));
+
+  /* number blocks */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Max number blocks per stack");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.num_blocks, 4, 8, 1, 2, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (blocks_changed), NULL);
+
+  /* set wave speed */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Wave speed");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  menu = gtk_menu_new ();
+  for (i=0; i<8; i++)
+  {
+    menuitem =  gtk_menu_item_new_with_label(speeds[i]);
+    gtk_menu_append(GTK_MENU(menu), menuitem);
+    gtk_widget_show (menuitem);
+    gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+           GTK_SIGNAL_FUNC (speed_changed), GINT_TO_POINTER(i));
+  }
+  optionmenu = gtk_option_menu_new();
+  gtk_menu_set_active(GTK_MENU(menu), conf_private.wave_speed);
+  gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu), menu);
+  gtk_box_pack_start (GTK_BOX (hbox), optionmenu, FALSE, FALSE, 4);
+  gtk_widget_show (optionmenu);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_fountain.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,789 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2004 Marc Pompl (marc.pompl@lynorics.de)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+#include "particle.h"
+
+/* Max number of particles */
+#define MAX_PARTICLES 10000
+
+static GLuint texture[1];	/* Storage For Our Particle Texture                   */
+
+static int draw_mode = 0;	// the drawing mode
+
+static GLuint col = 0;		/* Current Color Selection                            */
+
+static gboolean fountain_already_initialized = FALSE;
+
+static float flash_timer = 0;	/* timer for flash */
+
+static struct
+{
+  int draw_mode;
+  gboolean flash_on_beat;
+  int flash_timer;
+
+  gboolean rainbow;		/* Toggle rainbow effect                              */
+
+  GLfloat slowdown;		/* Slow Down Particles (1.0 - 4.0) */
+  GLfloat xspeed;		/* Base X Speed */
+  GLfloat yspeed;		/* Base Y Speed */
+  GLfloat up;			/* Particles firing upways (0.0 - 1.0) */
+  GLfloat side;			/* Particles firing sideways (0.0 - 1.0) */
+  GLfloat strength;		/* Strength of particle blast (0.0 - 1.0) */
+  gboolean hide_inactive;	/* Disable inactive ("just falling") particles? */
+  GLfloat size;			/* Size of particles */
+  int particles;		/* number of particles */
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  (config_global *) NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  (config_global *) NULL,
+  &conf_private_new
+};
+
+static char fountain_flash_on_beat[] = "fountain_flash_on_beat";
+static char fountain_flash_timer[] = "fountain_flash_timer";
+static char fountain_rainbow[] = "fountain_rainbow";
+static char fountain_slowdown[] = "fountain_slowdown";
+static char fountain_xspeed[] = "fountain_xspeed";
+static char fountain_yspeed[] = "fountain_yspeed";
+static char fountain_up[] = "fountain_up";
+static char fountain_side[] = "fountain_side";
+static char fountain_strength[] = "fountain_strength";
+static char fountain_hide_inactive[] = "fountain_hide_inactive";
+static char fountain_size[] = "fountain_size";
+static char fountain_particles[] = "fountain_particles";
+
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+static void init_draw_mode (void);
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+iris_theme theme_fountain = {
+  "fountain",
+  "an atmospheric particle fountain\nno support  for wireframe or solid surfaces\nbased upon NeHe tutorial #19",
+  "Marc Pompl (marc.pompl@lynorics.de)",
+  "fountain",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  init_draw_mode,
+  get_x_angle,
+  draw_one_frame
+};
+
+/* Create our particle structure */
+typedef struct
+{
+  GLint active;			/* Active (Yes/No) */
+  GLfloat life;			/* Particle Life   */
+  GLfloat fade;			/* Fade Speed      */
+
+  GLfloat r;			/* Red Value       */
+  GLfloat g;			/* Green Value     */
+  GLfloat b;			/* Blue Value      */
+
+  GLfloat fr;			/* Red Flash Value       */
+  GLfloat fg;			/* Green Flash Value     */
+  GLfloat fb;			/* Blue Flash Value      */
+
+  GLfloat x;			/* X Position      */
+  GLfloat y;			/* Y Position      */
+  GLfloat z;			/* Z Position      */
+
+  GLfloat xi;			/* X Direction     */
+  GLfloat yi;			/* Y Direction     */
+  GLfloat zi;			/* Z Direction     */
+
+  GLfloat xg;			/* X Gravity       */
+  GLfloat yg;			/* Y Gravity       */
+  GLfloat zg;			/* Z Gravity       */
+} particle;
+
+/* Rainbow of colors */
+static GLfloat fountain_colors[16][3] = {
+  {1.0f, 0.5f, 0.5f},
+  {1.0f, 0.75f, 0.5f},
+  {1.0f, 1.0f, 0.5f},
+
+  {0.75f, 1.0f, 0.5f},
+
+  {0.5f, 1.0f, 0.5f},
+  {0.5f, 1.0f, 0.75f},
+  {0.5f, 1.0f, 1.0f},
+
+  {0.5f, 0.75f, 1.0f},
+  {0.5f, 0.5f, 1.0f},
+  {0.75f, 0.5f, 1.0f},
+
+  {1.0f, 0.5f, 1.0f},
+  {1.0f, 0.5f, 0.75f},
+  {0.75f, 0.5f, 0.75f},
+
+  {0.5f, 0.5f, 0.5f},
+  {0.75f, 0.75f, 0.75f},
+  {1.0f, 1.0f, 1.0f},
+};
+
+/* Our beloved array of particles */
+static particle particles[MAX_PARTICLES];
+
+void
+flashParticleColor (int num)
+{
+  GLfloat dr;
+  GLfloat dg;
+  GLfloat db;
+  dr = 1 - particles[num].r;
+  dg = 1 - particles[num].g;
+  db = 1 - particles[num].b;
+  particles[num].fr = 1 - dr * dr;
+  particles[num].fg = 1 - dg * dg;
+  particles[num].fb = 1 - db * db;
+}
+
+/* function to "load" a GL texture */
+void
+loadTexture ()
+{
+  /* Create The Texture */
+  glGenTextures (1, &texture[0]);
+
+  /* Typical Texture Generation Using Data From The Bitmap */
+  glBindTexture (GL_TEXTURE_2D, texture[0]);
+
+  /* Generate The Texture */
+  glTexImage2D (GL_TEXTURE_2D, 0, 3, particle_image.width,
+		particle_image.height, 0, GL_RGBA,
+		GL_UNSIGNED_BYTE, particle_image.pixel_data);
+
+  /* Linear Filtering */
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
+/* function to reset one particle to initial state */
+void
+ResetParticle (int num, GLint color, GLfloat xDir, GLfloat yDir, GLfloat zDir)
+{
+  /* Make the particels active */
+  particles[num].active = TRUE;
+  /* Give the particles life */
+  particles[num].life = 1.0f;
+  /* Random Fade Speed */
+  particles[num].fade =
+    (GLfloat) (rand () * 150) / (RAND_MAX + 1.0) / 1000.0f + 0.003f;
+  /* Select Red Rainbow Color */
+  particles[num].r = fountain_colors[color][0];
+  /* Select Green Rainbow Color */
+  particles[num].g = fountain_colors[color][1];
+  /* Select Blue Rainbow Color */
+  particles[num].b = fountain_colors[color][2];
+  /* Set the position on the X axis */
+  particles[num].x = 0.0f;
+  /* Set the position on the Y axis */
+  particles[num].y = 0.0f;
+  /* Set the position on the Z axis */
+  particles[num].z = 0.0f;
+  /* Random Speed On X Axis */
+  particles[num].xi = xDir;
+  /* Random Speed On Y Axi */
+  particles[num].yi = yDir;
+  /* Random Speed On Z Axis */
+  particles[num].zi = zDir;
+  /* Set Horizontal Pull To Zero */
+  particles[num].xg = 0.0f;
+  /* Set Vertical Pull Downward */
+  particles[num].yg = -0.8f;
+  /* Set Pull On Z Axis To Zero */
+  particles[num].zg = 0.0f;
+  flashParticleColor (num);
+}
+
+static void
+initParticle (int num, GLint color, GLfloat value)
+{
+  GLfloat xi, yi, zi;
+  xi = conf_private.xspeed +
+    (GLfloat) ((rand () * 60 - 30.0f) / (RAND_MAX +
+					 1.0) * 500 * conf_private.side *
+	       (value + conf_private.strength));
+  yi =
+    conf_private.yspeed +
+    (GLfloat) ((rand () * 100) / (RAND_MAX + 1.0) * 500 * conf_private.up *
+	       (value + conf_private.strength));
+  zi =
+    (GLfloat) ((rand () * 60 - 30.0f) / (RAND_MAX +
+					 1.0) * 500 * conf_private.side *
+	       (value + conf_private.strength));
+  ResetParticle (num, color, xi, yi, zi);
+}
+
+static void
+init_draw_mode ()
+{
+  GLfloat ratio;
+  int loop;
+
+  conf.global->transparency = TRUE;
+  conf.global->wireframe = FALSE;
+
+  draw_mode = 1 + (int) (3.0 * rand () / (RAND_MAX + 1.0));
+
+  ratio = (GLfloat) GLWin.window_width / (GLfloat) GLWin.window_height;
+
+  loadTexture ();
+  /* Enable smooth shading */
+  glShadeModel (GL_SMOOTH);
+
+  /* Set the background black */
+  glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+
+  /* Depth buffer setup */
+  glClearDepth (1.0f);
+
+  /* Enables Depth Testing */
+  glDisable (GL_DEPTH_TEST);
+
+  /* Enable Blending */
+  glEnable (GL_BLEND);
+
+  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+  /* Type Of Blending To Perform */
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+
+  /* Really Nice Perspective Calculations */
+  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+  /* Really Nice Point Smoothing */
+  glHint (GL_POINT_SMOOTH_HINT, GL_NICEST);
+
+  /* Enable Texture Mapping */
+  glEnable (GL_TEXTURE_2D);
+  /* Select Our Texture */
+  glBindTexture (GL_TEXTURE_2D, texture[0]);
+
+  /* Reset all the particles */
+  if (!fountain_already_initialized)
+    {
+      for (loop = 0; loop < MAX_PARTICLES; loop++)
+	{
+	  GLint color = (loop + 1) / (MAX_PARTICLES / 16);
+	  initParticle (loop, color, (rand () * 0.5f) / (RAND_MAX + 1.0));
+	}
+    }
+  fountain_already_initialized = TRUE;
+}
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (5.0 + (int) (30.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+static void
+draw_one_frame (gboolean beat)
+{
+  int loop;
+  if ((beat) && (conf_private.flash_on_beat))
+    flash_timer = conf_private.flash_timer;
+
+  /* If rainbow coloring is turned on, cycle the colors */
+  if (conf_private.rainbow)	// && ( delay > 25 ) )
+    {
+      col++;
+      col = col % 16;
+    }
+
+  /* Modify each of the particles */
+  for (loop = 0; loop < MAX_PARTICLES; loop++)
+    {
+      /* Grab Our Particle X Position */
+      GLfloat x = particles[loop].x;
+      /* Grab Our Particle Y Position */
+      GLfloat y = particles[loop].y;
+      /* Particle Z Position + Zoom */
+      GLfloat z = particles[loop].z;
+
+      if ((loop < conf_private.particles) && (particles[loop].active))
+	{
+	  /* Draw The Particle Using Our RGB Values,
+	   * Fade The Particle Based On It's Life
+	   */
+	  if ((conf_private.flash_on_beat) && (flash_timer > 0))
+	    glColor4f (particles[loop].fr,
+		       particles[loop].fg,
+		       particles[loop].fb, particles[loop].life);
+	  else if (conf_private.rainbow)
+	    glColor4f (particles[loop].r,
+		       particles[loop].g,
+		       particles[loop].b, particles[loop].life);
+	  else
+	    {
+	      GLfloat r, g, b;
+	      get_color (&r, &g, &b, &datas.data1[loop % NUM_BANDS]);
+	      glColor4f (r, g, b, particles[loop].life);
+	    }
+
+	  /* Build Quad From A Triangle Strip */
+	  glBegin (GL_TRIANGLE_STRIP);
+	  /* Top Right */
+	  glTexCoord2d (1, 1);
+	  glVertex3f (x + conf_private.size, y + conf_private.size, z);
+	  /* Top Left */
+	  glTexCoord2d (0, 1);
+	  glVertex3f (x - conf_private.size, y + conf_private.size, z);
+	  /* Bottom Right */
+	  glTexCoord2d (1, 0);
+	  glVertex3f (x + conf_private.size, y - conf_private.size, z);
+	  /* Bottom Left */
+	  glTexCoord2d (0, 0);
+	  glVertex3f (x - conf_private.size, y - conf_private.size, z);
+	  glEnd ();
+
+	  glBegin (GL_TRIANGLE_STRIP);
+	  /* Top Right */
+	  glTexCoord2d (1, 1);
+	  glVertex3f (x, y + conf_private.size, z + conf_private.size);
+	  /* Top Left */
+	  glTexCoord2d (0, 1);
+	  glVertex3f (x, y + conf_private.size, z - conf_private.size);
+	  /* Bottom Right */
+	  glTexCoord2d (1, 0);
+	  glVertex3f (x, y - conf_private.size, z + conf_private.size);
+	  /* Bottom Left */
+	  glTexCoord2d (0, 0);
+	  glVertex3f (x, y - conf_private.size, z - conf_private.size);
+	  glEnd ();
+
+	  glBegin (GL_TRIANGLE_STRIP);
+	  /* Top Right */
+	  glTexCoord2d (1, 1);
+	  glVertex3f (x + conf_private.size, y, z + conf_private.size);
+	  /* Top Left */
+	  glTexCoord2d (0, 1);
+	  glVertex3f (x + conf_private.size, y, z - conf_private.size);
+	  /* Bottom Right */
+	  glTexCoord2d (1, 0);
+	  glVertex3f (x - conf_private.size, y, z + conf_private.size);
+	  /* Bottom Left */
+	  glTexCoord2d (0, 0);
+	  glVertex3f (x - conf_private.size, y, z - conf_private.size);
+	  glEnd ();
+	}
+
+      if (flash_timer > 0)
+	{
+	  /* Move On The X Axis By X Speed */
+	  particles[loop].x += particles[loop].xi /
+	    (conf_private.slowdown * 2000);
+	  /* Move On The Y Axis By Y Speed */
+	  particles[loop].y += particles[loop].yi /
+	    (conf_private.slowdown * 2000);
+	  /* Move On The Z Axis By Z Speed */
+	  particles[loop].z += particles[loop].zi /
+	    (conf_private.slowdown * 2000);
+	}
+      else
+	{
+	  /* Move On The X Axis By X Speed */
+	  particles[loop].x += particles[loop].xi /
+	    (conf_private.slowdown * 1000);
+	  /* Move On The Y Axis By Y Speed */
+	  particles[loop].y += particles[loop].yi /
+	    (conf_private.slowdown * 1000);
+	  /* Move On The Z Axis By Z Speed */
+	  particles[loop].z += particles[loop].zi /
+	    (conf_private.slowdown * 1000);
+	}
+      /* Take Pull On X Axis Into Account */
+      particles[loop].xi += particles[loop].xg;
+      /* Take Pull On Y Axis Into Account */
+      particles[loop].yi += particles[loop].yg;
+      /* Take Pull On Z Axis Into Account */
+      particles[loop].zi += particles[loop].zg;
+      /* If the particle dies, revive it */
+      /* Reduce Particles Life By 'Fade' */
+      particles[loop].life -= particles[loop].fade;
+
+      if (particles[loop].life < 0.0f)
+	{
+	  if (conf_private.rainbow)
+	    initParticle (loop, col, datas.data1[col]);
+	  else
+	    initParticle (loop, col,
+			  datas.
+			  data1[(int)
+				((rand () * NUM_BANDS) / (RAND_MAX + 1.0))]);
+	  if ((conf_private.hide_inactive) && (datas.data1[col] == 0.0f))
+	    particles[loop].active = FALSE;
+
+	}
+    }
+  if (flash_timer > 0)
+    flash_timer--;
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_get_bool (db, section_name, fountain_flash_on_beat, &conf_private.flash_on_beat);
+  bmp_cfg_db_get_int (db, section_name, fountain_flash_timer, &conf_private.flash_timer);
+  bmp_cfg_db_get_bool (db, section_name, fountain_rainbow, &conf_private.rainbow);
+  bmp_cfg_db_get_float (db, section_name, fountain_slowdown, &conf_private.slowdown);
+  bmp_cfg_db_get_float (db, section_name, fountain_xspeed, &conf_private.xspeed);
+  bmp_cfg_db_get_float (db, section_name, fountain_yspeed, &conf_private.yspeed);
+  bmp_cfg_db_get_float (db, section_name, fountain_up, &conf_private.up);
+  bmp_cfg_db_get_float (db, section_name, fountain_side, &conf_private.side);
+  bmp_cfg_db_get_float (db, section_name, fountain_strength, &conf_private.strength);
+  bmp_cfg_db_get_bool (db, section_name, fountain_hide_inactive, &conf_private.hide_inactive);
+  bmp_cfg_db_get_float (db, section_name, fountain_size, &conf_private.size);
+  bmp_cfg_db_get_int (db, section_name, fountain_particles, &conf_private.particles);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_bool (db, section_name, fountain_flash_on_beat, conf_private.flash_on_beat);
+  bmp_cfg_db_set_int (db, section_name, fountain_flash_timer, conf_private.flash_timer);
+  bmp_cfg_db_set_bool (db, section_name, fountain_rainbow, conf_private.rainbow);
+  bmp_cfg_db_set_float (db, section_name, fountain_slowdown, conf_private.slowdown);
+  bmp_cfg_db_set_float (db, section_name, fountain_xspeed, conf_private.xspeed);
+  bmp_cfg_db_set_float (db, section_name, fountain_yspeed, conf_private.yspeed);
+  bmp_cfg_db_set_float (db, section_name, fountain_up, conf_private.up);
+  bmp_cfg_db_set_float (db, section_name, fountain_side, conf_private.side);
+  bmp_cfg_db_set_float (db, section_name, fountain_strength, conf_private.strength);
+  bmp_cfg_db_set_bool (db, section_name, fountain_hide_inactive, conf_private.hide_inactive);
+  bmp_cfg_db_set_float (db, section_name, fountain_size, conf_private.size);
+  bmp_cfg_db_set_int (db, section_name, fountain_particles, conf_private.particles);
+}
+
+
+static void
+config_default ()
+{
+  conf_private.flash_on_beat = TRUE;
+  conf_private.flash_timer = 8;
+
+  conf_private.rainbow = TRUE;
+  conf_private.slowdown = 2.0f;
+  conf_private.xspeed = 0.0f;
+  conf_private.yspeed = 1.0f;
+  conf_private.up = 0.8f;
+  conf_private.side = 0.2f;
+  conf_private.strength = 0.1f;
+  conf_private.hide_inactive = TRUE;
+  conf_private.size = 0.16f;
+  conf_private.particles = 1000;
+}
+
+void
+flash_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.flash_on_beat = !conf_private_new.flash_on_beat;
+}
+
+static void
+value_flash (GtkAdjustment * adj)
+{
+  conf_private_new.flash_timer = (float) adj->value;
+}
+
+void
+hide_inactive_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.hide_inactive = !conf_private_new.hide_inactive;
+}
+
+void
+rainbow_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.rainbow = !conf_private_new.rainbow;
+}
+
+static void
+value_slowdown (GtkAdjustment * adj)
+{
+  conf_private_new.slowdown = (float) adj->value / 100;
+}
+
+static void
+value_up (GtkAdjustment * adj)
+{
+  conf_private_new.up = (float) adj->value / 100;
+}
+
+static void
+value_side (GtkAdjustment * adj)
+{
+  conf_private_new.side = (float) adj->value / 100;
+}
+
+static void
+value_strength (GtkAdjustment * adj)
+{
+  conf_private_new.strength = (float) adj->value / 100;
+}
+
+static void
+value_size (GtkAdjustment * adj)
+{
+  conf_private_new.size = (float) adj->value / 100;
+}
+
+static void
+value_particles (GtkAdjustment * adj)
+{
+  conf_private_new.particles = (float) adj->value;
+}
+static void
+config_create (GtkWidget * vbox)
+{
+  GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private_new));
+
+  /* Number of particles */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Number of particles");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.particles, 1, MAX_PARTICLES, 1, 10,
+			0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_particles), NULL);
+
+  /* wave on beat */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Flash on beats");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.flash_on_beat);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (flash_toggled), NULL);
+
+  /* number of frame for the wave to propagate */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Flash propagation timer (in frames)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.flash_timer, 1, 50, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_flash), NULL);
+
+  /* strength for up firing */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Slowdown");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.slowdown * 100, 100, 400, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_slowdown), NULL);
+
+  /* strength for up firing */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Strength of up firing");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.up * 100, 1, 100, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_up), NULL);
+
+  /* strength for side firing */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Strength of side firing");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.side * 100, 1, 100, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_side), NULL);
+
+  /* overall strength */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Strength");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.strength * 100, 1, 100, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_strength), NULL);
+
+  /* Toggle inactive particles */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Hide inactive particles");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.hide_inactive);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (hide_inactive_toggled), NULL);
+
+  /* Toggle rainbow */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Rainbow colors");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.rainbow);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (rainbow_toggled), NULL);
+
+  /* size of particles */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Size of particles");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.size * 100, 1, 100, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_size), NULL);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_knot.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,415 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+
+static struct
+{
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static void init (void);
+static void cleanup (void);
+static void init_draw_mode (void);
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+
+iris_theme theme_knot = {
+  "Knot",
+  "Dancing knot",
+  "Pascal Brochart for Nebulus, adapted for Iris by foser",
+  "knot",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  init,
+  cleanup,
+  init_draw_mode,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+gboolean reverse = FALSE;
+GLfloat knot_time;
+
+typedef struct
+{
+  GLfloat x, y, z;
+}
+glcoord;
+
+typedef struct
+{
+  GLfloat r, g, b;
+}
+glcolors;
+
+typedef struct
+{
+  int numfaces, numverts, numsides;
+  GLuint faces[16 * 64 * 4 * 4];
+  glcoord vertices[16 * 64];
+  glcolors Colors[16 * 64];
+}
+tknotobject;
+
+tknotobject *knotobject;
+
+
+void
+createknot (int scaling_factor1, int scaling_factor2, GLfloat radius1,
+	    GLfloat radius2, GLfloat radius3)
+{
+  int count1, count2;
+  GLfloat alpha, beta, distance, mindistance, rotation;
+  GLfloat x, y, z, dx, dy, dz;
+  GLfloat value, modulus, dist;
+  int index1, index2;
+
+  knotobject->numsides = 4;
+
+  knotobject->numverts = 0;
+  alpha = 0;
+  for (count2 = 0; count2 < scaling_factor2; count2++)
+    {
+      alpha = alpha + 2 * M_PI / scaling_factor2;
+      x = radius2 * cos (2 * alpha) + radius1 * sin (alpha);
+      y = radius2 * sin (2 * alpha) + radius1 * cos (alpha);
+      z = radius2 * cos (3 * alpha);
+      dx = -2 * radius2 * sin (2 * alpha) + radius1 * cos (alpha);
+      dy = 2 * radius2 * cos (2 * alpha) - radius1 * sin (alpha);
+      dz = -3 * radius2 * sin (3 * alpha);
+      value = sqrt (dx * dx + dz * dz);
+      modulus = sqrt (dx * dx + dy * dy + dz * dz);
+
+      beta = 0;
+      for (count1 = 0; count1 < scaling_factor1; count1++)
+	{
+	  beta = beta + 2 * M_PI / scaling_factor1;
+
+	  knotobject->vertices[knotobject->numverts].x =
+	    x - radius3 * (cos (beta) * dz -
+			   sin (beta) * dx * dy / modulus) / value;
+	  knotobject->vertices[knotobject->numverts].y =
+	    y - radius3 * sin (beta) * value / modulus;
+	  knotobject->vertices[knotobject->numverts].z =
+	    z + radius3 * (cos (beta) * dx +
+			   sin (beta) * dy * dz / modulus) / value;
+
+
+	  dist =
+	    sqrt (knotobject->vertices[knotobject->numverts].x *
+		  knotobject->vertices[knotobject->numverts].x +
+		  knotobject->vertices[knotobject->numverts].y *
+		  knotobject->vertices[knotobject->numverts].y +
+		  knotobject->vertices[knotobject->numverts].z *
+		  knotobject->vertices[knotobject->numverts].z);
+
+	  knotobject->Colors[knotobject->numverts].r =
+	    ((2 / dist) + (0.5 * sin (beta) + 0.4)) / 2.0;
+	  knotobject->Colors[knotobject->numverts].g =
+	    ((2 / dist) + (0.5 * sin (beta) + 0.4)) / 2.0;
+	  knotobject->Colors[knotobject->numverts].b =
+	    ((2 / dist) + (0.5 * sin (beta) + 0.4)) / 2.0;
+
+	  knotobject->numverts++;
+	}
+    }
+
+  for (count1 = 0; count1 < scaling_factor2; count1++)
+    {
+      index1 = count1 * scaling_factor1;
+      index2 = index1 + scaling_factor1;
+      index2 = index2 % knotobject->numverts;
+      rotation = 0;
+      mindistance =
+	(knotobject->vertices[index1].x -
+	 knotobject->vertices[index2].x) * (knotobject->vertices[index1].x -
+					   knotobject->vertices[index2].x) +
+	(knotobject->vertices[index1].y -
+	 knotobject->vertices[index2].y) * (knotobject->vertices[index1].y -
+					   knotobject->vertices[index2].y) +
+	(knotobject->vertices[index1].z -
+	 knotobject->vertices[index2].z) * (knotobject->vertices[index1].z -
+					   knotobject->vertices[index2].z);
+      for (count2 = 1; count2 < scaling_factor1; count2++)
+	{
+	  index2 = count2 + index1 + scaling_factor1;
+	  if (count1 == scaling_factor2 - 1)
+	    index2 = count2;
+	  distance =
+	    (knotobject->vertices[index1].x -
+	     knotobject->vertices[index2].x) * (knotobject->vertices[index1].x -
+					       knotobject->vertices[index2].
+					       x) +
+	    (knotobject->vertices[index1].y -
+	     knotobject->vertices[index2].y) * (knotobject->vertices[index1].y -
+					       knotobject->vertices[index2].
+					       y) +
+	    (knotobject->vertices[index1].z -
+	     knotobject->vertices[index2].z) * (knotobject->vertices[index1].z -
+					       knotobject->vertices[index2].z);
+	  if (distance < mindistance)
+	    {
+	      mindistance = distance;
+	      rotation = count2;
+	    }
+	}
+
+      for (count2 = 0; count2 < scaling_factor1; count2++)
+	{
+	  knotobject->faces[4 * (index1 + count2) + 0] = index1 + count2;
+
+	  index2 = count2 + 1;
+	  index2 = index2 % scaling_factor1;
+	  knotobject->faces[4 * (index1 + count2) + 1] = index1 + index2;
+
+	  index2 = (count2 + rotation + 1);
+	  index2 = index2 % scaling_factor1;
+	  knotobject->faces[4 * (index1 + count2) + 2] =
+	    (index1 + index2 + scaling_factor1) % knotobject->numverts;
+
+	  index2 = (count2 + rotation);
+	  index2 = index2 % scaling_factor1;
+
+	  knotobject->faces[4 * (index1 + count2) + 3] =
+	    (index1 + index2 + scaling_factor1) % knotobject->numverts;
+	  knotobject->numfaces++;
+	}
+    }
+}
+
+
+static void
+init ()
+{
+  knotobject = (tknotobject *)malloc(sizeof(tknotobject));
+  createknot (16, 64, 2, 2.0, 1.0);
+}
+
+
+static void
+cleanup()
+{
+  free(knotobject);
+}
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (80.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+init_draw_mode ()
+{
+  //don't think all of this really is needed here..
+  glDepthFunc (GL_LESS);
+  glDisable (GL_NORMALIZE);
+  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+  glDisable (GL_BLEND);
+  glEnable (GL_DEPTH_TEST);
+}
+
+
+void
+recalculateknot (int scaling_factor1, int scaling_factor2, GLfloat radius1,
+		 GLfloat radius2, GLfloat radius3)
+{
+  int count1, count2;
+  GLfloat alpha, beta;
+  GLfloat x, y, z, dx, dy, dz;
+  GLfloat value, modulus;
+  int index1, index2;
+  GLfloat distance, Mindistance, rotation;
+
+  knotobject->numverts = 0;
+  alpha = 0;
+  for (count2 = 0; count2 < scaling_factor2; count2++)
+    {
+      alpha = alpha + 2 * M_PI / scaling_factor2;
+      x = radius2 * cos (2 * alpha) + radius1 * sin (alpha);
+      y = radius2 * sin (2 * alpha) + radius1 * cos (alpha);
+      z = radius2 * cos (3 * alpha);
+      dx = -2 * radius2 * sin (2 * alpha) + radius1 * cos (alpha);
+      dy = 2 * radius2 * cos (2 * alpha) - radius1 * sin (alpha);
+      dz = -3 * radius2 * sin (3 * alpha);
+      value = sqrt (dx * dx + dz * dz);
+      modulus = sqrt (dx * dx + dy * dy + dz * dz);
+
+      beta = 0;
+      for (count1 = 0; count1 < scaling_factor1; count1++)
+	{
+	  beta = beta + 2 * M_PI / scaling_factor1;
+
+	  knotobject->vertices[knotobject->numverts].x =
+	    x - radius3 * (cos (beta) * dz -
+			   sin (beta) * dx * dy / modulus) / value;
+	  knotobject->vertices[knotobject->numverts].y =
+	    y - radius3 * sin (beta) * value / modulus;
+	  knotobject->vertices[knotobject->numverts].z =
+	    z + radius3 * (cos (beta) * dx +
+			   sin (beta) * dy * dz / modulus) / value;
+
+	  knotobject->numverts++;
+	}
+    }
+
+  knotobject->numfaces = 0;
+  for (count1 = 0; count1 < scaling_factor2; count1++)
+    {
+      index1 = count1 * scaling_factor1;
+      index2 = index1 + scaling_factor1;
+      index2 = index2 % knotobject->numverts;
+      rotation = 0;
+      Mindistance =
+	(knotobject->vertices[index1].x -
+	 knotobject->vertices[index2].x) * (knotobject->vertices[index1].x -
+					   knotobject->vertices[index2].x) +
+	(knotobject->vertices[index1].y -
+	 knotobject->vertices[index2].y) * (knotobject->vertices[index1].y -
+					   knotobject->vertices[index2].y) +
+	(knotobject->vertices[index1].z -
+	 knotobject->vertices[index2].z) * (knotobject->vertices[index1].z -
+					   knotobject->vertices[index2].z);
+      for (count2 = 1; count2 < scaling_factor1; count2++)
+	{
+	  index2 = count2 + index1 + scaling_factor1;
+	  if (count1 == scaling_factor2 - 1)
+	    index2 = count2;
+	  distance =
+	    (knotobject->vertices[index1].x -
+	     knotobject->vertices[index2].x) * (knotobject->vertices[index1].x -
+					       knotobject->vertices[index2].
+					       x) +
+	    (knotobject->vertices[index1].y -
+	     knotobject->vertices[index2].y) * (knotobject->vertices[index1].y -
+					       knotobject->vertices[index2].
+					       y) +
+	    (knotobject->vertices[index1].z -
+	     knotobject->vertices[index2].z) * (knotobject->vertices[index1].z -
+					       knotobject->vertices[index2].z);
+	  if (distance < Mindistance)
+	    {
+	      Mindistance = distance;
+	      rotation = count2;
+	    }
+	}
+
+      for (count2 = 0; count2 < scaling_factor1; count2++)
+	{
+	  knotobject->faces[4 * (index1 + count2) + 0] = index1 + count2;
+
+	  //removes draw artifacts
+	  //if (point_general->hide_glue)
+	  index2 = index2 % scaling_factor1;
+
+	  knotobject->faces[4 * (index1 + count2) + 2] =
+	    (index1 + index2 + scaling_factor1) % knotobject->numverts;
+
+	  index2 = count2 + rotation;
+	  index2 = index2 % scaling_factor1;
+
+	  knotobject->faces[4 * (index1 + count2) + 3] =
+	    (index1 + index2 + scaling_factor1) % knotobject->numverts;
+	  knotobject->numfaces++;
+	}
+    }
+}
+
+
+void
+draw_the_knot (void)
+{
+  int i, j, num;
+  float red, green, blue, peak;
+
+  glBegin (GL_QUADS);
+  j = knotobject->numfaces * 4;
+  for (i = 0; i < j; i++)
+    {
+      num = knotobject->faces[i];
+
+      //adapted to use Iris colors
+      get_color (&red, &green, &blue, &peak);
+      glColor3f (knotobject->Colors[num].r * red,
+		 knotobject->Colors[num].g * green, knotobject->Colors[num].b);
+      glVertex3f (knotobject->vertices[num].x, knotobject->vertices[num].y,
+		  knotobject->vertices[num].z);
+    }
+  glEnd ();
+}
+
+
+void
+createknotpolygons (void)
+{
+  if (datas.loudness > 12000)
+    if (reverse)
+      knot_time -= 12000.0f / (16.0f * config.fps);
+    else
+      knot_time += 12000.0f / (16.0f * config.fps);
+  else if (reverse)
+    knot_time -= datas.loudness / (16.0f * config.fps);
+  else
+    knot_time += datas.loudness / (16.0f * config.fps);
+
+  recalculateknot (16, 64, 3 * sin (0.015 * knot_time) + 0.8,
+		   3 * cos (0.008 * knot_time) + 0.8, 1.1);
+
+  glTranslatef (0.0f, 0.0f, 0.0f);
+  draw_the_knot ();
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  if (beat)
+    reverse = !reverse;
+  glPushMatrix ();
+  /* scale it all down to Iris sizes */
+  glScalef (0.5, 0.5, 0.5);
+  createknotpolygons ();
+  glPopMatrix ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_original.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,366 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+GLfloat jump[16] =
+  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+  0.0
+};
+
+xz xz1, xz2, xz3, xz4;
+
+static int draw_mode = 0;	// the drawing mode
+
+static struct
+{
+  int draw_mode;
+  int angle_step;
+  gboolean wave_on_beat;
+  GLfloat wave_height;
+  int wave_timer;
+  GLfloat radius;
+  GLfloat interband;
+  GLfloat linelength;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  (config_global *) NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  (config_global *) NULL,
+  &conf_private_new
+};
+
+static char original_draw_mode[] = "original_draw_mode";
+static char original_angle_step[] = "original_angle_step";
+static char original_wave_on_beat[] = "original_wave_on_beat";
+static char original_wave_height[] = "original_wave_height";
+static char original_wave_timer[] = "original_wave_timer";
+static char original_radius[] = "original_radius";
+static char original_interband[] = "original_interband";
+static char original_linelength[] = "original_linelength";
+
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+static void init_draw_mode (void);
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+iris_theme theme_original = {
+  "Original",
+  "A 360 degrees spectrum analyzer",
+  "Cédric Delfosse (cdelfosse@free.fr)",
+  "original",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  init_draw_mode,
+  get_x_angle,
+  draw_one_frame
+};
+
+
+static void
+shift_jump ()
+{
+  int i;
+
+  for (i = 15; i > 0; i--)
+    jump[i] = jump[i - 1];
+  jump[0] = 0.0;
+}
+
+
+static void
+init_draw_mode ()
+{
+  draw_mode = 1 + (int) (3.0 * rand () / (RAND_MAX + 1.0));
+}
+
+
+static GLfloat
+get_x_angle ()
+{
+  if (draw_mode == 3)
+    return (45.0 + (int) (30.0 * rand () / (RAND_MAX + 1.0)));
+  else
+    return (55.0 + (int) (35.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  static unsigned int cpt = 0;
+  static float a = 1.0;
+  static float b = 1.0;
+  int d = 0;
+  float step;
+  float rad = (float) ((2 * M_PI * d) / 360);
+  float cosv = a * (float) cos (rad);
+  float sinv = b * (float) sin (rad);
+
+  if ((conf_private.wave_on_beat) && (beat))
+    jump[0] = conf_private.wave_height;
+
+
+  glBegin (GL_QUADS);
+  for (d = 0, step = 0; d < 360; d = d + conf_private.angle_step)
+    {
+      int l;
+      float rad2 = (float) ((2 * M_PI * (d + conf_private.angle_step)) / 360);
+      float cosv2 = a * (float) cos (rad2);
+      float sinv2 = b * (float) sin (rad2);
+
+      for (l = 0; l < 16; l++)
+	{
+	  int i;
+	  GLfloat red, green, blue;
+	  xz xz1, xz2, xz3, xz4;
+
+	  GLfloat y;
+	  GLfloat u = (float) (l * conf_private.interband * cosv);
+	  GLfloat v = (float) (l * conf_private.interband * sinv);
+	  GLfloat u2 = (float) (l * conf_private.interband * cosv2);
+	  GLfloat v2 = (float) (l * conf_private.interband * sinv2);
+
+	  xz1.x = u + (conf_private.radius + conf_private.linelength) * cosv;
+	  xz1.z = v + (conf_private.radius + conf_private.linelength) * sinv;
+	  xz2.x = u + conf_private.radius * cosv;
+	  xz2.z = v + conf_private.radius * sinv;
+	  xz3.x =
+	    u2 + (conf_private.radius + conf_private.linelength) * cosv2;
+	  xz3.z =
+	    v2 + (conf_private.radius + conf_private.linelength) * sinv2;
+	  xz4.x = u2 + conf_private.radius * cosv2;
+	  xz4.z = v2 + conf_private.radius * sinv2;
+
+	  // calculate the height of the bar
+	  // this makes a fade with the past drawn values
+	  for (i = 0, y = 0; i < conf_private.angle_step; i++)
+	    y += datas.data360[d + i][l];
+	  y /= (float) conf_private.angle_step;
+
+	  // get the color associated with the height of the bar
+	  if (y != 0.0)
+	    get_color (&red, &green, &blue, &y);
+	  else
+	    break;		// we draw nothing if the signal is null
+
+	  y *= 4;		// should be in the config ?
+
+	  if (conf_private.wave_on_beat)
+	    y += jump[l];
+
+	  switch (draw_mode)
+	    {
+	    case 1:
+	      // draw a bar
+	      {
+		glColor4f (red / 2, green / 2, blue / 2, 0.3);
+		bar_side (y, &xz1, &xz2);
+		bar_side (y, &xz3, &xz4);
+		bar_side (y, &xz1, &xz3);
+		bar_side (y, &xz2, &xz4);
+		if (jump[l])
+		  glColor4f (config.color_flash_red, config.color_flash_green,
+			     config.color_flash_blue, 0.3);
+		else
+		  glColor4f (red, green, blue, 0.3);
+		bar_top_or_bottom (y, &xz1, &xz2, &xz3, &xz4);
+
+		break;
+	      }
+	    case 2:
+	      // draw only the top of a bar
+	      {
+		if (jump[l])
+		  glColor4f (config.color_flash_red, config.color_flash_green,
+			     config.color_flash_blue, 0.3);
+		else
+		  glColor4f (red, green, blue, 0.3);
+		bar_top_or_bottom (y, &xz1, &xz2, &xz3, &xz4);
+
+		break;
+	      }
+	    case 3:
+	      // draw only a side of a bar
+	      {
+		if (jump[l])
+		  glColor4f (config.color_flash_red, config.color_flash_green,
+			     config.color_flash_blue, 0.3);
+		else
+		  glColor4f (red, green, blue, 0.3);
+		bar_side (y, &xz3, &xz4);
+
+		break;
+	      }
+	    case 4:
+	      //draw only another side of a bar
+	      {
+		if (jump[l])
+		  glColor4f (config.color_flash_red, config.color_flash_green,
+			     config.color_flash_blue, 0.3);
+		else
+		  glColor4f (red, green, blue, 0.3);
+		bar_side (y, &xz1, &xz3);
+
+		break;
+	      }
+
+	    }			// switch
+
+	}			// for(l=0
+
+      rad = rad2;
+      cosv = cosv2;
+      sinv = sinv2;
+
+    }				// for(d=0
+
+  if (!cpt)
+    {
+      shift_jump ();
+      cpt = conf_private.wave_timer;
+    }
+  cpt--;
+
+  glEnd ();
+
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_get_int (db, section_name, original_draw_mode, &conf_private.draw_mode);
+  bmp_cfg_db_get_int (db, section_name, original_angle_step, &conf_private.angle_step);
+  bmp_cfg_db_get_bool (db, section_name, original_wave_on_beat, &conf_private.wave_on_beat);
+  bmp_cfg_db_get_float (db, section_name, original_wave_height, &conf_private.wave_height);
+  bmp_cfg_db_get_int (db, section_name, original_wave_timer, &conf_private.wave_timer);
+  bmp_cfg_db_get_float (db, section_name, original_radius, &conf_private.radius);
+  bmp_cfg_db_get_float (db, section_name, original_interband, &conf_private.interband);
+  bmp_cfg_db_get_float (db, section_name, original_linelength, &conf_private.linelength);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_int (db, section_name, original_draw_mode, conf_private.draw_mode);
+  bmp_cfg_db_set_int (db, section_name, original_angle_step, conf_private.angle_step);
+  bmp_cfg_db_set_bool (db, section_name, original_wave_on_beat, conf_private.wave_on_beat);
+  bmp_cfg_db_set_float (db, section_name, original_wave_height, conf_private.wave_height);
+  bmp_cfg_db_set_int (db, section_name, original_wave_timer, conf_private.wave_timer);
+  bmp_cfg_db_set_float (db, section_name, original_radius, conf_private.radius);
+  bmp_cfg_db_set_float (db, section_name, original_interband, conf_private.interband);
+  bmp_cfg_db_set_float (db, section_name, original_linelength, conf_private.linelength);
+}
+
+
+static void
+config_default ()
+{
+  conf_private.draw_mode = 2;
+  conf_private.angle_step = 8;
+  conf_private.wave_on_beat = TRUE;
+  conf_private.wave_height = 0.5;
+  conf_private.wave_timer = 5;
+  conf_private.radius = 0.4;
+  conf_private.interband = 0.25;
+  conf_private.linelength = 0.11;
+}
+
+
+void
+jumpbeat_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.wave_on_beat = !conf_private_new.wave_on_beat;
+}
+
+
+static void
+value_jump_speed (GtkAdjustment * adj)
+{
+  conf_private_new.wave_timer = (int) adj->value;
+}
+
+
+static void
+config_create (GtkWidget * vbox)
+{
+  GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private_new));
+
+  /* wave on beat */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Wave on beats");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.wave_on_beat);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (jumpbeat_toggled), NULL);
+
+  /* number of frame for the wave to propagate */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Wave propagation timer (in frames)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.wave_timer, 1, 50, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_jump_speed), NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_pinwheel.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,407 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* New Theme created by Ron Lockwood-Childs
+ * Looks best when alpha blending is on
+ */
+
+/* $Id: theme_pinwheel.c,v 1.5 2002/05/16 20:38:17 cedric Exp $ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+#define NUM_PER_RING 8
+#define GAP (M_PI_4)
+
+#define RANDOM_HEIGHT_COUNTDOWN 60
+
+
+static struct
+{
+  gboolean height_random;
+  gfloat height_set;
+  gfloat height;
+  gfloat num_sections;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+
+
+static char pinwheel_numsec[] = "pinwheel_numsec";
+static char pinwheel_hrandom[] = "pinwheel_hrandom";
+static char pinwheel_hset[] = "pinwheel_hset";
+
+
+iris_theme theme_pinwheel = {
+  "PinWheel",
+  "A spectrum of pinwheels",
+  "Ron Lockwood-Childs",
+  "pinwheel",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+static time_t time_random = 0;	// timer for random height mode
+
+static GLfloat data2[NUM_BANDS];	// previous freq band data
+static GLfloat angle[NUM_BANDS];	// previous angle data
+static GLfloat radii[NUM_BANDS + 2] =
+  { 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f,
+  4.0f, 4.5f, 5.0f, 5.5f, 6.0f, 6.5f, 7.0f, 7.5f,
+  8.0f
+};
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (80.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+set_height (void)
+{
+  time_t cur_time = time (NULL);	// current time
+
+  if (conf_private.height_random)
+    {
+      /* we are in random height mode, see if it time to change height */
+      if (cur_time - time_random > RANDOM_HEIGHT_COUNTDOWN)
+	{
+	  /* generate float  1 <= x <= 3 */
+	  conf_private.height = ((gfloat) rand () * 2.0 / RAND_MAX) + 1.0;
+
+	  /* reset timer for when to generate new random height */
+	  time_random = time (NULL);
+	}
+    }
+  else
+    {
+      conf_private.height = conf_private.height_set;
+    }
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  int t1, t2;			// loop vars
+  GLfloat red, green, blue;
+  GLfloat z = 0.0;
+  GLfloat scaler = 2.0f;	// scales the whole field - lower is bigger
+  GLfloat scaleh;		// height of the bar - lower is smaller
+  GLfloat xin_up, zin_up, xin_dn, zin_dn, xot_up, zot_up, xot_dn, zot_dn;
+  GLfloat rin, rot;		// radius of inner and outer edges of p-gram
+  GLfloat angle_up, angle_dn;	// angles of top and bottom of p-gram
+  GLfloat differ;		// holds the angle increment
+  GLfloat maxdropoff = 0.05;	// smooth changes in heights
+  GLfloat angle_step;
+
+  /* update bar height (could be changing randomly over time) */
+  set_height ();
+  scaleh = conf_private.height;
+
+  /* internal routine to shift all data when a new datarow arrives */
+  for (t1 = 0; t1 < 16; t1++)
+    {
+      differ = data2[t1] - datas.data1[t1];
+      // Rotate counter c.w. if differ positive, c.w. if negative
+      angle[t1] += (differ * M_PI_4 / 3.0f);	// max angle change = +/- PI/12
+      if (angle[t1] > (2.0f * M_PI))
+	{			// cap angle at 360
+	  angle[t1] -= (2.0f * M_PI);
+	}
+      else if (angle[t1] < 0)
+	{			// keep angle positive
+	  angle[t1] += (2.0f * M_PI);
+	}
+
+      // smooth bar height changes
+      if (datas.data1[t1] > data2[t1])
+	{
+	  if ((datas.data1[t1] - data2[t1]) > maxdropoff)
+	    data2[t1] += maxdropoff;
+	  else
+	    data2[t1] += datas.data1[t1];
+	}
+      else if (datas.data1[t1] < data2[t1])
+	{
+	  if ((data2[t1] - datas.data1[t1]) > maxdropoff)
+	    data2[t1] -= maxdropoff;
+	  else
+	    data2[t1] -= datas.data1[t1];
+	}
+    }
+
+  glBegin (GL_QUADS);
+
+  for (t1 = 0; t1 < 16; t1++)
+    {				// iterate thru rings
+
+      // calculate inner and outer radius for this ring of p-grams
+      rin = (radii[t1 + 1] - ((radii[1] - radii[0]) / 2.0f)) / scaler;
+      rot = (radii[t1 + 1] + ((radii[1] - radii[0]) / 2.0f)) / scaler;
+      for (t2 = 0; t2 < conf_private.num_sections; t2++)
+	{			// iterate thru bars in a single ring
+
+	  angle_step =
+	    angle[t1] + (t2 * 2 * M_PI / conf_private.num_sections);
+	  if (angle_step > (M_PI * 2))
+	    angle_step -= (M_PI * 2);
+	  else if (angle_step < 0)
+	    angle_step += (M_PI * 2);
+	  // calculate upper and lower angles for this p-gram
+	  angle_up = angle_step + (M_PI_2 / 9.0f);
+	  angle_dn = angle_step - (M_PI_2 / 9.0f);
+	  // now figure out all the p-gram vertices
+	  xin_dn = cos (angle_dn) * rin;
+	  zin_dn = sin (angle_dn) * rin;
+	  xin_up = cos (angle_up) * rin;
+	  zin_up = sin (angle_up) * rin;
+	  xot_dn = cos (angle_dn) * rot;
+	  zot_dn = sin (angle_dn) * rot;
+	  xot_up = cos (angle_up) * rot;
+	  zot_up = sin (angle_up) * rot;
+
+	  // now start drawin'
+	  // start with the front, then left, back, right, finally the top
+
+	  // "front"
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_dn, data2[t1] * scaleh, zot_dn);	// "top-right"
+
+	  get_color (&red, &green, &blue, &z);	// bottom color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_dn, z, zot_dn);	// "bottom-right"
+	  glVertex3f (xin_dn, z, zin_dn);	// "bottom-left"
+
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xin_dn, data2[t1] * scaleh, zin_dn);	// "top-left"
+
+	  // "left"
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xin_dn, data2[t1] * scaleh, zin_dn);	// "top-out"
+
+	  get_color (&red, &green, &blue, &z);	// bottom color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xin_dn, z, zin_dn);	// "bottom-out"
+	  glVertex3f (xin_up, z, zin_up);	// "bottom-in"
+
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xin_up, data2[t1] * scaleh, zin_up);	// "top-in"
+
+	  // "back"
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xin_up, data2[t1] * scaleh, zin_up);	// "top-left"
+
+	  get_color (&red, &green, &blue, &z);	// bottom color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xin_up, z, zin_up);	// "bottom-left"
+	  glVertex3f (xot_up, z, zot_up);	// "bottom-right"
+
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_up, data2[t1] * scaleh, zot_up);	// "top-right"
+
+	  // "right"
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_up, data2[t1] * scaleh, zot_up);	// "top-in"
+
+	  get_color (&red, &green, &blue, &z);	// bottom color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_up, z, zot_up);	// "bottom-in"
+	  glVertex3f (xot_dn, z, zot_dn);	// "bottom-out"
+
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_dn, data2[t1] * scaleh, zot_dn);	// "top-out"
+
+	  // "top"
+	  get_color (&red, &green, &blue, &data2[t1]);	// top color
+	  glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	  glVertex3f (xot_dn, data2[t1] * scaleh, zot_dn);	// "out-right"
+	  glVertex3f (xin_dn, data2[t1] * scaleh, zin_dn);	// "out-left"
+	  glVertex3f (xin_up, data2[t1] * scaleh, zin_up);	// "in-left"
+	  glVertex3f (xot_up, data2[t1] * scaleh, zot_up);	// "in-right"
+
+	}
+    }
+
+  glEnd ();
+
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_get_float (db, section_name, pinwheel_numsec, &conf_private.num_sections);
+  bmp_cfg_db_get_bool (db, section_name, pinwheel_hrandom, &conf_private.height_random);
+  bmp_cfg_db_get_float (db, section_name, pinwheel_hset, &conf_private.height_set);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_float (db, section_name, pinwheel_numsec, conf_private.num_sections);
+  bmp_cfg_db_set_bool (db, section_name, pinwheel_hrandom, conf_private.height_random);
+  bmp_cfg_db_set_float (db, section_name, pinwheel_hset, conf_private.height_set);
+}
+
+
+static void
+config_default ()
+{
+  conf_private.num_sections = 8.0;
+  conf_private.height_random = FALSE;
+  conf_private.height_set = 2.0;
+  conf_private.height = 2.0;
+}
+
+
+static void
+sections_changed (GtkAdjustment * adj)
+{
+  conf_private_new.num_sections = (int) adj->value;
+}
+
+
+static void
+height_changed (GtkAdjustment * adj)
+{
+  conf_private_new.height_set = (int) adj->value;
+}
+
+
+static void
+height_toggled (GtkWidget * widget, GtkScale * height_scale)
+{
+  conf_private_new.height_random = !conf_private_new.height_random;
+  gtk_widget_set_sensitive (GTK_WIDGET (height_scale),
+			    !conf_private_new.height_random);
+}
+
+
+static void
+config_create (GtkWidget * vbox)
+{
+  GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private));
+
+  /* number sections per ring */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Number sections per ring");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.num_sections, 4, 20, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (sections_changed), NULL);
+
+  /* random max height */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Random height");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.height_random);
+
+  /* explicitly set max height */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Maximum height");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.height_set, 1, 3, 0.1, 1, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 1);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_set_sensitive (GTK_WIDGET (hscale),
+			    !conf_private_new.height_random);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (height_changed), NULL);
+
+  /* slider gets enabled/disabled according to random setting */
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (height_toggled), GTK_SCALE (hscale));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_pipes.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,368 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* New Theme created by Ron Lockwood-Childs
+ * Looks best when alpha blending is on
+ */
+
+/* $Id: theme_pipes.c,v 1.5 2002/05/16 20:38:17 cedric Exp $ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include <stdio.h>
+#include "iris.h"
+
+#define NUM_BANDS 16
+#define REPEAT 5
+#define CIRCLE_POINTS 12
+#define PIPE_DIAMETER 0.25f
+#define PIPE_THICKNESS 0.10f
+#define PIPE_ANGLE (45.0f / (float)NUM_BANDS)
+#define PIPE_RING_ANGLE (300.0f / (float)NUM_BANDS)
+#define PIPE_RING_RADIUS(side) (side / (2.0f * sin( PIPE_RING_ANGLE / 2.0f )))
+
+
+static struct
+{
+  gfloat slope;
+  gfloat length;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+
+
+static char pipes_slope[] = "pipes_slope";
+static char pipes_length[] = "pipes_length";
+
+
+iris_theme theme_pipes = {
+  "Pipes",
+  "Coral spectrum",
+  "Ron Lockwood-Childs",
+  "pipes",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+typedef struct
+{
+  GLfloat x_n;
+  GLfloat z_n;
+}
+rectangular;
+
+
+GLfloat data2[NUM_BANDS];	// previous freq band data
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (55.0 + (int) (35.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  int t1, t2, t3;		// loop vars
+  GLfloat red, green, blue;
+  GLfloat y = 0.0;
+//  GLfloat circumference;      // loop var around cylinder
+  // store each set of points around the center of the cylinder
+  rectangular outer_cylinder[CIRCLE_POINTS];	// each y, z around outer circle
+  rectangular inner_cylinder[CIRCLE_POINTS];	// each y, z around inner circle
+  rectangular ring_of_pipes[NUM_BANDS];	// for wrapping pipes in a circle
+  GLfloat differ;		// holds the angle increment
+  GLfloat maxdropoff = 0.05;	// smooth changes in heights
+  GLfloat angle_step;
+//  GLfloat adj_x;              // bar height adjustment
+  GLfloat repeat_index_adj;	// adj for repeating NUM_BANDS bars around spiral
+  int next_point;
+  static int first_time = 0;
+
+  for (t1 = 0, angle_step = 0;
+       t1 < CIRCLE_POINTS;
+       t1++, angle_step += ((M_PI * 2) / (float) CIRCLE_POINTS))
+    {				// get each point of each "circle" (more like a polygon)
+      outer_cylinder[t1].x_n = cos (angle_step) * (PIPE_DIAMETER / 2.0f);
+      outer_cylinder[t1].z_n = sin (angle_step) * (PIPE_DIAMETER / 2.0f);
+      inner_cylinder[t1].x_n = cos (angle_step) *
+	((PIPE_DIAMETER - PIPE_THICKNESS) / 2.0f);
+      inner_cylinder[t1].z_n = sin (angle_step) *
+	((PIPE_DIAMETER - PIPE_THICKNESS) / 2.0f);
+    }
+  for (t1 = 0; t1 < NUM_BANDS; t1++)
+    {
+      // smooth out the pipe length changes
+      differ = datas.data1[t1] - data2[t1];	// calculate change in amplitude
+      if (fabs (differ) > maxdropoff)
+	{
+	  if (differ > 0)
+	    data2[t1] += maxdropoff;
+	  else if (differ < 0)
+	    data2[t1] -= maxdropoff;
+	}
+      else
+	{
+	  data2[t1] += differ;
+	}
+      // work out the pipe placement
+      ring_of_pipes[t1].x_n = cos (t1 * PIPE_RING_ANGLE) * 2;
+      ring_of_pipes[t1].z_n = sin (t1 * PIPE_RING_ANGLE) * 2;
+    }
+
+  for (t3 = 0; t3 < REPEAT; t3++)
+    {
+      for (t1 = 0; t1 < NUM_BANDS; t1++)
+	{			// iterate thru each pipe
+
+	  glPushMatrix ();
+	  repeat_index_adj = t1 + (t3 * NUM_BANDS);
+	  // now alter the model view matrix to put the pipe in the right position
+	  glRotatef (PIPE_RING_ANGLE * repeat_index_adj, 0.0f, 0.5f, 0.0f);
+	  glTranslatef (0.5f + (0.05f * repeat_index_adj),
+			(conf_private.slope * repeat_index_adj), 0);
+	  glRotatef (-1 * PIPE_ANGLE * repeat_index_adj, 0.0f, 0.0f, 1.0f);
+
+	  glBegin (GL_QUADS);
+	  // draw each cylinder segment, from one end of the pipe to the other
+	  for (t2 = 0; t2 < CIRCLE_POINTS; t2++)
+	    {
+	      if (t2 >= (CIRCLE_POINTS - 1))
+		next_point = 0;
+	      else
+		next_point = t2 + 1;
+	      // current angle to angle + PI / # of points
+	      // can draw both inner and outer cylinder segments per angle
+	      // also: split pipe height so we can do 
+	      // color 2 -> color 1 -> color 2 along its height
+
+	      // top half of outer pipe segment
+	      get_color (&red, &green, &blue, &data2[t1]);	// top color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "top-left"
+	      glVertex3f (outer_cylinder[t2].x_n,
+			  data2[t1] * conf_private.length,
+			  outer_cylinder[t2].z_n);
+
+	      get_color (&red, &green, &blue, &y);	// bottom color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "middle-left"
+	      glVertex3f (outer_cylinder[t2].x_n,
+			  0.0f, outer_cylinder[t2].z_n);
+	      // "middle-right"
+	      glVertex3f (outer_cylinder[next_point].x_n,
+			  0.0f, outer_cylinder[next_point].z_n);
+
+	      get_color (&red, &green, &blue, &data2[t1]);	// top color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "top-right"
+	      glVertex3f (outer_cylinder[next_point].x_n,
+			  data2[t1] * conf_private.length,
+			  outer_cylinder[next_point].z_n);
+
+	      // top half of inner pipe segment
+	      get_color (&red, &green, &blue, &data2[t1]);	// top color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "top-left"
+	      glVertex3f (inner_cylinder[t2].x_n,
+			  data2[t1] * conf_private.length,
+			  inner_cylinder[t2].z_n);
+
+	      get_color (&red, &green, &blue, &y);	// bottom color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "middle-left"
+	      glVertex3f (inner_cylinder[t2].x_n,
+			  0.0f, inner_cylinder[t2].z_n);
+	      // "middle-right"
+	      glVertex3f (inner_cylinder[next_point].x_n,
+			  0.0f, inner_cylinder[next_point].z_n);
+
+	      get_color (&red, &green, &blue, &data2[t1]);	// top color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "top-right"
+	      glVertex3f (inner_cylinder[next_point].x_n,
+			  data2[t1] * conf_private.length,
+			  inner_cylinder[next_point].z_n);
+
+	      // now "cap" the ends of the pipe
+
+	      // cap "top" of pipe
+	      get_color (&red, &green, &blue, &data2[t1]);	// top color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "outer-bottom"
+	      glVertex3f (outer_cylinder[t2].x_n,
+			  data2[t1] * conf_private.length,
+			  outer_cylinder[t2].z_n);
+	      // "inner-bottom"
+	      glVertex3f (inner_cylinder[t2].x_n,
+			  data2[t1] * conf_private.length,
+			  inner_cylinder[t2].z_n);
+	      // "inner-top"
+	      glVertex3f (inner_cylinder[next_point].x_n,
+			  data2[t1] * conf_private.length,
+			  inner_cylinder[next_point].z_n);
+	      // "outer-top"
+	      glVertex3f (outer_cylinder[next_point].x_n,
+			  data2[t1] * conf_private.length,
+			  outer_cylinder[next_point].z_n);
+
+	      // cap "bottom" of pipe
+	      get_color (&red, &green, &blue, &y);	// bottom color
+	      glColor4f (red / 2.0f, green / 2.0f, blue / 2.0f, 0.5f);
+	      // "outer-bottom"
+	      glVertex3f (outer_cylinder[t2].x_n,
+			  0.0f, outer_cylinder[t2].z_n);
+	      // "inner-bottom"
+	      glVertex3f (inner_cylinder[t2].x_n,
+			  0.0f, inner_cylinder[t2].z_n);
+	      // "inner-top"
+	      glVertex3f (inner_cylinder[next_point].x_n,
+			  0.0f, inner_cylinder[next_point].z_n);
+	      // "outer-top"
+	      glVertex3f (outer_cylinder[next_point].x_n,
+			  0.0f, outer_cylinder[next_point].z_n);
+	    }
+	  glEnd ();		// specify each pipe separately
+	  glPopMatrix ();
+	}
+    }
+
+
+  first_time++;
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_get_float (db, section_name, pipes_slope, &conf_private.slope);
+  bmp_cfg_db_get_float (db, section_name, pipes_length, &conf_private.length);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_float (db, section_name, pipes_slope, conf_private.slope);
+  bmp_cfg_db_set_float (db, section_name, pipes_length, conf_private.length);
+}
+
+
+static void
+config_default ()
+{
+  conf_private.slope = -0.05;
+  conf_private.length = 1.5;
+}
+
+
+static void
+slope_changed (GtkAdjustment * adj)
+{
+  conf_private_new.slope = (float) adj->value;
+}
+
+
+static void
+length_changed (GtkAdjustment * adj)
+{
+  conf_private_new.length = (float) adj->value;
+}
+
+
+static void
+config_create (GtkWidget * vbox)
+{
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private));
+
+  /* slope in vertical direction */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Rate of descent/ascent (vertical slope)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.slope, -0.05, 0.05, 0.001, 0.01, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 2);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (slope_changed), NULL);
+
+  /* length of each pipe */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Pipe length");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.length, 0.5, 3.5, 0.1, 0.5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 1);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (length_changed), NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_pyramid.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,140 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+
+static struct
+{
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+
+iris_theme theme_pyramid = {
+  "Pyramid",
+  "Pyramid shaped spectrum",
+  "Marinus Schraal (foser@sesmar.eu.org)",
+  "pyramid",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (30.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  GLfloat scale = 2.0;		// scales the whole squares, higher is bigger
+  GLfloat x, height = -4, oldheight;
+  GLfloat red, green, blue;
+  static GLfloat data[16];	// where the spectrum values are stored
+  int l;
+
+  for (l = 0; l < 16; l++)
+    {
+      if (datas.data1[l] > data[l])
+	data[l] = datas.data1[l];
+      else
+	data[l] -= 0.015;
+      if (data[l] < 0.0)
+	data[l] = 0.0;
+    }
+
+  glBegin (GL_QUADS);
+  for (l = 0; l < 16; l++)
+    {
+      x = data[l] * scale;
+      oldheight = height;
+      height = height + 0.4;
+
+      if (data[l] > 0.0)
+	{
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red, green, blue, 0.75);
+
+	  /* sides */
+	  //top right
+	  glVertex3f (x, height, x);	// top right (front)
+	  glVertex3f (x, oldheight, x);	//bottom right
+	  glVertex3f (x, oldheight, -x);	//bottom left
+	  glVertex3f (x, height, -x);	// top left 
+	  //top left
+	  glVertex3f (x, height, -x);	// top right (front)
+	  glVertex3f (x, oldheight, -x);	//bottom right
+	  glVertex3f (-x, oldheight, -x);	//bottom left
+	  glVertex3f (-x, height, -x);	// top left 
+	  //bottom left
+	  glVertex3f (-x, height, -x);	// top right (front)
+	  glVertex3f (-x, oldheight, -x);	//bottom right
+	  glVertex3f (-x, oldheight, x);	//bottom left
+	  glVertex3f (-x, height, x);	// top left
+
+	  //bottom right
+	  glVertex3f (-x, height, x);	// top right (front)
+	  glVertex3f (-x, oldheight, x);	//bottom right
+	  glVertex3f (x, oldheight, x);	//bottom left
+	  glVertex3f (x, height, x);	// top left
+
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red, green, blue, 0.5);
+	  /* top */
+	  glVertex3f (x, height, x);	// Top Right Of The Quad (Bottom)
+	  glVertex3f (x, height, -x);	// Top Left Of The Quad (Bottom)
+	  glVertex3f (-x, height, -x);	// Bottom Left Of The Quad (Bottom)
+	  glVertex3f (-x, height, x);	// Bottom Right Of The Quad (Bottom)
+
+	}
+    }
+
+  glEnd ();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_spectrotoy.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,165 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+static struct
+{
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+
+iris_theme theme_spectrotoy = {
+  "Spectrotoy",
+  "Seashell shaped spectrum",
+  "Cédric Delfosse (cdelfosse@free.fr)",
+  "spectrotoy",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (65.0 + (int) (25.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  unsigned int step;
+  GLfloat x1, x2, y1, y2, x3, y3, x4, y4;
+  GLfloat y;
+  GLfloat red, green, blue;
+  static GLfloat data[16];	// where the spectrum values are stored
+
+  for (step = 0; step < 16; step++)
+    {
+      if (datas.data1[step] > data[step])
+	data[step] = datas.data1[step];
+      else
+	data[step] -= 0.02;
+      if (data[step] < 0.0)
+	data[step] = 0.0;
+    }
+  data[16] = data[0];
+
+  glBegin (GL_TRIANGLES);
+
+  x1 = 0.5 * cos (0);
+  y1 = 0.5 * sin (0);
+
+  x2 = (0.5 + data[0] * 3) * cos (0);
+  y2 = (0.5 + data[0] * 3) * sin (0);
+
+  for (step = 0; step < 17; step++)
+    {
+      y = data[step] * 3;
+
+      x3 = 0.5 * cos (step * 2 * M_PI / 16);
+      y3 = 0.5 * sin (step * 2 * M_PI / 16);
+
+      x4 = (0.5 + y) * cos (step * 2 * M_PI / 16);
+      y4 = (0.5 + y) * sin (step * 2 * M_PI / 16);
+
+      get_color (&red, &green, &blue, &data[step]);
+
+      /* a side */
+      glColor4f (red / 2, green / 2, blue / 2, 0.5);
+      glVertex3f (x1, 0, y1);
+      glVertex3f (x2, 0, y2);
+      glVertex3f (x2, y, y2);
+      glVertex3f (x2, y, y2);
+      glVertex3f (x1, y, y1);
+      glVertex3f (x1, 0, y1);
+
+      /* another side */
+      glColor4f (red / 2, green / 2, blue / 2, 0.5);
+      glVertex3f (x3, 0, y3);
+      glVertex3f (x4, 0, y4);
+      glVertex3f (x4, y, y4);
+      glVertex3f (x4, y, y4);
+      glVertex3f (x3, y, y3);
+      glVertex3f (x3, 0, y3);
+
+      /* side in */
+      glColor4f (red / 2, green / 2, blue / 2, 0.5);
+      glVertex3f (x1, 0, y1);
+      glVertex3f (x3, 0, y3);
+      glVertex3f (x3, y, y3);
+      glVertex3f (x3, y, y3);
+      glVertex3f (x1, y, y1);
+      glVertex3f (x1, 0, y1);
+
+      /* side out */
+      glColor4f (red / 2, green / 2, blue / 2, 0.5);
+      glVertex3f (x4, 0, y4);
+      glVertex3f (x2, 0, y2);
+      glVertex3f (x2, y, y2);
+      glVertex3f (x2, y, y2);
+      glVertex3f (x4, y, y4);
+      glVertex3f (x4, 0, y4);
+
+      /* top */
+      glColor4f (red, green, blue, 0.5);
+      glVertex3f (x1, y, y1);
+      glVertex3f (x2, y, y2);
+      glVertex3f (x3, y, y3);
+      glVertex3f (x3, y, y3);
+      glVertex3f (x2, y, y2);
+      glVertex3f (x4, y, y4);
+
+      x1 = x3;
+      y1 = y3;
+      x2 = x4;
+      y2 = y4;
+    }
+
+  glEnd ();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_spectrum.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,278 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+
+static char spectrum_proportional[] = "spectrum_proportional";
+
+static GLfloat peak[16];	// where the peak values are stored
+
+static struct
+{
+  gboolean proportional;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+static void init_draw_mode (void);
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+
+iris_theme theme_spectrum = {
+  "Spectrum",
+  "A simple spectrum",
+  "Cédric Delfosse (cdelfosse@free.fr)",
+  "spectrum",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  init_draw_mode,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+static void
+init_draw_mode ()
+{
+  memset (peak, 0x00, 16);
+}
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (80.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  GLfloat x1, x2;
+  GLfloat bar_length = 0.30;
+  GLfloat bar_distance = 0.1;
+  GLfloat bar_deep = 1.5;
+  GLfloat y, y2;
+  GLfloat red, green, blue;
+  GLfloat z = 0.0;
+  static GLfloat data[16];	// where the spectrum values are stored
+  int l;
+
+  for (l = 0; l < 16; l++)
+    {
+      if (datas.data1[l] > data[l])
+	data[l] = datas.data1[l];
+      else
+	data[l] -= 0.015;
+      if (data[l] < 0.0)
+	data[l] = 0.0;
+    }
+
+  glBegin (GL_TRIANGLES);
+
+  x1 = -(bar_length * 16.0 + bar_distance * 15.0) / 2.0;
+  x2 = x1 + bar_length;
+
+  for (l = 0; l < 16; l++)
+    {
+      GLfloat width;
+      y = data[l] * 4;
+
+      if (peak[l] < data[l])
+	{
+	  peak[l] = data[l];
+	  if (beat)
+	    peak[l] += 0.2;
+	}
+      else
+	peak[l] -= 0.007;
+      if (conf_private.proportional)
+	width = peak[l];
+      else
+	width = bar_deep / 2;
+      if (peak[l] < 0.0)
+	peak[l] = 0.0;
+      else
+	{
+	  y2 = peak[l] * 4 + 0.1;
+	  get_color (&red, &green, &blue, &peak[l]);
+	  glColor4f (red * 1.5, green * 1.5, blue * 1.5, 0.8);
+	  glVertex3f (x1, y2, -width);
+	  glVertex3f (x2, y2, -width);
+	  glVertex3f (x2, y2, +width);
+	  glVertex3f (x2, y2, +width);
+	  glVertex3f (x1, y2, -width);
+	  glVertex3f (x1, y2, +width);
+	}
+
+      if (y > 0.0)
+	{
+	  /* one side */
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1, y, -width);
+	  glVertex3f (x2, y, -width);
+
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1, 0, -width);
+	  glVertex3f (x1, 0, -width);
+	  glVertex3f (x2, 0, -width);
+
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x2, y, -width);
+
+	  /* top */
+	  glColor4f (red, green, blue, 0.5);
+	  glVertex3f (x1, y, -width);
+	  glVertex3f (x2, y, -width);
+	  glVertex3f (x2, y, +width);
+	  glVertex3f (x2, y, +width);
+	  glVertex3f (x1, y, -width);
+	  glVertex3f (x1, y, +width);
+
+	  /* other side */
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1, y, width);
+	  glVertex3f (x2, y, width);
+
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1, 0, width);
+	  glVertex3f (x1, 0, width);
+	  glVertex3f (x2, 0, width);
+
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x2, y, width);
+
+	   /**/ glVertex3f (x1, y, +width);
+	  glVertex3f (x1, y, -width);
+
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1, 0, -width);
+
+	  glVertex3f (x1, 0, -width);
+	  glVertex3f (x1, 0, +width);
+
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1, y, +width);
+
+	   /**/ glVertex3f (x2, y, +width);
+	  glVertex3f (x2, y, -width);
+
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x2, 0, -width);
+
+	  glVertex3f (x2, 0, -width);
+	  glVertex3f (x2, 0, +width);
+
+	  get_color (&red, &green, &blue, &data[l]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x2, y, +width);
+	}
+
+      x1 += bar_length + bar_distance;
+      x2 += bar_length + bar_distance;
+
+    }
+
+  glEnd ();
+
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_get_bool (db, section_name, spectrum_proportional, &conf_private.proportional);
+}
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_bool (db, section_name, spectrum_proportional, conf_private.proportional);
+}
+
+static void
+config_default ()
+{
+  conf_private.proportional = TRUE;
+}
+
+
+static void
+proportional_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.proportional = !conf_private_new.proportional;
+}
+
+
+static void
+config_create (GtkWidget * vbox)
+{
+  GtkWidget *hbox;
+  GtkWidget *button;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private_new));
+
+  /* proportional mode */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Proportional mode");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.proportional);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (proportional_toggled), NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_squarefield.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,192 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+
+static struct
+{
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+
+iris_theme theme_squarefield = {
+  "SquareField",
+  "Waving square field",
+  "Marinus Schraal (foser@sesmar.eu.org)",
+  "squarefield",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+GLfloat dataSquare[NUM_BANDS][NUM_BANDS];	// internal sounddata structure
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (80.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  int t1, t2;			// loop vars
+  GLfloat x1, y1;
+  GLfloat red, green, blue;
+  GLfloat z = 0.0;
+  GLfloat scale = 4.5;		// scales the whole field - lower is bigger
+  GLfloat scaleh = 3;		// scales height of the bar - lower is smaller
+  GLfloat maxfalloff = 0.05;
+
+  /* internal routine to shift all data when a new datarow arrives */
+  for (t1 = 15; t1 > 0; t1--)
+    {
+      for (t2 = 0; t2 < 16; t2++)
+	{
+	  dataSquare[t1][t2] = dataSquare[t1 - 1][t2];
+	}
+    }
+  for (t2 = 0; t2 < 16; t2++)
+    {
+      if (dataSquare[0][t2] > datas.data1[t2]
+	  && ((dataSquare[0][t2] - datas.data1[t2]) > maxfalloff))
+	{
+	  dataSquare[0][t2] = dataSquare[0][t2] - maxfalloff;
+	}
+      else
+	{
+	  dataSquare[0][t2] = datas.data1[t2];
+	}
+    }
+
+  /* some kinda random base i started out on
+     turned out to be too big thats why i added scaling vars
+   */
+  x1 = 11.75f;
+  y1 = 11.75f;
+
+  glBegin (GL_QUADS);
+
+  for (t1 = 0; t1 < 16; t1++)
+    {
+      x1 = 11.75f;
+      for (t2 = 0; t2 < 16; t2++)
+	{
+	  /* bottom : turned off */
+
+/*			get_color (&red, &green, &blue, &z);
+			glColor4f (red/2 , green/2 , blue/2 , 0.5); 
+			glVertex3f( (x1-1)/scale , 0, (y1-1)/scale);			// Top Right Of The Quad (Bottom)
+			glVertex3f( x1/scale, 0, (y1-1)/scale);			// Top Left Of The Quad (Bottom)
+			glVertex3f( x1/scale, 0, y1/scale);			// Bottom Left Of The Quad (Bottom)
+			glVertex3f( (x1-1)/scale, 0, y1/scale);			// Bottom Right Of The Quad (Bottom)
+*/
+
+	  /* sides */
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2] * scaleh, (y1 - 1) / scale);	// top right (front)
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, 0, (y1 - 1) / scale);	//bottom right
+	  glVertex3f (x1 / scale, 0, (y1 - 1) / scale);	//bottom left
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, (y1 - 1) / scale);	// top left
+
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, (y1 - 1) / scale);	// top fron (left)
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1 / scale, 0, (y1 - 1) / scale);	// bottom fron (left)
+	  glVertex3f (x1 / scale, 0, y1 / scale);	// back bottom (left)
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// top back (left)
+
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2] * scaleh, (y1 - 1) / scale);	// top front (right)
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, 0, (y1 - 1) / scale);	// bottom front (right)
+	  glVertex3f ((x1 - 1) / scale, 0, y1 / scale);	// bottom back (right)
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// top back(right)
+
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// right top (back)
+	  get_color (&red, &green, &blue, &z);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f ((x1 - 1) / scale, 0, y1 / scale);	// right bottom (back)
+	  glVertex3f (x1 / scale, 0, y1 / scale);	// left bottom (back)
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red / 2, green / 2, blue / 2, 0.5);
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// left top (back)
+
+	  /* top */
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red, green, blue, 0.5);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2] * scaleh, (y1 - 1) / scale);	// Top Right Of The Quad (Bottom)
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, (y1 - 1) / scale);	// Top Left Of The Quad (Bottom)
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// Bottom Left Of The Quad (Bottom)
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// Bottom Right Of The Quad (Bottom)
+
+	  x1 -= 1.5;
+	}
+      y1 -= 1.5;
+    }
+
+  glEnd ();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_waves.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,160 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+
+
+static struct
+{
+  gboolean proportional;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  NULL,
+  &conf_private_new
+};
+
+
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+
+iris_theme theme_waves = {
+  "Waves",
+  "Pulsating waves",
+  "Marinus Schraal (foser@sesmar.eu.org)",
+  "waves",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  get_x_angle,
+  draw_one_frame,
+};
+
+
+GLfloat dataSquare[NUM_BANDS][NUM_BANDS];	// internal sounddata structure
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (10.0 + (int) (80.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+
+static void
+draw_one_frame (gboolean beat)
+{
+  int t1, t2;			// loop vars
+  GLfloat x1, y1;
+  GLfloat red, green, blue;
+  GLfloat scale = 3;		// scales the whole field - lower is bigger
+  GLfloat scaleh = 2.5;		// scales height of the bar - lower is smaller
+  GLfloat maxfalloff = 0.05;
+  GLfloat intensity = 0.5;
+
+  /* internal routine to shift all data when a new datarow arrives */
+  for (t1 = 15; t1 > 0; t1--)
+    {
+      for (t2 = 0; t2 < 16; t2++)
+	{
+	  dataSquare[t1][t2] = dataSquare[t1 - 1][t2];
+	}
+    }
+  for (t2 = 0; t2 < 16; t2++)
+    {
+      if (dataSquare[0][t2] > datas.data1[t2]
+	  && ((dataSquare[0][t2] - datas.data1[t2]) > maxfalloff))
+	{
+	  dataSquare[0][t2] = dataSquare[0][t2] - maxfalloff;
+	}
+      else
+	{
+	  dataSquare[0][t2] = datas.data1[t2];
+	}
+    }
+
+  /* some kinda random base i started out on
+   * turned out to be too big thats why i added scaling vars
+   */
+  x1 = 7.5f;
+  y1 = 7.5f;
+
+  for (t1 = 0; t1 < 15; t1++)
+    {
+      x1 = 7.5f;
+      for (t2 = 0; t2 < 15; t2++)
+	{
+
+	  glBegin (GL_TRIANGLES);
+	  intensity = 0.75;
+
+	  /* triangle 1 */
+	  get_color (&red, &green, &blue, &dataSquare[t1 + 1][t2 + 1]);
+	  glColor4f (red, green, blue, intensity);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1 + 1][t2 + 1] * scaleh, (y1 - 1) / scale);	// Top Right Of The Quad (Bottom)
+
+	  get_color (&red, &green, &blue, &dataSquare[t1 + 1][t2]);
+	  glColor4f (red, green, blue, intensity);
+	  glVertex3f (x1 / scale, dataSquare[t1 + 1][t2] * scaleh, (y1 - 1) / scale);	// Top Left Of The Quad (Bottom)
+
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red, green, blue, intensity);
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// Bottom Left Of The Quad (Bottom)
+
+	  /* triangle 2 */
+	  get_color (&red, &green, &blue, &dataSquare[t1 + 1][t2 + 1]);
+	  glColor4f (red, green, blue, intensity);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1 + 1][t2 + 1] * scaleh, (y1 - 1) / scale);	// Top Right Of The Quad (Bottom)
+
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2 + 1]);
+	  glColor4f (red, green, blue, intensity);
+	  glVertex3f ((x1 - 1) / scale, dataSquare[t1][t2 + 1] * scaleh, y1 / scale);	// Bottom Right Of The Quad (Bottom)
+
+	  get_color (&red, &green, &blue, &dataSquare[t1][t2]);
+	  glColor4f (red, green, blue, intensity);
+	  glVertex3f (x1 / scale, dataSquare[t1][t2] * scaleh, y1 / scale);	// Bottom Left Of The Quad (Bottom)
+
+	  glEnd ();
+
+	  x1 -= 1;
+	}
+      y1 -= 1;
+    }
+
+  glEnd ();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/transition.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,184 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2000-2002 Cédric DELFOSSE (cdelfosse@free.fr)
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Transitions on theme change
+ * TODO : transitions on song change
+ * new transitions are easy to add
+ */
+
+#include <stdlib.h>
+#include "iris.h"
+
+extern GLfloat y_angle;
+extern GLfloat x_angle;
+extern int max_transition_frames;
+extern int transition_frames;
+int transition = 0;
+
+void
+trans_zoom_out (gboolean init)
+{
+  static GLfloat x, y, z;
+  //only init when starting transition
+  if (init)
+    {
+      x = 1.0;
+      y = 1.0;
+      z = 1.0;
+      return;
+    }
+
+  if (max_transition_frames / 2 < transition_frames)
+    {
+      x -= 1.0 / (max_transition_frames / 2);
+      y -= 1.0 / (max_transition_frames / 2);
+      z -= 1.0 / (max_transition_frames / 2);
+    }
+  else
+    {
+      x += 1.0 / (max_transition_frames / 2);
+      y += 1.0 / (max_transition_frames / 2);
+      z += 1.0 / (max_transition_frames / 2);
+    }
+
+  glScalef (x, y, z);
+}
+
+void
+trans_zoom_in (gboolean init)
+{
+  static GLfloat x, y, z;
+  //only init when starting transition
+  if (init)
+    {
+      x = 1.0;
+      y = 1.0;
+      z = 1.0;
+      return;
+    }
+
+  if (max_transition_frames / 2 < transition_frames)
+    {
+      x += 5.0 / (max_transition_frames / 2);
+      y += 5.0 / (max_transition_frames / 2);
+      z += 5.0 / (max_transition_frames / 2);
+    }
+  else
+    {
+      x -= 5.0 / (max_transition_frames / 2);
+      y -= 5.0 / (max_transition_frames / 2);
+      z -= 5.0 / (max_transition_frames / 2);
+    }
+
+  glScalef (x, y, z);
+}
+
+/* move up to top down look */
+void
+trans_vertical_view (gboolean init)
+{
+  static GLfloat x_angle_tmp;
+  if (init)
+    {
+      x_angle_tmp = x_angle;
+    }
+  if (max_transition_frames / 2 < transition_frames)
+    {
+      x_angle += (90.0 - x_angle_tmp) / (max_transition_frames / 2);
+    }
+  else
+    {
+      x_angle -= (90.0 - x_angle_tmp) / (max_transition_frames / 2);
+    }
+
+}
+
+void
+trans_spin_half_and_back (gboolean cc)
+{
+  if (max_transition_frames / 2 < transition_frames)
+    {
+      if (cc)
+	y_angle -= 180.0 / (max_transition_frames / 2);
+      else
+	y_angle += 180.0 / (max_transition_frames / 2);
+    }
+  else
+    {
+      if (cc)
+	y_angle += 180.0 / (max_transition_frames / 2);
+      else
+	y_angle -= 180.0 / (max_transition_frames / 2);
+    }
+}
+
+void
+trans_spin_full (gboolean cc)
+{
+  if (cc)
+    y_angle -= 360.0 / max_transition_frames;
+  else
+    y_angle += 360.0 / max_transition_frames;
+}
+
+/* called on themeswitch */
+void
+init_theme_transition (void)
+{
+  /* don't forget to update after adding new transitions */
+  transition = (int) ((gfloat) 6 * rand () / (RAND_MAX + 1.0));
+
+  /* init/reset transitions that need it */
+  trans_zoom_in (TRUE);
+  trans_zoom_out (TRUE);
+  trans_vertical_view (TRUE);
+}
+
+/* called every frame of a transition */
+void
+theme_transition ()
+{
+  switch (transition)
+    {
+    case 0:
+      trans_zoom_out (FALSE);
+      break;
+    case 1:
+      trans_zoom_out (FALSE);
+      trans_spin_half_and_back ((int)
+				((gfloat) 1 * rand () / (RAND_MAX + 1.0)));
+      break;
+    case 2:
+      trans_zoom_in (FALSE);
+      break;
+    case 3:
+      trans_zoom_in (FALSE);
+      trans_spin_half_and_back ((int)
+				((gfloat) 1 * rand () / (RAND_MAX + 1.0)));
+      break;
+    case 4:
+      trans_vertical_view (FALSE);
+      trans_zoom_in (FALSE);
+      break;
+    case 5:
+      trans_vertical_view (FALSE);
+      trans_zoom_in (FALSE);
+      trans_spin_full ((int) ((gfloat) 1 * rand () / (RAND_MAX + 1.0)));
+      break;
+    }
+}