Mercurial > audlegacy-plugins
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; + } +}