Mercurial > audlegacy-plugins
diff src/iris/theme_pinwheel.c @ 116:a578bf9b2851 trunk
[svn] - iris vis plugin port
author | nenolod |
---|---|
date | Tue, 24 Oct 2006 21:25:31 -0700 |
parents | |
children |
line wrap: on
line diff
--- /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)); +}