changeset 1507:0c5fdcf3f947 trunk

[svn] - incomplete stuff
author nenolod
date Sun, 06 Aug 2006 01:53:29 -0700
parents 2a8e193c07a6
children 2e1e5dae8f4c
files ChangeLog Plugins/Visualization/paranormal/pn/Makefile Plugins/Visualization/paranormal/pn/pn.h Plugins/Visualization/paranormal/pn/pnactuator.c Plugins/Visualization/paranormal/pn/pnactuator.h Plugins/Visualization/paranormal/pn/pnactuatorfactory.c Plugins/Visualization/paranormal/pn/pnactuatorfactory.h Plugins/Visualization/paranormal/pn/pnactuatorlist.c Plugins/Visualization/paranormal/pn/pnactuatorlist.h Plugins/Visualization/paranormal/pn/pnaudiodata.c Plugins/Visualization/paranormal/pn/pnaudiodata.h Plugins/Visualization/paranormal/pn/pnblur.c Plugins/Visualization/paranormal/pn/pnblur.h Plugins/Visualization/paranormal/pn/pnbooleanoption.c Plugins/Visualization/paranormal/pn/pnbooleanoption.h Plugins/Visualization/paranormal/pn/pnbuiltins.c Plugins/Visualization/paranormal/pn/pnbuiltins.h Plugins/Visualization/paranormal/pn/pnconfig.h Plugins/Visualization/paranormal/pn/pncontainer.c Plugins/Visualization/paranormal/pn/pncontainer.h Plugins/Visualization/paranormal/pn/pncpu.c Plugins/Visualization/paranormal/pn/pncpu.h Plugins/Visualization/paranormal/pn/pndisplacement.c Plugins/Visualization/paranormal/pn/pndisplacement.h Plugins/Visualization/paranormal/pn/pndistortion.c Plugins/Visualization/paranormal/pn/pndistortion.h Plugins/Visualization/paranormal/pn/pnerror.c Plugins/Visualization/paranormal/pn/pnerror.h Plugins/Visualization/paranormal/pn/pnflip.c Plugins/Visualization/paranormal/pn/pnflip.h Plugins/Visualization/paranormal/pn/pnfloatoption.c Plugins/Visualization/paranormal/pn/pnfloatoption.h Plugins/Visualization/paranormal/pn/pngtk.h Plugins/Visualization/paranormal/pn/pnimage.c Plugins/Visualization/paranormal/pn/pnimage.h Plugins/Visualization/paranormal/pn/pnimagecontext.c Plugins/Visualization/paranormal/pn/pnimagecontext.h Plugins/Visualization/paranormal/pn/pninit.c Plugins/Visualization/paranormal/pn/pninit.h Plugins/Visualization/paranormal/pn/pnintegeroption.c Plugins/Visualization/paranormal/pn/pnintegeroption.h Plugins/Visualization/paranormal/pn/pnlistoption.c Plugins/Visualization/paranormal/pn/pnlistoption.h Plugins/Visualization/paranormal/pn/pnobject.c Plugins/Visualization/paranormal/pn/pnobject.h Plugins/Visualization/paranormal/pn/pnoption.c Plugins/Visualization/paranormal/pn/pnoption.h Plugins/Visualization/paranormal/pn/pnoptionwidget.h Plugins/Visualization/paranormal/pn/pnrotozoom.c Plugins/Visualization/paranormal/pn/pnrotozoom.h Plugins/Visualization/paranormal/pn/pnscope.c Plugins/Visualization/paranormal/pn/pnscope.h Plugins/Visualization/paranormal/pn/pnscript.c Plugins/Visualization/paranormal/pn/pnscript.h Plugins/Visualization/paranormal/pn/pnscriptparser.y Plugins/Visualization/paranormal/pn/pnstringoption.c Plugins/Visualization/paranormal/pn/pnstringoption.h Plugins/Visualization/paranormal/pn/pnsymboltable.c Plugins/Visualization/paranormal/pn/pnsymboltable.h Plugins/Visualization/paranormal/pn/pntestactuator.c Plugins/Visualization/paranormal/pn/pntestactuator.h Plugins/Visualization/paranormal/pn/pnuserobject.c Plugins/Visualization/paranormal/pn/pnuserobject.h Plugins/Visualization/paranormal/pn/pnvis.c Plugins/Visualization/paranormal/pn/pnvis.h Plugins/Visualization/paranormal/pn/pnxml.h
diffstat 65 files changed, 9821 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Aug 05 23:43:14 2006 -0700
+++ b/ChangeLog	Sun Aug 06 01:53:29 2006 -0700
@@ -1,3 +1,12 @@
+2006-08-06 06:43:14 +0000  Stephen Sokolow <deitarion@gmail.com>
+  revision [1926]
+  Fix the test for whether a notification is necessary
+  
+
+  Changes:        Modified:
+  +3 -3           trunk/Plugins/General/notify/notify.c  
+
+
 2006-08-06 05:55:11 +0000  William Pitcock <nenolod@nenolod.net>
   revision [1924]
   - fix!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/Makefile	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,44 @@
+include ../../../../mk/rules.mk
+include ../../../../mk/objective.mk
+
+OBJECTIVE_LIBS_NOINST = libparanormal.a
+
+OBJECT_CFLAGS   = $(GTK_CFLAGS)
+OBJECT_LIBS     = $(GTK_LIBS)
+
+CFLAGS += -fPIC -DPIC -Wall -g -I../../../.. $(OBJECT_CFLAGS) $(XML_CFLAGS) -I..
+LIBADD   = -lm $(OBJECT_LIBS) $(XML_LIBS)
+
+SOURCES =  \
+	pnactuator.c        \
+	pnactuatorfactory.c \
+	pnactuatorlist.c    \
+	pnaudiodata.c       \
+	pnblur.c            \
+	pnbooleanoption.c   \
+	pnbuiltins.c        \
+	pncontainer.c       \
+	pncpu.c             \
+	pndisplacement.c    \
+	pndistortion.c      \
+	pnerror.c           \
+	pnflip.c            \
+	pnfloatoption.c     \
+	pnimage.c           \
+	pnimagecontext.c    \
+	pninit.c            \
+	pnintegeroption.c   \
+	pnlistoption.c      \
+	pnobject.c          \
+	pnoption.c          \
+	pnrotozoom.c        \
+	pnscope.c           \
+	pnscript.c          \
+	pnscriptparser.y    \
+	pnstringoption.c    \
+	pnsymboltable.c     \
+	pntestactuator.c    \
+	pnuserobject.c      \
+	pnvis.c             
+
+OBJECTS = ${SOURCES:.c=.o}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pn.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,55 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_H__
+#define __PN_H__
+
+#include "pnactuator.h"
+#include "pnactuatorfactory.h"
+#include "pnactuatorlist.h"
+#include "pnaudiodata.h"
+#include "pnblur.h"
+#include "pnbooleanoption.h"
+#include "pnbuiltins.h"
+#include "pncontainer.h"
+#include "pncpu.h"
+#include "pndisplacement.h"
+#include "pndistortion.h"
+#include "pnerror.h"
+#include "pnflip.h"
+#include "pnfloatoption.h"
+#include "pngtk.h"
+#include "pnimage.h"
+#include "pnimagecontext.h"
+#include "pninit.h"
+#include "pnintegeroption.h"
+#include "pnlistoption.h"
+#include "pnobject.h"
+#include "pnoption.h"
+#include "pnoptionwidget.h"
+#include "pnrotozoom.h"
+#include "pnscope.h"
+#include "pnscript.h"
+#include "pnstringoption.h"
+#include "pnsymboltable.h"
+#include "pntestactuator.h"
+#include "pnuserobject.h"
+#include "pnvis.h"
+#include "pnxml.h"
+
+#endif /* __PN_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnactuator.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,312 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pnactuator.h"
+#include "pnerror.h"
+
+static void         pn_actuator_class_init       (PnActuatorClass *class);
+static void         pn_actuator_init             (PnActuator *actuator,
+						  PnActuatorClass *class);
+
+/* GObject signals */
+static void         pn_actuator_finalize         (GObject *gobject);
+
+/* PnObject signals */
+static void         pn_actuator_destroy          (PnObject *object);
+
+/* PnUserObject methods */
+static void         pn_actuator_save_thyself     (PnUserObject *user_object,
+						  xmlNodePtr node);
+static void         pn_actuator_load_thyself     (PnUserObject *user_object,
+						  xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_actuator_get_type (void)
+{
+  static GType actuator_type = 0;
+
+  if (! actuator_type)
+    {
+      static const GTypeInfo actuator_info =
+      {
+	sizeof (PnActuatorClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_actuator_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnActuator),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_actuator_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      actuator_type = g_type_register_static (PN_TYPE_USER_OBJECT,
+					      "PnActuator",
+					      &actuator_info,
+					      G_TYPE_FLAG_ABSTRACT);
+    }
+  return actuator_type;
+}
+
+static void
+pn_actuator_class_init (PnActuatorClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+
+  /* GObject signals */
+  gobject_class->finalize = pn_actuator_finalize;
+
+  /* PnObject signals */
+  object_class->destroy = pn_actuator_destroy;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_actuator_save_thyself;
+  user_object_class->load_thyself = pn_actuator_load_thyself;
+}
+
+static void
+pn_actuator_init (PnActuator *actuator, PnActuatorClass *class)
+{
+  actuator->options = g_array_new (FALSE, FALSE, sizeof (PnOption *));
+}
+
+static void
+pn_actuator_destroy (PnObject *object)
+{
+  PnActuator *actuator = (PnActuator *) object;
+  gint i;
+
+  for (i=0; i < actuator->options->len; i++)
+    pn_object_unref (g_array_index (actuator->options, PnObject *, i));
+}
+
+static void
+pn_actuator_finalize (GObject *gobject)
+{
+  PnActuator *actuator = (PnActuator *) gobject;
+
+  g_array_free (actuator->options, FALSE);
+
+  if (G_OBJECT_CLASS (parent_class)->finalize)
+    G_OBJECT_CLASS (parent_class)->finalize (gobject);
+}
+
+static void
+pn_actuator_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnActuator *actuator;
+  gint i;
+  xmlNodePtr options_node, option_node;
+  PnOption *option;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (user_object));
+  g_return_if_fail (node != NULL);
+
+  actuator = (PnActuator *) user_object;
+
+  options_node = xmlNewChild (node, NULL, "Options", NULL);
+
+  /* Save all the options  */
+  for (i=0; i < actuator->options->len; i++)
+    {
+      option = g_array_index (actuator->options, PnOption *, i);
+      option_node = xmlNewChild (options_node, NULL, "BUG",  NULL);
+      pn_user_object_save_thyself (PN_USER_OBJECT (option), option_node);
+    }
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_actuator_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnActuator *actuator;
+  xmlNodePtr options_node, option_node;
+  PnOption *option;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (user_object));
+  g_return_if_fail (node != NULL);
+
+  actuator = (PnActuator *) user_object;
+
+  /* FIXME: should these 'xmlChildrenNode' be 'xmlRootNode'? */
+
+  /* find the 'options' node */
+  for (options_node = node->xmlChildrenNode; options_node; options_node = options_node->next)
+    if (g_strcasecmp (options_node->name, "Options") == 0)
+      break;
+
+  /* load each of the options */
+  if (options_node)
+    {
+      for (option_node = options_node->xmlChildrenNode; option_node; option_node = option_node->next)
+	{
+	  option = pn_actuator_get_option_by_name (actuator, option_node->name);
+	  if (option)
+	    pn_user_object_load_thyself (PN_USER_OBJECT (option), option_node);
+	  else
+	    pn_error ("unknown actuator option ecountered in actuator \"%s\": %s",
+		      node->name,
+		      option_node->name);
+	}
+    }
+
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+/**
+ * pn_actuator_add_option
+ * @actuator: a #PnActuator
+ * @option: the #PnOption to add
+ *
+ * Adds a #PnOption to the actuator.
+ */
+void
+pn_actuator_add_option (PnActuator *actuator, PnOption *option)
+{
+  g_return_if_fail (actuator != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (actuator));
+  g_return_if_fail (option != NULL);
+  g_return_if_fail (PN_IS_OPTION (option));
+  g_return_if_fail (! pn_actuator_get_option_by_name (actuator, PN_USER_OBJECT_NAME (option)));
+
+  g_array_append_val (actuator->options, option);
+  pn_object_ref (PN_OBJECT (option));
+  pn_object_sink (PN_OBJECT (option));
+  pn_user_object_set_owner (PN_USER_OBJECT (option), PN_USER_OBJECT (actuator));
+}
+
+/**
+ * pn_actuator_get_option_by_index
+ * @actuator: a #PnActuator
+ * @index: the index of the option to retrieve
+ *
+ * Retrieves a #PnOption associated with the actuator based on
+ * the index of the option.  Indices start at 0 and are determined
+ * by the order in which the options were added.
+ *
+ * Returns: The #PnOption at index @index
+ */
+PnOption*
+pn_actuator_get_option_by_index (PnActuator *actuator, guint index)
+{
+  g_return_val_if_fail (actuator != NULL, NULL);
+  g_return_val_if_fail (PN_IS_ACTUATOR (actuator), NULL);
+  g_return_val_if_fail (index < actuator->options->len, NULL);
+
+  return g_array_index (actuator->options, PnOption *, index);
+}
+
+/**
+ * pn_actuator_get_option_by_name
+ * @actuator: a #PnActuator
+ * @name: the name of the option to retrieve
+ *
+ * Retrieves the first #PnOption associated with the actuator 
+ * based on the name of the option.
+ *
+ * Returns: The first #PnOption with the name @name
+ */
+PnOption*
+pn_actuator_get_option_by_name (PnActuator *actuator, const gchar *name)
+{
+  gint i;
+  PnOption *option;
+
+  g_return_val_if_fail (actuator != NULL, NULL);
+  g_return_val_if_fail (PN_IS_ACTUATOR (actuator), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  for (i=0; i < actuator->options->len; i++)
+    {
+      option = g_array_index (actuator->options, PnOption *, i);
+      if (g_strcasecmp (pn_user_object_get_name (PN_USER_OBJECT (option)), name) == 0)
+	return option;
+    }
+
+  return NULL;
+}
+
+/**
+ * pn_actuator_prepare
+ * @actuator: a #PnActuator
+ * @image: the #PnImage for which the actuator should prepare
+ *
+ * Prepares an actuator to act upon a given #PnImage.
+ */
+void
+pn_actuator_prepare (PnActuator *actuator, PnImage *image)
+{
+  PnActuatorClass *class;
+
+  g_return_if_fail (actuator != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (actuator));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  class = PN_ACTUATOR_GET_CLASS (actuator);
+
+  if (class->prepare)
+    class->prepare (actuator, image);
+}
+
+/**
+ * pn_actuator_execute
+ * @actuator: a #PnActuator
+ * @image: the #PnImage to act upon
+ * @audio_data: the #PnAudioData to use when basing effects on sound
+ *
+ * Causes the actuator to perform its function on @image.  The pn_actuator_prepare()
+ * *MUST* have previously been called with the same @actuator and @image arguments.
+ */
+void
+pn_actuator_execute (PnActuator *actuator, PnImage *image, PnAudioData *audio_data)
+{
+  PnActuatorClass *class;
+
+  g_return_if_fail (actuator != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (actuator));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+/*    g_return_if_fail (PN_IS_AUDIO_DATA (audio_data)); */
+
+  class = PN_ACTUATOR_GET_CLASS (actuator);
+
+  if (class->execute)
+    class->execute (actuator, image, audio_data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnactuator.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,91 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_ACTUATOR_H__
+#define __PN_ACTUATOR_H__
+
+#include <glib.h>
+#include "pnuserobject.h"
+#include "pnoption.h"
+#include "pnimage.h"
+#include "pnaudiodata.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_ACTUATOR_OPT_LAST = 0
+};
+
+#define PN_TYPE_ACTUATOR              (pn_actuator_get_type ())
+#define PN_ACTUATOR(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_ACTUATOR, PnActuator))
+#define PN_ACTUATOR_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_ACTUATOR, PnActuatorClass))
+#define PN_IS_ACTUATOR(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_ACTUATOR))
+#define PN_IS_ACTUATOR_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_ACTUATOR))
+#define PN_ACTUATOR_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_ACTUATOR, PnActuatorClass))
+
+typedef struct _PnActuator        PnActuator;
+typedef struct _PnActuatorClass   PnActuatorClass;
+
+typedef void (*PnActuatorPrepFunc) (PnActuator *actuator,
+				    PnImage *image);
+typedef void (*PnActuatorExecFunc) (PnActuator *actuator,
+				    PnImage *image,
+				    PnAudioData *audio_data);
+
+struct _PnActuator
+{
+  PnUserObject parent;
+
+  GArray *options;
+};
+
+struct _PnActuatorClass
+{
+  PnUserObjectClass parent_class;
+
+  void (* prepare) (PnActuator *actuator,
+		    PnImage *image);
+  void (* execute) (PnActuator *actuator,
+		    PnImage *image,
+		    PnAudioData *audio_data);
+};
+
+/* Creators */
+GType                 pn_actuator_get_type                (void);
+
+/* Accessors */
+void                  pn_actuator_add_option              (PnActuator *actuator,
+							   PnOption *option);
+PnOption             *pn_actuator_get_option_by_index     (PnActuator *actuator,
+							   guint index);
+PnOption             *pn_actuator_get_option_by_name      (PnActuator *actuator,
+							   const gchar *name);
+/* Actions */
+void                  pn_actuator_prepare                 (PnActuator *actuator,
+							   PnImage *image);
+void                  pn_actuator_execute                 (PnActuator *actuator,
+							   PnImage *image,
+							   PnAudioData *audio_data);
+
+
+
+
+#endif /* __PN_ACTUATOR_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnactuatorfactory.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,109 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pnactuatorfactory.h"
+
+static gboolean    pn_actuator_factory_initialized = FALSE;
+static GHashTable *actuator_hash;
+
+void
+pn_actuator_factory_init (void)
+{
+  if (pn_actuator_factory_initialized == TRUE)
+    return;
+
+  /* FIXME: This should be done this way, but to avoid mixing glib version calls
+   * when linked to both versions, we need to use functions that are in both
+   * versions.
+   *
+   * uncomment this when glib-1.2 is no longer linked to by things like XMMS
+   */
+/*    actuator_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); */
+  actuator_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+  pn_actuator_factory_initialized = TRUE;
+}
+
+void
+pn_actuator_factory_register_actuator (const gchar *name, GType type)
+{
+  gchar *dup_name;
+  GType *dup_type;
+
+  g_return_if_fail (pn_actuator_factory_initialized == TRUE);
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (g_type_is_a (type, PN_TYPE_ACTUATOR));
+
+/*    if (pn_actuator_factory_is_registered (name)) */
+/*      return; */
+
+  dup_name = g_strdup (name);
+  dup_type = g_new (GType, 1);
+  *dup_type = type;
+
+  g_hash_table_insert (actuator_hash, dup_name, dup_type);
+}
+
+void
+pn_actuator_factory_unregister_actuator (const gchar *name)
+{
+  g_return_if_fail (pn_actuator_factory_initialized == TRUE);
+  g_return_if_fail (name != NULL);
+
+  g_hash_table_remove (actuator_hash, name);
+}
+
+gboolean
+pn_actuator_factory_is_registered (const gchar *name)
+{
+  g_return_val_if_fail (pn_actuator_factory_initialized == TRUE, FALSE);
+  g_return_val_if_fail (name != NULL, FALSE);
+
+  return (g_hash_table_lookup (actuator_hash, name) != NULL);
+}
+
+PnActuator*
+pn_actuator_factory_new_actuator (const gchar *name)
+{
+  GType *type;
+  g_return_val_if_fail (pn_actuator_factory_initialized == TRUE, NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  type = (GType *) g_hash_table_lookup (actuator_hash, name);
+  if (! type)
+    return NULL;
+
+  return (PnActuator *) g_object_new (*type, NULL);
+}
+
+PnActuator*
+pn_actuator_factory_new_actuator_from_xml (xmlNodePtr node)
+{
+  PnActuator *actuator;
+
+  actuator = pn_actuator_factory_new_actuator (node->name);
+  if (! actuator)
+    return NULL;
+
+  pn_user_object_load_thyself (PN_USER_OBJECT (actuator), node);
+
+  return actuator;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnactuatorfactory.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,33 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_ACTUATOR_FACTORY_H__
+#define __PN_ACTUATOR_FACTORY_H__
+
+#include "pnactuator.h"
+
+void               pn_actuator_factory_init                             (void);
+void               pn_actuator_factory_register_actuator                (const gchar *name,
+									 GType type);
+void               pn_actuator_factory_unregister_actuator              (const gchar *name);
+gboolean           pn_actuator_factory_is_registered                    (const gchar *name);
+PnActuator        *pn_actuator_factory_new_actuator                     (const gchar *name);
+PnActuator        *pn_actuator_factory_new_actuator_from_xml            (xmlNodePtr node);
+
+
+#endif /* __PN_ACTUATOR_FACTORY_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnactuatorlist.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,120 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include "pnactuatorlist.h"
+
+static void         pn_actuator_list_class_init       (PnActuatorListClass *class);
+static void         pn_actuator_list_init             (PnActuatorList *actuator_list,
+						       PnActuatorListClass *class);
+/* PnActuator methods */
+static void         pn_actuator_list_execute          (PnActuatorList *actuator_list,
+						       PnImage *image,
+						       PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_actuator_list_get_type (void)
+{
+  static GType actuator_list_type = 0;
+
+  if (! actuator_list_type)
+    {
+      static const GTypeInfo actuator_list_info =
+      {
+	sizeof (PnActuatorListClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_actuator_list_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnActuatorList),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_actuator_list_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      actuator_list_type = g_type_register_static (PN_TYPE_CONTAINER,
+					      "PnActuatorList",
+					      &actuator_list_info,
+					      0);
+    }
+  return actuator_list_type;
+}
+
+static void
+pn_actuator_list_class_init (PnActuatorListClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnActuator methods */
+  actuator_class->execute = (PnActuatorExecFunc) pn_actuator_list_execute;
+}
+
+static void
+pn_actuator_list_init (PnActuatorList *actuator_list, PnActuatorListClass *class)
+{
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (actuator_list), "Container.Actuator_List");
+  pn_user_object_set_description (PN_USER_OBJECT (actuator_list),
+				  "A container that executes all its actuators sequentially");
+}
+
+static void
+pn_actuator_list_execute (PnActuatorList *actuator_list, PnImage *image,
+			  PnAudioData *audio_data)
+{
+  guint i;
+  GArray *actuators;
+
+  g_return_if_fail (actuator_list != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR_LIST (actuator_list));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+
+  actuators = ((PnContainer *) (actuator_list))->actuators;;
+
+  for (i=0; i<actuators->len; i++)
+    pn_actuator_execute (g_array_index (actuators, PnActuator *, i), image, audio_data);
+
+  if (PN_ACTUATOR_CLASS (parent_class)->execute)
+    PN_ACTUATOR_CLASS (parent_class)->execute(PN_ACTUATOR (actuator_list), image, audio_data);
+}
+
+/**
+ * pn_actuator_list_new
+ *
+ * Creates a new #PnActuatorList.
+ *
+ * Returns: The new #PnActuatorList.
+ */
+PnActuatorList*
+pn_actuator_list_new (void)
+{
+  return (PnActuatorList *) g_object_new (PN_TYPE_ACTUATOR_LIST, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnactuatorlist.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,59 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_ACTUATOR_LIST_H__
+#define __PN_ACTUATOR_LIST_H__
+
+#include "pncontainer.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_ACTUATOR_LIST_OPT_LAST = PN_CONTAINER_OPT_LAST
+};
+
+#define PN_TYPE_ACTUATOR_LIST              (pn_actuator_list_get_type ())
+#define PN_ACTUATOR_LIST(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_ACTUATOR_LIST, PnActuatorList))
+#define PN_ACTUATOR_LIST_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_ACTUATOR_LIST, PnActuatorListClass))
+#define PN_IS_ACTUATOR_LIST(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_ACTUATOR_LIST))
+#define PN_IS_ACTUATOR_LIST_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_ACTUATOR_LIST))
+#define PN_ACTUATOR_LIST_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_ACTUATOR_LIST, PnActuatorListClass))
+
+#define PN_ACTUATOR_LIST_ACTUATORS(obj)    (PN_ACTUATOR_LIST (obj)->actuators)
+
+typedef struct _PnActuatorList        PnActuatorList;
+typedef struct _PnActuatorListClass   PnActuatorListClass;
+
+struct _PnActuatorList
+{
+  PnContainer parent;
+};
+
+struct _PnActuatorListClass
+{
+  PnContainerClass parent_class;
+};
+
+/* Creators */
+GType                 pn_actuator_list_get_type                (void);
+PnActuatorList       *pn_actuator_list_new                     (void);
+
+#endif /* __PN_ACTUATOR_LIST_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnaudiodata.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,292 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <math.h>
+
+#include <config.h>
+#include "pnaudiodata.h"
+
+/* Initialization */
+static void         pn_audio_data_class_init        (PnAudioDataClass *class);
+static void         pn_audio_data_init              (PnAudioData *audio_data,
+						     PnAudioDataClass *class);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+pn_audio_data_get_type (void)
+{
+  static GType audio_data_type = 0;
+
+  if (! audio_data_type)
+    {
+      static const GTypeInfo audio_data_info =
+      {
+	sizeof (PnAudioDataClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_audio_data_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnAudioData),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_audio_data_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      audio_data_type = g_type_register_static (PN_TYPE_OBJECT,
+					    "PnAudioData",
+					    &audio_data_info,
+					    0);
+    }
+  return audio_data_type;
+}
+
+static void
+pn_audio_data_class_init (PnAudioDataClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+
+  parent_class = g_type_class_peek_parent (class);
+}
+
+static void
+pn_audio_data_init (PnAudioData *audio_data, PnAudioDataClass *class)
+{
+  audio_data->stereo = TRUE;
+
+  /* Initialize with a 1-sample and 1-band pcm_ and freq_data, respecitvely */
+  audio_data->pcm_samples = 1;
+  audio_data->pcm_data[0] = g_new0 (gfloat, 1);
+  audio_data->pcm_data[1] = g_new0 (gfloat, 1);
+  audio_data->pcm_data[2] = g_new0 (gfloat, 1);
+  
+  audio_data->freq_bands = 1;
+  audio_data->freq_data[0] = g_new0 (gfloat, 1);
+  audio_data->freq_data[1] = g_new0 (gfloat, 1);
+  audio_data->freq_data[2] = g_new0 (gfloat, 1);
+}
+
+/**
+ * pn_audio_data_new
+ *
+ * Creates a new #PnAudioData object.
+ *
+ * Returns: The new #PnAudioData object
+ */
+PnAudioData*
+pn_audio_data_new (void)
+{
+  return (PnAudioData *) g_object_new (PN_TYPE_AUDIO_DATA, NULL);
+}
+
+/**
+ * pn_audio_data_set_stereo
+ * @audio_data: a #PnAudioData
+ * @stereo: TRUE or FALSE
+ *
+ * Sets whether @audio_data will use stereo audio data.  If
+ * stereo is %FALSE, each channel buffer points to the same memory
+ * location;  otherwise they are separate buffers.
+ */
+void
+pn_audio_data_set_stereo (PnAudioData *audio_data, gboolean stereo)
+{
+  gboolean changed;
+
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+  changed = audio_data->stereo == stereo ? TRUE : FALSE;
+  audio_data->stereo = stereo;
+
+  if (changed)
+    {
+      pn_audio_data_set_pcm_samples (audio_data, audio_data->pcm_samples);
+      pn_audio_data_set_freq_bands (audio_data, audio_data->freq_bands);
+    }
+}
+
+/**
+ * pn_audio_data_get_stereo
+ * @audio_data: a #PnAudioData
+ *
+ * Retrieves the whether or not @audio_data contains stereo audio data
+ *
+ * Returns: %TRUE if it contains stereo data, %FALSE otherwise
+ */
+gboolean
+pn_audio_data_get_stereo (PnAudioData *audio_data)
+{
+  g_return_val_if_fail (audio_data != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_AUDIO_DATA (audio_data), FALSE);
+
+  return audio_data->stereo;
+}
+
+/**
+ * pn_audio_data_set_pcm_samples
+ * @audio_data: a #PnAudioData
+ * @samples: the number of samples
+ *
+ * Sets the number of samples that @audio_data's pcm data
+ * contains.
+ */ 
+void
+pn_audio_data_set_pcm_samples (PnAudioData *audio_data, guint samples)
+{
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+  g_return_if_fail (samples > 0);
+
+  if (audio_data->pcm_data[0])
+    {
+      g_free (audio_data->pcm_data[0]);
+      if (audio_data->stereo)
+	{
+	  g_free (audio_data->pcm_data[1]);
+	  g_free (audio_data->pcm_data[2]);
+	}
+    }
+
+  audio_data->pcm_samples = samples;
+  audio_data->pcm_data[0] = g_new0 (gfloat, samples);
+  if (audio_data->stereo)
+    {
+      audio_data->pcm_data[1] = g_new0 (gfloat, samples);
+      audio_data->pcm_data[2] = g_new0 (gfloat, samples);
+    }
+  else
+    audio_data->pcm_data[1] = audio_data->pcm_data[2] = audio_data->pcm_data[0];
+}
+      
+/**
+ * pn_audio_data_get_pcm_samples
+ * @audio_data: a #PnAudioData
+ *
+ * Retrieves the number of samples that @audio_data's pcm data
+ * contains
+ *
+ * Returns: The number of samples
+ */
+guint
+pn_audio_data_get_pcm_samples (PnAudioData *audio_data)
+{
+  g_return_val_if_fail (audio_data != NULL, 0);
+  g_return_val_if_fail (PN_IS_AUDIO_DATA (audio_data), 0);
+
+  return audio_data->pcm_samples;
+}  
+
+/**
+ * pn_audio_data_set_freq_bands
+ * @audio_data: a #PnAudioData
+ * @bands: the number of bands
+ *
+ * Sets the number of bands that @audio_data's frequency data
+ * contains.
+ */
+void
+pn_audio_data_set_freq_bands (PnAudioData *audio_data, guint bands)
+{
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+  g_return_if_fail (bands > 0);
+
+  
+  if (audio_data->freq_data[0])
+    {
+      g_free (audio_data->freq_data[0]);
+      if (audio_data->stereo)
+	{
+	  g_free (audio_data->freq_data[1]);
+	  g_free (audio_data->freq_data[2]);
+	}
+    }
+
+  audio_data->freq_bands = bands;
+  audio_data->freq_data[0] = g_new0 (gfloat, bands);
+  if (audio_data->stereo)
+    {
+      audio_data->freq_data[1] = g_new0 (gfloat, bands);
+      audio_data->freq_data[2] = g_new0 (gfloat, bands);
+    }
+  else
+    audio_data->freq_data[1] = audio_data->freq_data[2] = audio_data->freq_data[0];
+}
+
+/**
+ * pn_audio_data_get_freq_bands
+ * @audio_data: a #PnAudioData
+ *
+ * Retrieves the number of bands that @audio_data's frequency data
+ * contains
+ *
+ * Returns: The number of bands
+ */
+guint
+pn_audio_data_get_freq_bands (PnAudioData *audio_data)
+{
+  g_return_val_if_fail (audio_data != NULL, 0);
+  g_return_val_if_fail (PN_IS_AUDIO_DATA (audio_data), 0);
+
+  return audio_data->freq_bands;
+}  
+
+/**
+ * pn_audio_data_get_volume
+ * @audio_data: a #PnAudioData
+ *
+ * Retrieves the volume level (from 0.0 to 1.0) of the audio frame
+ * contained within a #PnAudioData object.
+ *
+ * Returns: The volume level
+ */
+gfloat
+pn_audio_data_get_volume (PnAudioData *audio_data)
+{
+  g_return_val_if_fail (audio_data != NULL, 0.0);
+  g_return_val_if_fail (PN_IS_AUDIO_DATA (audio_data), 0.0);
+
+  return audio_data->volume;
+}
+
+/**
+ * pn_audio_data_update
+ * @audio_data: a #PnAudioData
+ *
+ * Updates the information about the audio data frame in a #PnAudioData.
+ * This function should be called after all updates to pcm_data or freq_data.
+ */
+void
+pn_audio_data_update (PnAudioData *audio_data)
+{
+  guint i;
+
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+  /* Get the volume */
+  audio_data->volume = 0.0;
+  for (i=0; i<audio_data->pcm_samples; i++)
+    audio_data->volume = MAX (audio_data->volume, fabs (audio_data->pcm_data[PN_CHANNEL_LEFT][i]));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnaudiodata.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,101 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_AUDIO_DATA_H__
+#define __PN_AUDIO_DATA_H__
+
+#include "pnobject.h"
+
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  PN_CHANNEL_LEFT,
+  PN_CHANNEL_CENTER,
+  PN_CHANNEL_RIGHT
+} PnAudioDataChannels;
+
+#define PN_TYPE_AUDIO_DATA              (pn_audio_data_get_type ())
+#define PN_AUDIO_DATA(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_AUDIO_DATA, PnAudioData))
+#define PN_AUDIO_DATA_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_AUDIO_DATA, PnAudioDataClass))
+#define PN_IS_AUDIO_DATA(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_AUDIO_DATA))
+#define PN_IS_AUDIO_DATA_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_AUDIO_DATA))
+#define PN_AUDIO_DATA_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_AUDIO_DATA, PnAudioDataClass))
+#define PN_AUDIO_DATA_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define PN_AUDIO_DATA_CLASS_NAME(class) (g_type_name (PN_AUDIO_DATA_CLASS_TYPE (class)))
+
+#define PN_AUDIO_DATA_PCM_SAMPLES(obj)  (PN_AUDIO_DATA (obj)->pcm_samples)
+#define PN_AUDIO_DATA_PCM_DATA(obj,ch)  (PN_AUDIO_DATA (obj)->pcm_data[ch])
+#define PN_AUDIO_DATA_FREQ_BANDS(obj)   (PN_AUDIO_DATA (obj)->freq_bands)
+#define PN_AUDIO_DATA_FREQ_DATA(obj,ch) (PN_AUDIO_DATA (obj)->freq_data[ch])
+
+typedef struct _PnAudioData        PnAudioData;
+typedef struct _PnAudioDataClass   PnAudioDataClass;
+
+struct _PnAudioData
+{
+  PnObject parent;
+
+  /*< public >*/
+
+  /* PCM and frequency data are floats in the range of 0 to 1 */
+
+  /* PCM Data */
+  guint pcm_samples;    /* read-only */
+  gfloat *pcm_data[3];  /* read-write */
+
+  /* Frequency Data */
+  guint freq_bands;     /* read-only */
+  gfloat *freq_data[3]; /* read-write */
+
+  /*< private >*/
+  /* If this is TRUE, each channel is separate, otherwise they all point
+   * to the same buffer.  Default is TRUE.
+   */
+  gboolean stereo;
+
+  /* Overall volume of the audio frame */
+  gfloat volume;
+};
+
+struct _PnAudioDataClass
+{
+  PnObjectClass parent_class;
+};
+
+/* Creators */
+GType             pn_audio_data_get_type             (void);
+PnAudioData      *pn_audio_data_new                  (void);
+
+/* Accessors */
+void              pn_audio_data_set_stereo           (PnAudioData *audio_data,
+						      gboolean stereo);
+gboolean          pn_audio_data_get_stereo           (PnAudioData *audio_data);
+void              pn_audio_data_set_pcm_samples      (PnAudioData *audio_data,
+						      guint samples);
+guint             pn_audio_data_get_pcm_samples      (PnAudioData *audio_data);
+void              pn_audio_data_set_freq_bands       (PnAudioData *audio_data,
+						      guint bands);
+guint             pn_audio_data_get_freq_bands       (PnAudioData *audio_data);
+gfloat            pn_audio_data_get_volume           (PnAudioData *audio_data);
+
+/* Actions */
+void              pn_audio_data_update               (PnAudioData *audio_data);
+
+#endif /* __PN_AUDIO_DATA_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnblur.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,338 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include "pnblur.h"
+#include "pncpu.h"
+
+static void         pn_blur_class_init       (PnBlurClass *class);
+static void         pn_blur_init             (PnBlur *blur,
+					      PnBlurClass *class);
+
+/* PnActuator methods */
+static void         pn_blur_execute          (PnBlur *blur,
+					      PnImage *image,
+					      PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_blur_get_type (void)
+{
+  static GType blur_type = 0;
+
+  if (! blur_type)
+    {
+      static const GTypeInfo blur_info =
+      {
+	sizeof (PnBlurClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_blur_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnBlur),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_blur_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      blur_type = g_type_register_static (PN_TYPE_ACTUATOR,
+					      "PnBlur",
+					      &blur_info,
+					      0);
+    }
+  return blur_type;
+}
+
+static void
+pn_blur_class_init (PnBlurClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnActuator methods */
+  actuator_class->execute = (PnActuatorExecFunc) pn_blur_execute;
+}
+
+static void
+pn_blur_init (PnBlur *blur, PnBlurClass *class)
+{
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (blur), "Transform.Blur");
+  pn_user_object_set_description (PN_USER_OBJECT (blur),
+				  "Blur the image");
+}
+
+static inline void
+pn_blur_execute_medium (PnImage *image)
+{
+  register PnColor *src_left;
+  PnColor *src_top, *src_bot, *src_right;
+  PnColor *dest, *dest_last;
+  guint width, width_m1, total_width, height, height_m1;
+  register guint red_sum, green_sum, blue_sum;
+  guint i = 0;
+
+  width = pn_image_get_width (image);
+  width_m1 = width - 1;
+  total_width = pn_image_get_pitch (image)>>2;
+  height = pn_image_get_height (image);
+  height_m1 = height - 1;
+
+  dest = pn_image_get_transform_buffer (image);
+  src_left = pn_image_get_image_buffer (image) - 1;
+  src_right = src_left + 2;
+  src_top = (src_left - total_width) + 1;
+  src_bot = (src_left + total_width) + 1;
+
+  src_top += total_width;
+  src_bot += total_width;
+  src_left += total_width;
+  src_right += total_width;
+  dest += total_width;
+
+  dest_last = pn_image_get_transform_buffer (image) + (total_width * (height-1));
+  while (dest < dest_last)
+    {
+      for (i=0; i < width; i++)
+	{
+	  /* Top pixel */
+	  red_sum = src_top->red;
+	  green_sum = src_top->green;
+	  blue_sum = src_top->blue;
+
+	  /* Bottom pixel */
+	  red_sum += src_bot->red;
+	  green_sum += src_bot->green;
+	  blue_sum += src_bot->blue;
+
+	  /* Left pixel */
+	  if (i != 0)
+	    {
+	      red_sum += src_left->red;
+	      green_sum += src_left->green;
+	      blue_sum += src_left->blue;
+	    }
+	  else
+	    {
+	      red_sum += (src_left+1)->red;
+	      green_sum += (src_left+1)->green;
+	      blue_sum += (src_left+1)->blue;
+	    }
+
+	  /* Right pixel */
+	  if (i != width_m1)
+	    {
+	      red_sum += src_right->red;
+	      green_sum += src_right->green;
+	      blue_sum += src_right->blue;
+	    }
+	  else
+	    {
+	      red_sum += (src_left+1)->red;
+	      green_sum += (src_left+1)->green;
+	      blue_sum += (src_left+1)->blue;
+	    }
+
+	  src_left++;
+	  src_right++;
+	  src_top++;
+	  src_bot++;
+
+	  /*  	  red_sum *= 3; */
+	  /*  	  green_sum *= 3; */
+	  /*  	  blue_sum *= 3; */
+
+	  /* Center pixel */
+	  red_sum += src_left->red << 2;
+	  green_sum += src_left->green << 2;
+	  blue_sum += src_left->blue << 2;
+
+	  dest->red = (guchar)(red_sum >> 3);
+	  dest->green = (guchar)(green_sum >> 3);
+	  dest->blue = (guchar)(blue_sum >> 3);
+	  dest++;
+	}
+      src_left += total_width - width;
+      src_right += total_width - width;
+      src_bot += total_width - width;
+      src_top += total_width - width;
+      dest += total_width - width;
+    }
+}
+
+#ifdef PN_USE_MMX
+static void
+pn_blur_execute_medium_mmx (PnImage *image)
+{
+  guint width, pitch;
+  PnColor *src, *dest, *dest_last;
+
+  width = pn_image_get_width (image);
+  pitch = pn_image_get_pitch (image);
+
+  src = pn_image_get_image_buffer (image) - 1;
+  dest = pn_image_get_transform_buffer (image) + (pitch>>2);
+  dest_last = dest + ((pitch>>2) * (pn_image_get_height (image) - 2));
+
+  /*
+   * ecx = x counter
+   */
+
+  /*
+   * src  X    X    X
+   * X    X    X    X
+   * X    X    X    X
+   */
+
+  /*
+   * X    X    X    X
+   * X    dest X    X
+   * X    X    X    X
+   */
+
+  /*
+   * %0 = src
+   * %1 = dest
+   * %2 = pitch
+   * %3 = width
+   * %4 = dest_last
+   */
+  
+  /*
+   * mm0 = left dest pixel sum
+   * mm1 = right dest pixel sum
+   * mm6 = unpacked leftmost source pixel
+   * mm7 = 0
+   */
+
+  __asm__ __volatile__ (
+			"movl %3,%%ecx\n\t"                 /* start with x = 0 */
+
+			"pxor %%mm7,%%mm7\n\t"                 /* set up the zero mmx register used
+								* in unpacking
+								*/
+
+			"pxor %%mm6,%%mm6\n\t"                  /* start with the leftmost pixel = zero */
+								 
+
+			"10:\n\t"                              /* begin the inner loop */
+
+			"movq 4(%0),%%mm0\n\t"                 /* load and unpack the top and bottom */
+			"movq 4(%0,%2,2),%%mm2\n\t"            /* row of pixels	*/
+			"movq %%mm0,%%mm1\n\t"
+			"movq %%mm2,%%mm3\n\t"
+			"punpcklbw %%mm7,%%mm0\n\t"            /* tops */
+			"punpckhbw %%mm7,%%mm1\n\t"
+			"punpcklbw %%mm7,%%mm2\n\t"            /* bottoms */
+			"punpckhbw %%mm7,%%mm3\n\t"
+
+			"paddw %%mm2,%%mm0\n\t"                /* add the two top & bottom pixels */
+			"paddw %%mm3,%%mm1\n\t"
+
+			"paddw %%mm6,%%mm0\n\t"                /* add the left pixel */
+
+			"movq 4(%0,%2),%%mm2\n\t"              /* load and unpack the two center pixels */
+			"movq %%mm2,%%mm3\n\t"
+			"punpcklbw %%mm7,%%mm2\n\t"            /* used as quadruple-weighted center pixels */
+			"punpckhbw %%mm7,%%mm3\n\t"
+
+			"movq %%mm3,%%mm6\n\t"                 /* save the unpacked right-center pixel
+								* for the next iteration's leftmost pixel
+								*/
+
+			"cmpl $1,%%ecx\n\t"                    /* make sure the right-center pixel is on
+								* the image
+								*/
+			"je 20f\n\t"
+
+			"movd 12(%0,%2),%%mm5\n\t"             /* load and unpack the right pixel */
+			"punpcklbw %%mm7,%%mm5\n\t"
+			"paddw %%mm5,%%mm1\n\t"                /* add the right pixel */
+
+			"paddw %%mm3,%%mm0\n\t"                /* add the center pixels as adjecent pixels */
+			"paddw %%mm2,%%mm1\n\t"
+			"20:\n\t"
+
+			"psllw $2,%%mm2\n\t"                   /* multiply the center pixels by 4 */
+			"psllw $2,%%mm3\n\t"
+
+			/* multiply the sums (mm0 and mm1) by 3 for the heavy blur here */
+
+			"paddw %%mm2,%%mm0\n\t"                /* add the center pixels as center pixels */
+			"paddw %%mm3,%%mm1\n\t"
+
+			"psrlw $3,%%mm0\n\t"                   /* normalize the values - should be 4 for */
+			"psrlw $3,%%mm1\n\t"                   /* heavy blur */
+
+			"packuswb %%mm1,%%mm0\n\t"             /* repack it all and write it */
+			"movq %%mm0,(%1)\n\t"
+
+			"addl $8,%0\n\t"                       /* advance the pointers */
+			"addl $8,%1\n\t"
+
+			"subl $2,%%ecx\n\t"                    /* decrement inverse x counter */
+			"jg 10b\n\t"
+
+			"movl %3,%%ecx\n\t"                    /* start a new line */
+			"pxor %%mm6,%%mm6\n\t"
+
+			"cmpl %1,%4\n\t"                       /* if we're all done then stop */
+			"jg 10b\n\t"
+
+			"emms"                                 /* all done! */
+			: /* no outputs */
+			: "r" (src), "r" (dest), "r" (pitch), "r" (width), "m" (dest_last)
+			: "ecx"
+			);
+}
+#endif /* USE_MMX */
+
+static void
+pn_blur_execute (PnBlur *blur, PnImage *image, PnAudioData *audio_data)
+{
+  g_return_if_fail (blur != NULL);
+  g_return_if_fail (PN_IS_BLUR (blur));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+#ifdef PN_USE_MMX
+  if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+    pn_blur_execute_medium_mmx (image);
+  else
+#endif /* USE_MMX */
+    pn_blur_execute_medium (image);
+
+  pn_image_apply_transform (image);
+}
+
+PnBlur*
+pn_blur_new (void)
+{
+  return (PnBlur *) g_object_new (PN_TYPE_BLUR, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnblur.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,56 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_BLUR_H__
+#define __PN_BLUR_H__
+
+#include "pnactuator.h"
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_BLUR_OPT_LAST = PN_ACTUATOR_OPT_LAST
+};
+
+#define PN_TYPE_BLUR              (pn_blur_get_type ())
+#define PN_BLUR(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_BLUR, PnBlur))
+#define PN_BLUR_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_BLUR, PnBlurClass))
+#define PN_IS_BLUR(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_BLUR))
+#define PN_IS_BLUR_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_BLUR))
+#define PN_BLUR_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_BLUR, PnBlurClass))
+
+typedef struct _PnBlur        PnBlur;
+typedef struct _PnBlurClass   PnBlurClass;
+
+struct _PnBlur
+{
+  PnActuator parent;
+};
+
+struct _PnBlurClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                 pn_blur_get_type                (void);
+PnBlur               *pn_blur_new                     (void);
+
+#endif /* __PN_BLUR_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnbooleanoption.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,190 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <glib.h>
+#include "pnbooleanoption.h"
+#include "pnxml.h"
+#include "pnerror.h"
+
+static void         pn_boolean_option_class_init       (PnBooleanOptionClass *class);
+
+/* PnUserObject methods */
+static void         pn_boolean_option_save_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+static void         pn_boolean_option_load_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_boolean_option_get_type (void)
+{
+  static GType boolean_option_type = 0;
+
+  if (! boolean_option_type)
+    {
+      static const GTypeInfo boolean_option_info =
+      {
+	sizeof (PnBooleanOptionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_boolean_option_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnBooleanOption),
+	0,              /* n_preallocs */
+	NULL            /* instance_init */
+      };
+
+      /* FIXME: should this be dynamic? */
+      boolean_option_type = g_type_register_static (PN_TYPE_OPTION,
+					      "PnBooleanOption",
+					      &boolean_option_info,
+					      0);
+    }
+  return boolean_option_type;
+}
+
+static void
+pn_boolean_option_class_init (PnBooleanOptionClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnOptionClass *option_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  option_class = (PnOptionClass *) class;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_boolean_option_save_thyself;
+  user_object_class->load_thyself = pn_boolean_option_load_thyself;
+
+  /* PnOption methods */
+  /* FIXME: this needs to be uncommented when the widget is done */
+/*    option_class->widget_type = PN_TYPE_BOOLEAN_OPTION_WIDGET; */
+}
+
+static void
+pn_boolean_option_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnBooleanOption *boolean_option;
+  xmlNodePtr value_node;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_BOOLEAN_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  boolean_option = (PnBooleanOption *) user_object;
+
+  value_node = xmlNewChild (node, NULL, "Value", NULL);
+
+  if (boolean_option->value)
+    xmlNodeSetContent (value_node, "True");
+  else
+    xmlNodeSetContent (value_node, "False");
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_boolean_option_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnBooleanOption *boolean_option;
+  xmlNodePtr boolean_option_node;
+  gchar *val_str;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_BOOLEAN_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  boolean_option = (PnBooleanOption *) user_object;
+
+  /* find the node for this class */
+  for (boolean_option_node = node->xmlChildrenNode;
+       boolean_option_node;
+       boolean_option_node = boolean_option_node->next)
+    if (g_strcasecmp (boolean_option_node->name, "Value") == 0)
+      break;
+  if (! boolean_option_node)
+    {
+      pn_error ("unable to load a PnBooleanOption from xml node \"%s\"", node->name);
+      return;
+    }
+
+  val_str = xmlNodeGetContent (boolean_option_node);
+  if (! val_str)
+    goto done;
+
+  while (isspace (*val_str))
+    val_str++;
+
+  if (g_strncasecmp (val_str, "True", 4) == 0)
+    boolean_option->value = TRUE;
+  else if (g_strncasecmp (val_str, "False", 5) == 0)
+    boolean_option->value = FALSE;
+  else
+    {
+      pn_error ("invalid boolean option value encountered at xml node \"%s\"", node->name);
+      return;
+    }
+
+ done:
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+PnBooleanOption*
+pn_boolean_option_new (const gchar *name, const gchar *desc)
+{
+  PnBooleanOption *boolean_option;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (desc != NULL, NULL);
+
+  boolean_option =   (PnBooleanOption *) g_object_new (PN_TYPE_BOOLEAN_OPTION, NULL);
+
+  pn_user_object_set_name (PN_USER_OBJECT (boolean_option), name);
+  pn_user_object_set_description (PN_USER_OBJECT (boolean_option), desc);
+
+  return boolean_option;
+}
+
+void
+pn_boolean_option_set_value (PnBooleanOption *boolean_option, gboolean value)
+{
+  g_return_if_fail (boolean_option != NULL);
+  g_return_if_fail (PN_IS_BOOLEAN_OPTION (boolean_option));
+
+  boolean_option->value = value;
+}
+
+gboolean
+pn_boolean_option_get_value (PnBooleanOption *boolean_option)
+{
+  g_return_val_if_fail (boolean_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_BOOLEAN_OPTION (boolean_option), FALSE);
+
+  return boolean_option->value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnbooleanoption.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,60 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_BOOLEAN_OPTION_H__
+#define __PN_BOOLEAN_OPTION_H__
+
+#include "pnoption.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_BOOLEAN_OPTION              (pn_boolean_option_get_type ())
+#define PN_BOOLEAN_OPTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_BOOLEAN_OPTION, PnBooleanOption))
+#define PN_BOOLEAN_OPTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_BOOLEAN_OPTION, PnBooleanOptionClass))
+#define PN_IS_BOOLEAN_OPTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_BOOLEAN_OPTION))
+#define PN_IS_BOOLEAN_OPTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_BOOLEAN_OPTION))
+#define PN_BOOLEAN_OPTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_BOOLEAN_OPTION, PnBooleanOptionClass))
+
+typedef struct _PnBooleanOption        PnBooleanOption;
+typedef struct _PnBooleanOptionClass   PnBooleanOptionClass;
+
+struct _PnBooleanOption
+{
+  PnOption parent;
+
+  gboolean value;
+};
+
+struct _PnBooleanOptionClass
+{
+  PnOptionClass parent_class;
+};
+
+/* Creators */
+GType                 pn_boolean_option_get_type                (void);
+PnBooleanOption      *pn_boolean_option_new                     (const gchar *name,
+								 const gchar *desc);
+
+/* Accessors */
+void                  pn_boolean_option_set_value               (PnBooleanOption *boolean_option,
+								 gboolean value);
+gboolean              pn_boolean_option_get_value               (PnBooleanOption *boolean_option);
+
+#endif /* __PN_BOOLEAN_OPTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnbuiltins.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,44 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include "pnactuatorfactory.h"
+
+#include "pnactuatorlist.h"
+#include "pnblur.h"
+#include "pndisplacement.h"
+#include "pndistortion.h"
+#include "pnflip.h"
+#include "pnimagecontext.h"
+#include "pnrotozoom.h"
+#include "pnscope.h"
+
+/* This NEEDS to be kept in sync with ALL the actuators */
+void
+pn_builtins_register (void)
+{
+  pn_actuator_factory_register_actuator ("Container.Actuator_List", PN_TYPE_ACTUATOR_LIST);
+  pn_actuator_factory_register_actuator ("Transform.Blur", PN_TYPE_BLUR);
+  pn_actuator_factory_register_actuator ("Transform.Displacement", PN_TYPE_DISPLACEMENT);
+  pn_actuator_factory_register_actuator ("Transform.Distortion", PN_TYPE_DISTORTION);
+  pn_actuator_factory_register_actuator ("Transform.Flip", PN_TYPE_FLIP);
+  pn_actuator_factory_register_actuator ("Container.Image_Context", PN_TYPE_IMAGE_CONTEXT);
+  pn_actuator_factory_register_actuator ("Transform.Roto_Zoom", PN_TYPE_ROTO_ZOOM);
+  pn_actuator_factory_register_actuator ("Render.Scope", PN_TYPE_SCOPE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnbuiltins.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,32 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_BUILTINS_H__
+#define __PN_BUILTINS_H__
+
+
+G_BEGIN_DECLS
+
+
+void        pn_builtins_register                          (void);
+
+
+
+
+
+#endif /* __PN_BUILTINS_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pncontainer.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,300 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include "pncontainer.h"
+#include "pnactuatorfactory.h"
+#include "pnerror.h"
+#include "pnxml.h"
+
+static void         pn_container_class_init        (PnContainerClass *class);
+static void         pn_container_init              (PnContainer *container,
+						    PnContainerClass *class);
+/* PnObject methods */
+static void         pn_container_destroy           (PnObject *object);
+
+/* PnUserObject methods */
+static void         pn_container_save_thyself      (PnUserObject *user_object,
+						    xmlNodePtr node);
+static void         pn_container_load_thyself      (PnUserObject *user_object,
+						    xmlNodePtr node);
+
+/* PnActuator methods */
+static void         pn_container_prepare           (PnContainer *container,
+						    PnImage *image);
+
+/* PnContainer methods */
+static gboolean     pn_container_real_add_actuator (PnContainer *container,
+						    PnActuator *actuator,
+						    gint position);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_container_get_type (void)
+{
+  static GType container_type = 0;
+
+  if (! container_type)
+    {
+      static const GTypeInfo container_info =
+      {
+	sizeof (PnContainerClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_container_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnContainer),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_container_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      container_type = g_type_register_static (PN_TYPE_ACTUATOR,
+					      "PnContainer",
+					      &container_info,
+					      G_TYPE_FLAG_ABSTRACT);
+    }
+  return container_type;
+}
+
+static void
+pn_container_class_init (PnContainerClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnObject signals */
+  object_class->destroy = pn_container_destroy;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_container_save_thyself;
+  user_object_class->load_thyself = pn_container_load_thyself;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_container_prepare;
+
+  /* PnContainer methods */
+  class->add_actuator = pn_container_real_add_actuator;
+}
+
+static void
+pn_container_init (PnContainer *container, PnContainerClass *class)
+{
+  container->actuators = g_array_new (FALSE, FALSE, sizeof (PnActuator *));
+}
+
+static void
+pn_container_destroy (PnObject *object)
+{
+  PnContainer *container;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (PN_IS_CONTAINER (object));
+
+  container = (PnContainer *) object;
+
+  pn_container_remove_all_actuators (container);
+}
+
+static void
+pn_container_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnContainer *container;
+  PnActuator *actuator;
+  xmlNodePtr actuators_node, actuator_node;
+  guint i;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_CONTAINER (user_object));
+  g_return_if_fail (node != NULL);
+
+  container = (PnContainer *) user_object;
+
+  actuators_node = xmlNewChild (node, NULL, "Actuators", NULL);
+
+  /* Save the actuators */
+  for (i=0; i<container->actuators->len; i++)
+    {
+      actuator = g_array_index (container->actuators, PnActuator *, i);
+      actuator_node = xmlNewChild (actuators_node, NULL, "BUG", NULL);
+      pn_user_object_save_thyself (PN_USER_OBJECT (actuator), actuator_node);
+    }
+
+  if (PN_USER_OBJECT_CLASS (parent_class)->save_thyself)
+    PN_USER_OBJECT_CLASS (parent_class)->save_thyself (user_object, node);
+}
+
+static void
+pn_container_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnContainer *container;
+  xmlNodePtr actuators_node, actuator_node;
+  PnActuator *actuator;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_CONTAINER (user_object));
+  g_return_if_fail (node != NULL);
+
+  container = (PnContainer *) user_object;
+
+  /* FIXME: should these 'xmlChildrenNode' be 'xmlRootNode'? */
+
+  /* find the 'actuators' node */
+  for (actuators_node = node->xmlChildrenNode; actuators_node; actuators_node = actuators_node->next)
+    if (g_strcasecmp (actuators_node->name, "Actuators") == 0)
+      break;
+
+  /* load each of the actuators */
+  if (actuators_node)
+    {
+      for (actuator_node = actuators_node->xmlChildrenNode; actuator_node; actuator_node = actuator_node->next)
+	{
+	  actuator = pn_actuator_factory_new_actuator_from_xml (actuator_node);
+	  if (actuator)
+	    /* FIXME: Should this be pn_container_real_add_actuator? */
+	    pn_container_add_actuator (container, actuator, PN_POSITION_TAIL);
+	  else
+	    pn_error ("unknown actuator ecountered in container \"%s\": %s",
+		      node->name,
+		      actuator_node->name);
+	}
+    }
+
+  if (PN_USER_OBJECT_CLASS (parent_class)->load_thyself)
+    PN_USER_OBJECT_CLASS (parent_class)->load_thyself (user_object, node);
+}
+
+static void
+pn_container_prepare (PnContainer *container, PnImage *image)
+{
+  guint i;
+
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (PN_IS_CONTAINER (container));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  for (i=0; i<container->actuators->len; i++)
+    pn_actuator_prepare (g_array_index (container->actuators, PnActuator *, i), image);
+}
+
+static gboolean
+pn_container_real_add_actuator (PnContainer *container, PnActuator *actuator, gint position)
+{
+  g_return_val_if_fail (container != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_CONTAINER (container), FALSE);
+  g_return_val_if_fail (actuator != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_ACTUATOR (actuator), FALSE);
+  g_return_val_if_fail (position >= PN_POSITION_TAIL, FALSE);
+
+  if (position == PN_POSITION_TAIL || position >= container->actuators->len)
+    position = container->actuators->len;
+
+  /* Just pass it on to the GArray insert function */
+  g_array_insert_val (container->actuators, position, actuator);
+
+  pn_object_ref (PN_OBJECT (actuator));
+  pn_object_sink (PN_OBJECT (actuator));
+
+  return TRUE;
+}
+
+/**
+ * pn_container_add_actuator
+ * @container: a #PnContainer
+ * @actuator: the #PnActuator to add
+ * @position: the position at which to add the actuator
+ *
+ * Adds @actuator to @container.  @position is the zero-based index
+ * in the list of actuators that the newly added actuator should have,
+ * or it can be the value %PN_POSITION_HEAD or %PN_POSITION_TAIL.
+ *
+ * Returns: %TRUE on success; %FALSE on failure
+ */
+gboolean
+pn_container_add_actuator (PnContainer *container, PnActuator *actuator, gint position)
+{
+  g_return_val_if_fail (container != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_CONTAINER (container), FALSE);
+  g_return_val_if_fail (actuator != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_ACTUATOR (actuator), FALSE);
+  g_return_val_if_fail (position >= PN_POSITION_TAIL, FALSE);
+
+  if (PN_CONTAINER_GET_CLASS (container)->add_actuator)
+    return PN_CONTAINER_GET_CLASS (container)->add_actuator (container, actuator, position);
+  else
+    return FALSE;
+}
+
+/**
+ * pn_container_remove_actuator
+ * @container: a #PnContainer
+ * @actuator: the #PnActuator to remove
+ *
+ * Removes the first occurence of @actuator in @container's list
+ * of contained actuators.
+ */
+/* FIXME: what is the most convenient way to remove actuators? */
+/* Note: Only removes the first one in the array */
+void
+pn_container_remove_actuator (PnContainer *container, PnActuator *actuator)
+{
+  guint i;
+
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (PN_IS_CONTAINER (container));
+  g_return_if_fail (actuator != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (actuator));
+
+  for (i=0; i<container->actuators->len; i++)
+    if (g_array_index (container->actuators, PnActuator *, i) == actuator)
+      {
+	g_array_remove_index (container->actuators, i);
+	pn_object_unref (PN_OBJECT (actuator));
+	return;
+      }
+}
+
+/**
+ * pn_container_remove_all_actuators
+ * @container: a #PnContainer
+ *
+ * Removes all actuators from @container's list of contained actuators.
+ */
+void
+pn_container_remove_all_actuators (PnContainer *container)
+{
+  guint i;
+
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (PN_IS_CONTAINER (container));
+
+  for (i=0; i<container->actuators->len; i++)
+    pn_object_unref (g_array_index (container->actuators, PnObject *, i));
+
+  g_array_set_size (container->actuators, 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pncontainer.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,82 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_CONTAINER_H__
+#define __PN_CONTAINER_H__
+
+#include "pnactuator.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_CONTAINER_OPT_LAST = PN_ACTUATOR_OPT_LAST
+};
+
+typedef enum
+{
+  PN_POSITION_TAIL = -1,
+  PN_POSITION_HEAD = 0
+} PnContainerPosition;
+
+#define PN_TYPE_CONTAINER              (pn_container_get_type ())
+#define PN_CONTAINER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_CONTAINER, PnContainer))
+#define PN_CONTAINER_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_CONTAINER, PnContainerClass))
+#define PN_IS_CONTAINER(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_CONTAINER))
+#define PN_IS_CONTAINER_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_CONTAINER))
+#define PN_CONTAINER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_CONTAINER, PnContainerClass))
+
+#define PN_CONTAINER_ACTUATORS(obj)    (PN_CONTAINER (obj)->actuators)
+
+typedef struct _PnContainer        PnContainer;
+typedef struct _PnContainerClass   PnContainerClass;
+
+struct _PnContainer
+{
+  PnActuator parent;
+
+  GArray *actuators; /* read-only */
+};
+
+struct _PnContainerClass
+{
+  PnActuatorClass parent_class;
+
+  gboolean (* add_actuator) (PnContainer *container,
+			     PnActuator *actuator,
+			     gint position);
+};
+
+/* Creators */
+GType                 pn_container_get_type                (void);
+
+/* Actions */
+gboolean              pn_container_add_actuator            (PnContainer *container,
+							    PnActuator *actuator,
+							    gint position);
+void                  pn_container_remove_actuator         (PnContainer *container,
+							    PnActuator *actuator);
+void                  pn_container_remove_all_actuators    (PnContainer *container);
+
+
+
+
+
+#endif /* __PN_CONTAINER_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pncpu.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,95 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pncpu.h"
+
+static guint cpu_caps = 0;
+static gboolean pn_cpu_ready = FALSE;
+
+#if defined PN_USE_CPU_IA32
+#define pn_cpu_init_arch pn_cpu_init_ia32
+void
+pn_cpu_init_ia32 (void)
+{
+  gboolean AMD = FALSE;
+  guint eax, ebx, ecx, edx;
+
+  /* GCC won't acknowledge the fact that I'm clobbering ebx, so just save it */
+#define CPUID __asm__ __volatile__ ("pushl %%ebx\n\tcpuid\n\tmovl %%ebx,%1\n\tpopl %%ebx" \
+				    :"+a"(eax),"=r"(ebx),"=c"(ecx),"=d"(edx)::"ebx");
+
+  eax = 0;
+  CPUID;
+
+  AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
+
+  eax = 1;
+  CPUID;
+
+  if (edx & (1 << 23))
+    cpu_caps |= PN_CPU_CAP_MMX;
+
+  if (edx & (1 << 25))
+    {
+      cpu_caps |= PN_CPU_CAP_MMXEXT;
+      cpu_caps |= PN_CPU_CAP_SSE;
+    }
+
+  eax = 0x80000000;
+  CPUID;
+
+  if (eax >= 0x80000001)
+    {
+      eax = 0x80000001;
+      CPUID;
+
+      if (edx & (1 << 31))
+	cpu_caps |= PN_CPU_CAP_3DNOW;
+      if (AMD && (edx & (1 << 22)))
+	cpu_caps |= PN_CPU_CAP_MMXEXT;
+    }
+#undef CPUID
+}
+#else /* Architecture */
+void
+pn_cpu_init_arch (void)
+{
+}
+#endif /* Architecture */
+
+void
+pn_cpu_init (void)
+{
+  if (pn_cpu_ready)
+    return;
+
+  pn_cpu_init_arch ();
+
+  pn_cpu_ready = TRUE;
+}
+
+guint
+pn_cpu_get_caps (void)
+{
+  pn_cpu_init ();
+
+  return cpu_caps;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pncpu.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,33 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_CPU_H__
+#define __PN_CPU_H__
+
+typedef enum
+{
+  PN_CPU_CAP_MMX    = (1<<0),
+  PN_CPU_CAP_MMXEXT = (1<<1),
+  PN_CPU_CAP_SSE   =  (1<<2),
+  PN_CPU_CAP_3DNOW =  (1<<3)
+} PnCPUCaps;
+
+void               pn_cpu_init                             (void);
+guint              pn_cpu_get_caps                         (void);
+
+#endif /* __PN_CPU_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pndisplacement.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,423 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <math.h>
+#include <glib.h>
+#include "pndisplacement.h"
+#include "pnbooleanoption.h"
+#include "pnstringoption.h"
+#include "pncpu.h"
+
+enum
+{
+  PN_PIXEL_DISPLACEMENT_NO_PIXEL = 0xffffffff
+};
+
+static void         pn_displacement_class_init       (PnDisplacementClass *class);
+static void         pn_displacement_init             (PnDisplacement *displacement,
+						     PnDisplacementClass *class);
+/* PnObject signals */
+static void         pn_displacement_destroy          (PnObject *object);
+
+/* PnActuator methods */
+static void         pn_displacement_prepare          (PnDisplacement *displacement,
+						     PnImage *image);
+static void         pn_displacement_execute          (PnDisplacement *displacement,
+						     PnImage *image,
+						     PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_displacement_get_type (void)
+{
+  static GType displacement_type = 0;
+
+  if (! displacement_type)
+    {
+      static const GTypeInfo displacement_info =
+      {
+	sizeof (PnDisplacementClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_displacement_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnDisplacement),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_displacement_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      displacement_type = g_type_register_static (PN_TYPE_ACTUATOR,
+						 "PnDisplacement",
+						 &displacement_info,
+						 0);
+    }
+  return displacement_type;
+}
+
+static void
+pn_displacement_class_init (PnDisplacementClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnObject signals */
+  object_class->destroy = pn_displacement_destroy;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_displacement_prepare;
+  actuator_class->execute = (PnActuatorExecFunc) pn_displacement_execute;
+}
+
+static void
+pn_displacement_init (PnDisplacement *displacement, PnDisplacementClass *class)
+{
+  PnStringOption *init_script_opt, *frame_script_opt;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (displacement), "Transform.Displacement");
+  pn_user_object_set_description (PN_USER_OBJECT (displacement),
+				  "Displaces the image");
+
+  /* Set up the options */
+  init_script_opt = pn_string_option_new ("init_script", "The initialization script");
+  frame_script_opt = pn_string_option_new ("frame_script", "The per-frame script");
+
+  pn_actuator_add_option (PN_ACTUATOR (displacement), PN_OPTION (init_script_opt));
+  pn_actuator_add_option (PN_ACTUATOR (displacement), PN_OPTION (frame_script_opt));
+
+  /* Create the script objects and symbol table */
+  displacement->init_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (displacement->init_script));
+  pn_object_sink (PN_OBJECT (displacement->init_script));
+  displacement->frame_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (displacement->frame_script));
+  pn_object_sink (PN_OBJECT (displacement->frame_script));
+  displacement->symbol_table = pn_symbol_table_new ();
+  pn_object_ref (PN_OBJECT (displacement->symbol_table));
+  pn_object_sink (PN_OBJECT (displacement->symbol_table));
+
+  /* Get the variables from the symbol table */
+  displacement->x_var = pn_symbol_table_ref_variable_by_name (displacement->symbol_table, "x");
+  displacement->y_var = pn_symbol_table_ref_variable_by_name (displacement->symbol_table, "y");
+  displacement->volume_var = pn_symbol_table_ref_variable_by_name (displacement->symbol_table, "volume");
+}
+
+static void
+pn_displacement_destroy (PnObject *object)
+{
+  PnDisplacement *displacement;
+
+  displacement = (PnDisplacement *) object;
+
+  pn_object_unref (PN_OBJECT (displacement->init_script));
+  pn_object_unref (PN_OBJECT (displacement->frame_script));
+  pn_object_unref (PN_OBJECT (displacement->symbol_table));
+}
+
+/* FIXME: optimize this */
+static void
+pn_displacement_prepare (PnDisplacement *displacement, PnImage *image)
+{
+  PnStringOption *init_script_opt, *frame_script_opt;
+
+  g_return_if_fail (displacement != NULL);
+  g_return_if_fail (PN_IS_DISPLACEMENT (displacement));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  /* Parse the script strings */
+  init_script_opt =
+    (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (displacement),
+							PN_DISPLACEMENT_OPT_INIT_SCRIPT);
+  frame_script_opt =
+    (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (displacement),
+							PN_DISPLACEMENT_OPT_FRAME_SCRIPT);
+
+  pn_script_parse_string (displacement->init_script, displacement->symbol_table,
+			  pn_string_option_get_value (init_script_opt));
+  pn_script_parse_string (displacement->frame_script, displacement->symbol_table,
+			  pn_string_option_get_value (frame_script_opt));
+
+  /* Set up 0 displacement */
+  PN_VARIABLE_VALUE (displacement->x_var) = 0.0;
+  PN_VARIABLE_VALUE (displacement->y_var) = 0.0;
+
+  /* Run the init script */
+  pn_script_execute (displacement->init_script);
+
+  if (PN_ACTUATOR_CLASS (parent_class)->prepare)
+    PN_ACTUATOR_CLASS (parent_class)->prepare (PN_ACTUATOR (displacement), image);
+}
+
+static void
+pn_displacement_exec (PnImage *image, gint offset, guint nw, guint ne, guint sw, guint se,
+		      gint startx, gint starty, gint endx, gint endy)
+{
+  gint i, j, width, height, stride;
+  PnColor *src, *dest, zero = {0,0,0,0};
+  guint r, g, b;
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+
+  src = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+
+  for (j=0; j<height; j++)
+    for (i=0; i<width; i++)
+      {
+	if (i < startx || i >= endx
+	    || j < starty || j >= endy)
+	  dest[j * stride + i] = zero;
+	else
+	  {
+	    r = src[(j * stride + i) + offset].red * nw;
+	    g = src[(j * stride + i) + offset].green * nw;
+	    b = src[(j * stride + i) + offset].blue * nw;
+
+	    r += src[(j * stride + (i + 1)) + offset].red * ne;
+	    g += src[(j * stride + (i + 1)) + offset].green * ne;
+	    b += src[(j * stride + (i + 1)) + offset].blue * ne;
+
+	    r += src[((j + 1) * stride + i) + offset].red * sw;
+	    g += src[((j + 1) * stride + i) + offset].green * sw;
+	    b += src[((j + 1) * stride + i) + offset].blue * sw;
+
+	    r += src[((j + 1) * stride + (i + 1)) + offset].red * se;
+	    g += src[((j + 1) * stride + (i + 1)) + offset].green * se;
+	    b += src[((j + 1) * stride + (i + 1)) + offset].blue * se;
+
+	    dest[j * stride + i].red = r >> 7;
+	    dest[j * stride + i].green = g >> 7;
+	    dest[j * stride + i].blue = b >> 7;
+	  }
+      }
+}
+
+#ifdef PN_USE_MMX
+static void
+pn_displacement_exec_mmx (PnImage *image, gint offset, guint nw, guint ne, guint sw, guint se,
+			  gint startx, gint starty, gint endx, gint endy)
+{
+  PnColor *src, *dest, *endptr;
+  gint width, height, stride, i;
+  guint64 upnw; /* a place to store the unpacked se weight */
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+
+  src = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+
+  memset (dest, 0, pn_image_get_pitch (image) * starty);
+  for (i=MAX(starty, 0); i<endy; i++)
+    {
+      memset (dest + i * stride, 0, startx * sizeof (PnColor));
+      memset (dest + i * stride + endx, 0, (width - endx) * sizeof (PnColor));
+    }
+  memset (dest + endy * stride, 0, (height - endy) * pn_image_get_pitch (image));
+
+  src += (starty * stride) + offset;
+  endptr = src + endx;
+  src += startx;
+  dest += (starty * stride) + startx;
+
+  __asm__ __volatile__ (
+			/* Unpack the weights */
+			"pxor %%mm7,%%mm7\n\t"          /* zero mm7 for unpacking */
+			"movd %8,%%mm4\n\t"             /* load the weights */
+			"punpcklbw %%mm7,%%mm4\n\t"     /* unpack the weights to words */
+			"movq %%mm4,%%mm6\n\t"          /* copy the weights for separate expansion */
+			"punpcklwd %%mm4,%%mm4\n\t"     /* expand the top weights */
+			"punpckhwd %%mm6,%%mm6\n\t"     /* expand the bottom weights */
+			"movq %%mm4,%%mm5\n\t"          /* copy the top pixels for separate expansion */
+			"movq %%mm6,%%mm7\n\t"          /* copy the bottom pixels for separate expansion */
+			"punpckldq %%mm4,%%mm4\n\t"     /* expand the NW weight */
+			"punpckhdq %%mm5,%%mm5\n\t"     /* expand the NE weight */
+			"punpckldq %%mm6,%%mm6\n\t"     /* expand the SW weight */
+			"punpckhdq %%mm7,%%mm7\n\t"     /* expand the SE weight */
+			"movq %%mm7,%4\n\t"             /* save the SE weight so we can use mm7 as 0 */
+			"pxor %%mm7,%%mm7\n\t"          /* re-zero mm7 */
+
+			"10:\n\t"
+
+			/* zero mm7 for unpacking */
+			"pxor %%mm7,%%mm7\n\t"
+
+			/* load & unpack the pixels */
+			"movd (%0),%%mm0\n\t"
+			"punpcklbw %%mm7,%%mm0\n\t"
+			"movd 4(%0),%%mm1\n\t"
+			"punpcklbw %%mm7,%%mm1\n\t"
+			"movd (%0,%5),%%mm2\n\t"
+			"punpcklbw %%mm7,%%mm2\n\t"
+			"movd 4(%0,%5),%%mm3\n\t"
+			"punpcklbw %%mm7,%%mm3\n\t"
+
+			/* reload the unpacked se weight */
+			"movq %4,%%mm7\n\t"
+
+			/* weight each pixel */
+			"pmullw %%mm4,%%mm0\n\t"
+			"pmullw %%mm5,%%mm1\n\t"
+			"pmullw %%mm6,%%mm2\n\t"
+			"pmullw %%mm7,%%mm3\n\t"
+
+			/* add up the weighted pixels */
+			"paddw %%mm1,%%mm0\n\t"
+			"paddw %%mm2,%%mm0\n\t"
+			"paddw %%mm3,%%mm0\n\t"
+
+			/* normalize the resulting pixel, pack it, and write it */
+			"psrlw $7,%%mm0\n\t"
+			"packuswb %%mm0,%%mm0\n\t"
+			"movd %%mm0,(%1)\n\t"
+
+			/* advance the pointers */
+			"addl $4,%0\n\t"
+			"addl $4,%1\n\t"
+
+			/* see if we're done with this line */
+			"cmpl %3,%0\n\t"
+			"jl 10b\n\t"
+
+			/* advance the pointers */
+			"addl %7,%0\n\t"
+			"addl %7,%1\n\t"
+			"addl %5,%3\n\t"
+
+			/* see if we're done */
+			"incl %2\n\t"
+			"cmpl %6,%2\n\t"
+			"jl 10b\n\t"
+
+			"emms\n\t"
+
+			: /* no outputs */
+			: "r" (src), /* 0 */
+			"r" (dest), /* 1 */
+			"r" (starty), /* 2 */
+			"m" (endptr), /* 3 */
+			"m" (upnw), /* 4 */
+			"r" (pn_image_get_pitch (image)),  /* 5 */
+			"r" (endy), /* 6 */
+			"rm" (((stride - endx) + startx) * sizeof (PnColor)), /* 7 */
+			"rm" ((guint32)((se << 24) | (sw << 16) | (ne << 8) | nw ))); /* 8 */
+}
+#endif /* PN_USE_MMX */
+
+static void
+pn_displacement_execute (PnDisplacement *displacement, PnImage *image, PnAudioData *audio_data)
+{
+  g_return_if_fail (displacement != NULL);
+  g_return_if_fail (PN_IS_DISPLACEMENT (displacement));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+  /* set up the volume in-script variable */
+  PN_VARIABLE_VALUE (displacement->volume_var) = pn_audio_data_get_volume (audio_data);
+
+  /* run the frame scipt */
+  pn_script_execute (displacement->frame_script);
+
+  if (fabs (PN_VARIABLE_VALUE (displacement->x_var)) <= 2.0
+      && fabs (PN_VARIABLE_VALUE (displacement->y_var)) <= 2.0)
+    {
+      guint nw, ne, sw, se;
+      gint startx, starty, endx, endy;
+      gint offset;
+      gdouble x, y, xfrac, yfrac;
+
+      x = -PN_VARIABLE_VALUE (displacement->x_var) * (pn_image_get_width (image) >> 1);
+      y = PN_VARIABLE_VALUE (displacement->y_var) * (pn_image_get_height (image) >> 1);
+
+      xfrac = modf (x, &x);
+      yfrac = modf (y, &y);
+
+      if (x < 0.0 || xfrac < 0.0)
+	{
+	  x--;
+	  xfrac++;
+	}
+      if (y < 0.0 || yfrac < 0.0)
+	{
+	  y--;
+	  yfrac++;
+	}
+
+      se = xfrac * yfrac * 128.0;
+      sw = (1.0 - xfrac) * yfrac * 128.0;
+      ne = xfrac * (1.0 - yfrac) * 128.0;
+      nw = 128 - (se + sw + ne);
+
+      offset = (y * (pn_image_get_pitch (image) >> 2)) + x;
+
+      startx = -x;
+      starty = -y;
+      endx = pn_image_get_width (image) - (x+1);
+      endy = pn_image_get_height (image) - (y+1);
+
+      startx = MAX (startx, 0);
+      starty = MAX (starty, 0);
+      endx = MIN (endx, pn_image_get_width (image));
+      endy = MIN (endy, pn_image_get_height (image));
+
+      /* I'm too lazy to special case the rightmost & bottommost pixels */
+      if (endx == pn_image_get_width (image))
+	endx--;
+      if (endy == pn_image_get_height (image))
+	endy--;
+      
+#ifdef PN_USE_MMX
+      if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+	pn_displacement_exec_mmx (image, offset, nw, ne, sw, se, startx, starty, endx, endy);
+      else
+#endif /* PN_USE_MMX */
+	pn_displacement_exec (image, offset, nw, ne, sw, se, startx, starty, endx, endy);
+    }
+  else
+    memset (pn_image_get_transform_buffer (image), 0,
+	    pn_image_get_pitch (image) * pn_image_get_height (image));
+
+  pn_image_apply_transform (image);
+
+  if (PN_ACTUATOR_CLASS (parent_class)->execute)
+    PN_ACTUATOR_CLASS (parent_class)->execute (PN_ACTUATOR (displacement), image, audio_data);
+}
+
+PnDisplacement*
+pn_displacement_new (void)
+{
+  return (PnDisplacement *) g_object_new (PN_TYPE_DISPLACEMENT, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pndisplacement.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,71 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_DISPLACEMENT_H__
+#define __PN_DISPLACEMENT_H__
+
+#include "pnactuator.h"
+#include "pnscript.h"
+#include "pnsymboltable.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_DISPLACEMENT_OPT_INIT_SCRIPT = PN_ACTUATOR_OPT_LAST,
+  PN_DISPLACEMENT_OPT_FRAME_SCRIPT,
+  PN_DISPLACEMENT_OPT_LAST
+};
+
+#define PN_TYPE_DISPLACEMENT              (pn_displacement_get_type ())
+#define PN_DISPLACEMENT(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_DISPLACEMENT, PnDisplacement))
+#define PN_DISPLACEMENT_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_DISPLACEMENT, PnDisplacementClass))
+#define PN_IS_DISPLACEMENT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_DISPLACEMENT))
+#define PN_IS_DISPLACEMENT_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_DISPLACEMENT))
+#define PN_DISPLACEMENT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_DISPLACEMENT, PnDisplacementClass))
+
+typedef struct _PnDisplacement        PnDisplacement;
+typedef struct _PnDisplacementClass   PnDisplacementClass;
+
+struct _PnDisplacement
+{
+  PnActuator parent;
+
+  /* The script objects */
+  PnScript *init_script;
+  PnScript *frame_script;
+  PnSymbolTable *symbol_table;
+
+  /* The in-script variables */
+  PnVariable *x_var;
+  PnVariable *y_var;
+  PnVariable *volume_var;
+};
+
+struct _PnDisplacementClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                  pn_displacement_get_type                (void);
+PnDisplacement        *pn_displacement_new                     (void);
+
+#endif /* __PN_DISPLACEMENT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pndistortion.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,440 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <math.h>
+#include <glib.h>
+#include "pndistortion.h"
+#include "pnbooleanoption.h"
+#include "pnstringoption.h"
+#include "pncpu.h"
+
+enum
+{
+  PN_PIXEL_DISTORTION_NO_PIXEL = 0xffffffff
+};
+
+static void         pn_distortion_class_init       (PnDistortionClass *class);
+static void         pn_distortion_init             (PnDistortion *distortion,
+						     PnDistortionClass *class);
+/* GObject methods */
+static void         pn_distortion_finalize         (GObject *gobject);
+
+/* PnObject signals */
+static void         pn_distortion_destroy          (PnObject *object);
+
+/* PnActuator methods */
+static void         pn_distortion_prepare          (PnDistortion *distortion,
+						     PnImage *image);
+static void         pn_distortion_execute          (PnDistortion *distortion,
+						     PnImage *image,
+						     PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_distortion_get_type (void)
+{
+  static GType distortion_type = 0;
+
+  if (! distortion_type)
+    {
+      static const GTypeInfo distortion_info =
+      {
+	sizeof (PnDistortionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_distortion_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnDistortion),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_distortion_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      distortion_type = g_type_register_static (PN_TYPE_ACTUATOR,
+						 "PnDistortion",
+						 &distortion_info,
+						 0);
+    }
+  return distortion_type;
+}
+
+static void
+pn_distortion_class_init (PnDistortionClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* GObject methods */
+  gobject_class->finalize = pn_distortion_finalize;
+
+  /* PnObject signals */
+  object_class->destroy = pn_distortion_destroy;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_distortion_prepare;
+  actuator_class->execute = (PnActuatorExecFunc) pn_distortion_execute;
+}
+
+static void
+pn_distortion_init (PnDistortion *distortion, PnDistortionClass *class)
+{
+  PnBooleanOption *polar_coords_opt;
+  PnStringOption *distortion_script_opt;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (distortion), "Transform.Distortion");
+  pn_user_object_set_description (PN_USER_OBJECT (distortion),
+				  "Perform a distortion on all the points in the image");
+
+  /* Set up the options */
+  polar_coords_opt = pn_boolean_option_new ("polar_coords", "Whether or not to use polar coordinates "
+					    "in the distortion script");
+  distortion_script_opt = pn_string_option_new ("distortion_script", "A script specifying the "
+						 "distortion to be done at each point");
+
+  pn_actuator_add_option (PN_ACTUATOR (distortion), PN_OPTION (polar_coords_opt));
+  pn_actuator_add_option (PN_ACTUATOR (distortion), PN_OPTION (distortion_script_opt));
+
+  /* Create the script object and symbol table */
+  distortion->distortion_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (distortion->distortion_script));
+  pn_object_sink (PN_OBJECT (distortion->distortion_script));
+  distortion->symbol_table = pn_symbol_table_new ();
+  pn_object_ref (PN_OBJECT (distortion->symbol_table));
+  pn_object_sink (PN_OBJECT (distortion->symbol_table));
+
+  /* Get the variables from the symbol table */
+  distortion->x_var = pn_symbol_table_ref_variable_by_name (distortion->symbol_table, "x");
+  distortion->y_var = pn_symbol_table_ref_variable_by_name (distortion->symbol_table, "y");
+  distortion->r_var = pn_symbol_table_ref_variable_by_name (distortion->symbol_table, "r");
+  distortion->theta_var = pn_symbol_table_ref_variable_by_name (distortion->symbol_table, "theta");
+  distortion->intensity_var = pn_symbol_table_ref_variable_by_name (distortion->symbol_table, "intensity");
+}
+
+static void
+pn_distortion_finalize (GObject *gobject)
+{
+  PnDistortion *distortion;
+
+  distortion = (PnDistortion *) gobject;
+
+  if (distortion->map)
+    g_free (distortion->map);
+
+  if (G_OBJECT_CLASS (parent_class)->finalize)
+    G_OBJECT_CLASS (parent_class)->finalize (gobject);
+}
+
+static void
+pn_distortion_destroy (PnObject *object)
+{
+  PnDistortion *distortion;
+
+  distortion = (PnDistortion *) object;
+
+  pn_object_unref (PN_OBJECT (distortion->distortion_script));
+  pn_object_unref (PN_OBJECT (distortion->symbol_table));
+}  
+
+/* FIXME: optimize this */
+static void
+pn_distortion_prepare (PnDistortion *distortion, PnImage *image)
+{
+  PnBooleanOption *polar_coords_opt;
+  PnStringOption *distortion_script_opt;
+  gboolean polar;
+  guint width, stride, height;
+  guint i, j;
+  gdouble half_width, neg_half_height;
+  gdouble xfrac, yfrac;
+  gdouble x, y;
+
+  g_return_if_fail (distortion != NULL);
+  g_return_if_fail (PN_IS_DISTORTION (distortion));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  /* Parse the script strings */
+  distortion_script_opt =
+    (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (distortion),
+							PN_DISTORTION_OPT_DISTORTION_SCRIPT);
+
+  pn_script_parse_string (distortion->distortion_script,
+			  distortion->symbol_table,
+			  pn_string_option_get_value (distortion_script_opt));
+
+  /* Set up the new pixel distortion map */
+  if (distortion->map)
+    g_free (distortion->map);
+
+  polar_coords_opt =
+    (PnBooleanOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (distortion),
+							 PN_DISTORTION_OPT_POLAR_COORDS);
+  polar = pn_boolean_option_get_value (polar_coords_opt);
+  width = pn_image_get_width (image);
+  stride = pn_image_get_pitch (image) >> 2;
+  height = pn_image_get_height (image);
+
+  half_width = (((gdouble) width) - 1.0) * 0.5;
+  neg_half_height = (((gdouble) height) - 1.0) * -0.5;
+
+  distortion->map = g_new (PnPixelDistortion, width * height);
+
+  for (j=0; j < height; j++)
+    for (i=0; i < width; i++)
+      {
+	PN_VARIABLE_VALUE (distortion->x_var) = (((gdouble) i) / half_width) - 1.0;
+	PN_VARIABLE_VALUE (distortion->y_var) = (((gdouble) j) / neg_half_height) + 1.0;
+	PN_VARIABLE_VALUE (distortion->r_var) =
+	  sqrt ((PN_VARIABLE_VALUE (distortion->x_var) * PN_VARIABLE_VALUE (distortion->x_var))
+		+ (PN_VARIABLE_VALUE (distortion->y_var) * PN_VARIABLE_VALUE (distortion->y_var)));
+	if (PN_VARIABLE_VALUE (distortion->r_var) != 0)
+	  {
+	    PN_VARIABLE_VALUE (distortion->theta_var) = acos (PN_VARIABLE_VALUE (distortion->x_var)
+							       / PN_VARIABLE_VALUE (distortion->r_var));
+	    if (PN_VARIABLE_VALUE (distortion->y_var) < 0)
+	      PN_VARIABLE_VALUE (distortion->theta_var) = 2.0 * G_PI
+		- PN_VARIABLE_VALUE (distortion->theta_var);
+	  }
+	else
+	  PN_VARIABLE_VALUE (distortion->theta_var) = 0.0;
+	PN_VARIABLE_VALUE (distortion->intensity_var) = 1.0;
+
+	pn_script_execute (distortion->distortion_script);
+
+	if (polar)
+	  {
+	    PN_VARIABLE_VALUE (distortion->x_var) = PN_VARIABLE_VALUE (distortion->r_var)
+	      * cos (PN_VARIABLE_VALUE (distortion->theta_var));
+	    PN_VARIABLE_VALUE (distortion->y_var) = PN_VARIABLE_VALUE (distortion->r_var)
+	      * sin (PN_VARIABLE_VALUE (distortion->theta_var));
+	  }
+
+	if (PN_VARIABLE_VALUE (distortion->x_var) <= 1.0
+	    && PN_VARIABLE_VALUE (distortion->x_var) >= -1.0
+	    && PN_VARIABLE_VALUE (distortion->y_var) <= 1.0
+	    && PN_VARIABLE_VALUE (distortion->y_var) >= -1.0)
+	  {
+	    x = (PN_VARIABLE_VALUE (distortion->x_var) + 1.0) * half_width;
+	    xfrac = modf (x, &x);
+	    yfrac = modf ((PN_VARIABLE_VALUE (distortion->y_var) - 1.0) * neg_half_height, &y);
+
+	    distortion->map[i + (j * width)].offset =  ((guint) x) + (((guint) y) * stride);
+
+	    PN_VARIABLE_VALUE (distortion->intensity_var) =
+	      CLAMP (PN_VARIABLE_VALUE (distortion->intensity_var), 0.0, 1.0);
+
+	    distortion->map[i + (j * width)].se = xfrac * yfrac * 128.0 *
+	      PN_VARIABLE_VALUE (distortion->intensity_var);
+	    distortion->map[i + (j * width)].sw = (1.0 - xfrac) * yfrac * 128.0 *
+	      PN_VARIABLE_VALUE (distortion->intensity_var);
+	    distortion->map[i + (j * width)].ne = xfrac * (1.0 - yfrac) * 128.0 *
+	      PN_VARIABLE_VALUE (distortion->intensity_var);
+	    distortion->map[i + (j * width)].nw = (128.0 * PN_VARIABLE_VALUE (distortion->intensity_var))
+	      - (distortion->map[i + (j * width)].se
+		 + distortion->map[i + (j * width)].sw
+		 + distortion->map[i + (j * width)].ne);
+	  }
+	else
+	  distortion->map[i + (j * stride)].offset = PN_PIXEL_DISTORTION_NO_PIXEL;
+      }
+
+  if (parent_class->prepare)
+    parent_class->prepare (PN_ACTUATOR (distortion), image);
+}
+
+static inline void
+pn_distortion_translate (PnDistortion *distortion, PnImage *image)
+{
+  register PnPixelDistortion *pixtrans;
+  register PnColor *src;
+  PnColor *dest, *src_start;
+  guint i, j;
+  guint width, stride, height;
+  register guint red_sum, green_sum, blue_sum;
+
+  pixtrans = distortion->map;
+  src_start = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+
+  width = pn_image_get_width (image);
+  stride = pn_image_get_pitch (image) >> 2;
+  height = pn_image_get_height (image);
+
+  for (j=0; j < height; j++)
+    {
+      for (i=0; i < width; i++)
+	{
+	  if (pixtrans->offset != PN_PIXEL_DISTORTION_NO_PIXEL)
+	    {
+	      src = src_start + pixtrans->offset;
+
+	      red_sum = src->red * pixtrans->nw;
+	      green_sum = src->green * pixtrans->nw;
+	      blue_sum = src->blue * pixtrans->nw;
+
+	      src++;
+
+	      red_sum += src->red * pixtrans->ne;
+	      green_sum += src->green * pixtrans->ne;
+	      blue_sum += src->blue * pixtrans->ne;
+
+	      src += stride;
+
+	      red_sum += src->red * pixtrans->se;
+	      green_sum += src->green * pixtrans->se;
+	      blue_sum += src->blue * pixtrans->se;
+
+	      src--;
+
+	      red_sum += src->red * pixtrans->sw;
+	      green_sum += src->green * pixtrans->sw;
+	      blue_sum += src->blue * pixtrans->sw;
+
+	      dest->red = (guchar) (red_sum >> 7);
+	      dest->green = (guchar) (green_sum >> 7);
+	      dest->blue = (guchar) (blue_sum >> 7);
+	    }
+	  else
+	    *((gulong *)dest) = 0;
+
+	  pixtrans++;
+	  dest++;
+	}
+      dest += stride - width;
+    }
+}
+
+#ifdef PN_USE_MMX
+static inline void
+pn_distortion_translate_mmx (PnDistortion *distortion, PnImage *image)
+{
+  __asm__ __volatile__ (
+			".align 16\n"                   /* The start of the loop */
+			"10:\n\t"
+
+			"pxor %%mm7,%%mm7\n\t"          /* zero the reg for unpacking */
+
+			"movd (%0,%2,4),%%mm0\n\t"      /* load the NW pixel */
+			"movd 4(%0,%2,4),%%mm1\n\t"     /* load the NE pixel */
+			"addl %6,%2\n\t"                /* advance the offset to the next line */
+			"movd (%0,%2,4),%%mm2\n\t"      /* load the SW pixel */
+			"movd 4(%0,%2,4),%%mm3\n\t"     /* load the SE pixel */
+
+			"punpcklbw %%mm7,%%mm0\n\t"     /* unpack the NW pixel */
+			"punpcklbw %%mm7,%%mm1\n\t"     /* unpack the NE pixel */
+			"punpcklbw %%mm7,%%mm2\n\t"     /* unpack the SW pixel */
+			"punpcklbw %%mm7,%%mm3\n\t"     /* unpack the SE pixel */
+
+			"movd 4(%4),%%mm4\n\t"          /* load the weights */
+			"punpcklbw %%mm7,%%mm4\n\t"     /* unpack the weights to words */
+			"movq %%mm4,%%mm6\n\t"          /* copy the weights for separate expansion */
+			"punpcklwd %%mm4,%%mm4\n\t"     /* expand the top weights */
+			"punpckhwd %%mm6,%%mm6\n\t"     /* expand the bottom weights */
+			"movq %%mm4,%%mm5\n\t"          /* copy the top pixels for separate expansion */
+			"movq %%mm6,%%mm7\n\t"          /* copy the bottom pixels for separate expansion */
+			"punpckldq %%mm4,%%mm4\n\t"     /* expand the NW weight */
+			"punpckhdq %%mm5,%%mm5\n\t"     /* expand the NE weight */
+			"punpckldq %%mm6,%%mm6\n\t"     /* expand the SW weight */
+			"punpckhdq %%mm7,%%mm7\n\t"     /* expand the SE weight */
+
+			"pmullw %%mm4,%%mm0\n\t"        /* weight the NW pixel */
+			"pmullw %%mm5,%%mm1\n\t"        /* weight the NE pixel */
+			"pmullw %%mm6,%%mm2\n\t"        /* weight the SW pixel */
+			"pmullw %%mm7,%%mm3\n\t"        /* weight the SE pixel */
+
+			"paddusw %%mm1,%%mm0\n\t"       /* sum up the weighted pixels */
+			"paddusw %%mm2,%%mm0\n\t"
+			"paddusw %%mm3,%%mm0\n\t"
+
+			"addl $4,%1\n\t"                /* advance the dest pointer */
+
+			"psrlw $7,%%mm0\n\t"            /* divide the sums by 128 */
+			"packuswb %%mm0,%%mm0\n\t"      /* pack up the resulting pixel */
+			"movd %%mm0,(%1)\n\t"           /* write the pixel */
+			
+
+			"addl $8,%4\n\t"                /* advance the map pointer */
+			"movl (%4),%2\n\t"              /* load the next offset */
+
+			"dec %3\n\t"                    /* advance the inverse column counter */
+			"jg 10b\n\t"
+
+			"shll $2,%5\n\t"                /* get the width/stride in bytes */
+			"shll $2,%6\n\t"
+			"addl %6,%1\n\t"                /* add (stride - width) to the dest */
+			"subl %5,%1\n\t"
+			"shrl $2,%5\n\t"                /* revert width/stride to pixels */
+			"shrl $2,%6\n\t"
+			"movl %5,%3\n\t"                /* reset the inverse column counter */
+
+			"cmpl %7,%1\n\t"                /* see if we're done */
+			"jl 10b\n\t"
+
+			"emms\n\t"
+			:
+			:
+			"r" (pn_image_get_image_buffer (image)),
+			"r" (pn_image_get_transform_buffer (image) - 1),
+			"r" (distortion->map->offset),
+			"r" (pn_image_get_width (image)),
+			"r" (distortion->map),
+			"m" (pn_image_get_width (image)),
+			"m" (pn_image_get_pitch (image) >> 2),
+			"m" (pn_image_get_transform_buffer (image)
+			     + ((pn_image_get_pitch (image) >> 2) * (pn_image_get_height (image) - 1))));
+}
+#endif /* PN_USE_MMX */
+
+static void
+pn_distortion_execute (PnDistortion *distortion, PnImage *image, PnAudioData *audio_data)
+{
+  g_return_if_fail (distortion != NULL);
+  g_return_if_fail (PN_IS_DISTORTION (distortion));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+#ifdef PN_USE_MMX
+  if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+    pn_distortion_translate_mmx (distortion, image);
+  else
+#endif /* PN_USE_MMX */
+    pn_distortion_translate (distortion, image);
+
+  pn_image_apply_transform (image);
+}
+
+PnDistortion*
+pn_distortion_new (void)
+{
+  return (PnDistortion *) g_object_new (PN_TYPE_DISTORTION, NULL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pndistortion.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,85 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_DISTORTION_H__
+#define __PN_DISTORTION_H__
+
+#include "pnactuator.h"
+#include "pnscript.h"
+#include "pnsymboltable.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_DISTORTION_OPT_POLAR_COORDS = PN_ACTUATOR_OPT_LAST,
+  PN_DISTORTION_OPT_DISTORTION_SCRIPT,
+  PN_DISTORTION_OPT_LAST
+};
+
+#define PN_TYPE_DISTORTION              (pn_distortion_get_type ())
+#define PN_DISTORTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_DISTORTION, PnDistortion))
+#define PN_DISTORTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_DISTORTION, PnDistortionClass))
+#define PN_IS_DISTORTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_DISTORTION))
+#define PN_IS_DISTORTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_DISTORTION))
+#define PN_DISTORTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_DISTORTION, PnDistortionClass))
+
+typedef struct _PnPixelDistortion   PnPixelDistortion; 
+typedef struct _PnDistortion        PnDistortion;
+typedef struct _PnDistortionClass   PnDistortionClass;
+
+struct _PnPixelDistortion
+{
+  guint offset;
+  guchar nw; /* northwest weight */
+  guchar ne; /* northeast weight */
+  guchar sw; /* southwest weight */
+  guchar se; /* southeast weight */
+};
+
+struct _PnDistortion
+{
+  PnActuator parent;
+
+  /* The script objects */
+  PnScript *distortion_script;
+  PnSymbolTable *symbol_table;
+
+  /* The in-script variables */
+  PnVariable *x_var;
+  PnVariable *y_var;
+  PnVariable *r_var;
+  PnVariable *theta_var;
+  PnVariable *intensity_var;
+
+  /* Distortion map */
+  PnPixelDistortion *map;
+};
+
+struct _PnDistortionClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                 pn_distortion_get_type                (void);
+PnDistortion        *pn_distortion_new                     (void);
+
+#endif /* __PN_DISTORTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnerror.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,64 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <glib.h>
+#include "pnerror.h"
+
+static void     pn_error_default_handler        (const gchar *str);
+
+static PnErrorFunc error_func = pn_error_default_handler;
+
+static void
+pn_error_default_handler (const gchar *str)
+{
+  g_log ("paranormal", G_LOG_LEVEL_WARNING, str);
+}
+
+PnErrorFunc
+pn_error_set_handler (PnErrorFunc func)
+{
+  PnErrorFunc old_func = error_func;
+
+  if (! func)
+    error_func = pn_error_default_handler;
+  else
+    error_func = func;
+
+  return old_func;
+}
+
+void
+pn_error (const gchar *fmt, ...)
+{
+  va_list ap;
+  gchar *str;
+
+  g_return_if_fail (fmt != NULL);
+
+  va_start (ap, fmt);
+  str = g_strdup_vprintf (fmt, ap);
+  va_end (ap);
+
+  error_func (str);
+
+  g_free (str);
+}
+			  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnerror.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,30 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_ERROR_H__
+#define __PN_ERROR_H__
+
+typedef void (* PnErrorFunc) (const gchar *str);
+
+/* Accessors */
+PnErrorFunc     pn_error_set_handler        (PnErrorFunc func);
+
+/* Actions */
+void            pn_error                    (const gchar *fmt,
+					     ...);
+#endif /* __PN_ERROR_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnflip.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,436 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include "pnflip.h"
+#include "pnbooleanoption.h"
+#include "pnlistoption.h"
+#include "pncpu.h"
+
+enum
+{
+  PN_FLIP_DIRECTION_HORIZONTAL,
+  PN_FLIP_DIRECTION_VERTICAL
+};
+
+static void         pn_flip_class_init       (PnFlipClass *class);
+static void         pn_flip_init             (PnFlip *flip,
+					      PnFlipClass *class);
+/* PnActuator methods */
+static void         pn_flip_execute          (PnFlip *flip,
+					      PnImage *image,
+					      PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_flip_get_type (void)
+{
+  static GType flip_type = 0;
+
+  if (! flip_type)
+    {
+      static const GTypeInfo flip_info =
+      {
+	sizeof (PnFlipClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_flip_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnFlip),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_flip_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      flip_type = g_type_register_static (PN_TYPE_ACTUATOR,
+						 "PnFlip",
+						 &flip_info,
+						 0);
+    }
+  return flip_type;
+}
+
+static void
+pn_flip_class_init (PnFlipClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnActuator methods */
+  actuator_class->execute = (PnActuatorExecFunc) pn_flip_execute;
+}
+
+static void
+pn_flip_init (PnFlip *flip, PnFlipClass *class)
+{
+  PnBooleanOption *blend_opt;
+  PnListOption *direction_opt;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (flip), "Transform.Flip");
+  pn_user_object_set_description (PN_USER_OBJECT (flip),
+				  "Flip the image");
+
+  /* Set up the options */
+  blend_opt = pn_boolean_option_new ("blend", "Blend the flipped image with the original");
+  direction_opt = pn_list_option_new ("direction", "The direction in which the image will be flipped");
+
+  pn_list_option_add_item (direction_opt, "Horizontal");
+  pn_list_option_add_item (direction_opt, "Vertical");
+
+  pn_actuator_add_option (PN_ACTUATOR (flip), PN_OPTION (blend_opt));
+  pn_actuator_add_option (PN_ACTUATOR (flip), PN_OPTION (direction_opt));
+}
+
+static void
+pn_flip_execute_horizontal (PnImage *image)
+{
+  register guint i, j, tmp;
+  register guint32 *src, *dest;
+  guint width, height, stride;
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+
+  src = (guint32 *) pn_image_get_image_buffer (image);
+  dest = (guint32 *) pn_image_get_transform_buffer (image);
+
+  for (j=0; j<height; j++)
+    {
+      for (i=0; i<width >> 1; i++)
+	{
+	  tmp = src[j * stride + i];
+	  dest[j * stride + i] = src[j * stride + (width - (i + 1))];
+	  dest[j * stride + (width - (i + 1))] = tmp;
+	}
+      if (width & 0x1)
+	dest[j * stride + i] = src [j * stride + i];
+    }
+}
+
+static void
+pn_flip_execute_horizontal_blend (PnImage *image)
+{
+  register guint i, j;
+  register PnColor *src, *dest;
+  guint width, height, stride;
+  guint r, g, b;
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+
+  src = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+
+  for (j=0; j<height; j++)
+    {
+      for (i=0; i<width >> 1; i++)
+	{
+	  r = src[j * stride + i].red + src[j * stride + (width - (i + 1))].red;
+	  g = src[j * stride + i].green + src[j * stride + (width - (i + 1))].green;
+	  b = src[j * stride + i].blue + src[j * stride + (width - (i + 1))].blue;
+
+	  r >>= 1;
+	  g >>= 1;
+	  b >>= 1;
+
+	  dest[j * stride + i].red = dest[j * stride + (width - (i + 1))].red = r;
+	  dest[j * stride + i].green = dest[j * stride + (width - (i + 1))].green = g;
+	  dest[j * stride + i].blue = dest[j * stride + (width - (i + 1))].blue = b;
+	}
+      if (width & 0x1)
+	((guint32 *) dest)[j * stride + i] =
+	  ((guint32 *) src)[j * stride + i];
+    }
+}
+
+#ifdef PN_USE_MMX
+static void
+pn_flip_execute_horizontal_blend_mmx (PnImage *image)
+{
+  /*
+   * 0: src
+   * 1: dest
+   * 2: left index
+   * 3: right index
+   * 4: inverse line counter
+   * 5; half width
+   * 6: width
+   * 7: pitch
+   */
+
+  __asm__ __volatile__ (
+			"pxor %%mm7,%%mm7\n\t"              /* Zero mm7 */
+
+			"10:\n\t"
+
+			"movd (%0, %2, 4), %%mm0\n\t"       /* Load the two pixels */
+			"movd (%0, %3, 4), %%mm1\n\t"
+
+			"punpcklbw %%mm7, %%mm0\n\t"        /* Unpack the pixels */
+			"punpcklbw %%mm7, %%mm1\n\t"
+
+			"paddw %%mm1, %%mm0\n\t"            /* Average the pixels */
+			"psrlw $1, %%mm0\n\t"
+
+			"packuswb %%mm7, %%mm0\n\t"         /* Pack 'er up & write it*/
+			"movd %%mm0, (%1, %2, 4)\n\t"
+			"movd %%mm0, (%1, %3, 4)\n\t"
+
+			"incl %3\n\t"                       /* Advance the indexes & see if we're */
+			"decl %2\n\t"                       /* done with this line */
+			"jge 10b\n\t"
+
+			"movl %5, %2\n\t"                   /* Reset the indexes */
+			"movl %5, %3\n\t"
+			"decl %2\n\t"
+
+			"testl $0x1, %6\n\t"                 /* Do the stuff for an odd width */
+			"jz 20f\n\t"
+			"movd (%0, %3, 4), %%mm0\n\t"
+			"movd %%mm0, (%1, %3, 4)\n\t"
+			"incl %3\n\t"
+
+			"20:\n\t"
+
+			"addl %7, %0\n\t"                   /* Advance the line pointers */
+			"addl %7, %1\n\t"
+
+			"decl %4\n\t"                       /* See if we're done */
+			"jnz 10b\n\t"
+
+			"emms"
+			: /* no outputs */
+			: "r" (pn_image_get_image_buffer (image)),
+			"r" (pn_image_get_transform_buffer (image)),
+			"r" ((pn_image_get_width (image) >> 1) - 1),
+			"r" ((pn_image_get_width (image) >> 1) + (pn_image_get_width (image) & 0x1 ? 1 : 0)),
+			"rm" (pn_image_get_height (image)),
+			"rm" (pn_image_get_width (image) >> 1),
+			"rm" (pn_image_get_width (image)),
+			"rm" (pn_image_get_pitch (image))
+			);
+}
+#endif /* PN_USE_MMX */
+
+static void
+pn_flip_execute_vertical (PnImage *image)
+{
+  register guint i, j, tmp;
+  register guint32 *src, *dest;
+  guint width, height, stride;
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+
+  src = (guint32 *) pn_image_get_image_buffer (image);
+  dest = (guint32 *) pn_image_get_transform_buffer (image);
+
+  for (j=0; j<height >> 1; j++)
+    {
+      for (i=0; i<width; i++)
+	{
+	  tmp = src[j * stride + i];
+	  dest[j * stride + i] = src[(height - (j + 1)) * stride + i];
+	  dest[(height - (j + 1)) * stride + i] = tmp;
+	}
+      if (height & 0x1)
+	dest[j * stride + i] = src [j * stride + i];
+    }
+}
+
+static void
+pn_flip_execute_vertical_blend (PnImage *image)
+{
+  register guint i, j;
+  register PnColor *src, *dest;
+  guint width, height, stride;
+  guint r, g, b;
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+
+  src = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+
+  for (j=0; j<height >> 1; j++)
+    {
+      for (i=0; i<width; i++)
+	{
+	  r = src[j * stride + i].red + src[(height - (j + 1)) * stride + i].red;
+	  g = src[j * stride + i].green + src[(height - (j + 1)) * stride + i].green;
+	  b = src[j * stride + i].blue + src[(height - (j + 1)) * stride + i].blue;
+
+	  r >>= 1;
+	  g >>= 1;
+	  b >>= 1;
+
+	  dest[j * stride + i].red = dest[(height - (j + 1)) * stride + i].red = r;
+	  dest[j * stride + i].green = dest[(height - (j + 1)) * stride + i].green = g;
+	  dest[j * stride + i].blue = dest[(height - (j + 1)) * stride + i].blue = b;
+	}
+      if (height & 0x1)
+	((guint32 *) dest)[j * stride + i] =
+	  ((guint32 *) src)[j * stride + i];
+    }
+}
+
+#ifdef PN_USE_MMX
+static void
+pn_flip_execute_vertical_blend_mmx (PnImage *image)
+{
+  PnColor *src, *dest;
+  guint pitch, width, height;
+
+  src = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+  pitch = pn_image_get_pitch (image);
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+
+  /*
+   * 0: tsrc
+   * 1: bsrc
+   * 2: tdest
+   * 3: bdest
+   * 4: i
+   * 5: (half stride) - 1
+   * 6: pitch
+   * 7: src
+   */
+
+  __asm__ __volatile__ (
+			"pxor %%mm7,%%mm7\n\t"          /* Zero mm7 */
+
+			"movl %5,%4\n\t"                /* Do this so gcc doesn't make %4 and
+							 * %5 the same register
+							 */
+
+			"10:\n\t"
+
+			"movq (%0, %4, 8),%%mm0\n\t"    /* Read the pixels */
+			"movq (%1, %4, 8),%%mm2\n\t"
+			"movq %%mm0,%%mm1\n\t"
+			"movq %%mm2,%%mm3\n\t"
+
+			"punpcklbw %%mm7,%%mm0\n\t"     /* Unpack the pixels */
+			"punpckhbw %%mm7,%%mm1\n\t"
+			"punpcklbw %%mm7,%%mm2\n\t"
+			"punpckhbw %%mm7,%%mm3\n\t"
+
+			"paddw %%mm2,%%mm0\n\t"         /* Average the pixels */
+			"paddw %%mm3,%%mm1\n\t"
+			"psrlw $1,%%mm0\n\t"
+			"psrlw $1,%%mm1\n\t"
+
+			"packuswb %%mm1,%%mm0\n\t"      /* Pack & write the pixels */
+			"movq %%mm0,(%2,%4,8)\n\t"
+			"movq %%mm0,(%3,%4,8)\n\t"
+
+			"decl %4\n\t"                   /* See if we're done */
+			"jns 10b\n\t"
+
+			"movl %5,%4\n\t"                /* Reset the x-counter */
+
+			"subl %6,%0\n\t"                /* Advance the pointers */
+			"addl %6,%1\n\t"
+			"subl %6,%2\n\t"
+			"addl %6,%3\n\t"
+
+			"cmpl %7,%0\n\t"                /* See if we're done */
+			"jge 10b\n\t"
+
+			"emms"
+			: /* no outputs */
+			: "r" (src + (pitch >> 2) * ((height >> 1) - 1)),
+			"r" (src + (pitch >> 2) * ((height >> 1) + (height & 0x1 ? 1 : 0))),
+			"r" (dest + (pitch >> 2) * ((height >> 1) - 1)),
+			"r" (dest + (pitch >> 2) * ((height >> 1) + (height & 0x1 ? 1 : 0))),
+			"r" (0),
+			"rm" ((pitch >> 3) - 1),
+			"rm" (pitch),
+			"rm" (src)
+			);
+}
+#endif /* PN_USE_MMX */
+
+static void
+pn_flip_execute (PnFlip *flip, PnImage *image, PnAudioData *audio_data)
+{
+  PnBooleanOption *blend_opt;
+  PnListOption *direction_opt;
+
+  g_return_if_fail (flip != NULL);
+  g_return_if_fail (PN_IS_FLIP (flip));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+  blend_opt = (PnBooleanOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (flip), PN_FLIP_OPT_BLEND);
+  direction_opt = (PnListOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (flip), PN_FLIP_OPT_DIRECTION);
+
+  switch (pn_list_option_get_index (direction_opt))
+    {
+    case PN_FLIP_DIRECTION_HORIZONTAL:
+      if (pn_boolean_option_get_value (blend_opt))
+#ifdef PN_USE_MMX
+	if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+	  pn_flip_execute_horizontal_blend_mmx (image);
+	else
+#endif /* PN_USE_MMX */
+	  pn_flip_execute_horizontal_blend (image);
+      else
+	pn_flip_execute_horizontal (image);
+      break;
+    case PN_FLIP_DIRECTION_VERTICAL:
+      if (pn_boolean_option_get_value (blend_opt))
+#ifdef PN_USE_MMX
+	if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+	  pn_flip_execute_vertical_blend_mmx (image);
+      else
+#endif /* PN_USE_MMX */
+	pn_flip_execute_vertical_blend (image);
+      else
+	pn_flip_execute_vertical (image);
+      break;
+    }
+
+  pn_image_apply_transform (image);
+}
+
+PnFlip*
+pn_flip_new (void)
+{
+  return (PnFlip *) g_object_new (PN_TYPE_FLIP, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnflip.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,61 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_FLIP_H__
+#define __PN_FLIP_H__
+
+#include "pnactuator.h"
+#include "pnscript.h"
+#include "pnsymboltable.h"
+
+
+G_BEGIN_DECLS
+
+enum
+{
+  PN_FLIP_OPT_BLEND = PN_ACTUATOR_OPT_LAST,
+  PN_FLIP_OPT_DIRECTION,
+  PN_FLIP_OPT_LAST
+};
+
+#define PN_TYPE_FLIP              (pn_flip_get_type ())
+#define PN_FLIP(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_FLIP, PnFlip))
+#define PN_FLIP_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_FLIP, PnFlipClass))
+#define PN_IS_FLIP(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_FLIP))
+#define PN_IS_FLIP_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_FLIP))
+#define PN_FLIP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_FLIP, PnFlipClass))
+
+typedef struct _PnPixelFlip   PnPixelFlip; 
+typedef struct _PnFlip        PnFlip;
+typedef struct _PnFlipClass   PnFlipClass;
+
+struct _PnFlip
+{
+  PnActuator parent;
+};
+
+struct _PnFlipClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                 pn_flip_get_type                (void);
+PnFlip               *pn_flip_new                     (void);
+
+#endif /* __PN_FLIP_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnfloatoption.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,243 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <glib.h>
+#include "pnfloatoption.h"
+#include "pnxml.h"
+#include "pnerror.h"
+
+static void         pn_float_option_class_init       (PnFloatOptionClass *class);
+static void         pn_float_option_init             (PnFloatOption *float_option,
+							PnFloatOptionClass *class);
+
+/* PnUserObject methods */
+static void         pn_float_option_save_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+static void         pn_float_option_load_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_float_option_get_type (void)
+{
+  static GType float_option_type = 0;
+
+  if (! float_option_type)
+    {
+      static const GTypeInfo float_option_info =
+      {
+	sizeof (PnFloatOptionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_float_option_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnFloatOption),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_float_option_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      float_option_type = g_type_register_static (PN_TYPE_OPTION,
+					      "PnFloatOption",
+					      &float_option_info,
+					      0);
+    }
+  return float_option_type;
+}
+
+static void
+pn_float_option_class_init (PnFloatOptionClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnOptionClass *option_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  option_class = (PnOptionClass *) class;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_float_option_save_thyself;
+  user_object_class->load_thyself = pn_float_option_load_thyself;
+
+  /* PnOption methods */
+  /* FIXME: this needs to be uncommented when the widget is done */
+/*    option_class->widget_type = PN_TYPE_FLOAT_OPTION_WIDGET; */
+}
+
+static void
+pn_float_option_init (PnFloatOption *float_option,
+			PnFloatOptionClass *class)
+{
+  float_option->min = INT_MIN;
+  float_option->max = INT_MAX;
+}
+
+static void
+pn_float_option_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnFloatOption *float_option;
+  xmlNodePtr value_node;
+  gchar str[16];
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_FLOAT_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  float_option = (PnFloatOption *) user_object;
+
+  value_node = xmlNewChild (node, NULL, "Value", NULL);
+  sprintf (str, "%f", float_option->value);
+  xmlNodeSetContent (value_node, str);
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_float_option_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnFloatOption *float_option;
+  xmlNodePtr float_option_node;
+  gchar *val_str;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_FLOAT_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  float_option = (PnFloatOption *) user_object;
+
+  /* find the node for this class */
+  for (float_option_node = node->xmlChildrenNode;
+       float_option_node;
+       float_option_node = float_option_node->next)
+    if (g_strcasecmp (float_option_node->name, "Value") == 0)
+      break;
+  if (! float_option_node)
+    {
+      pn_error ("unable to load a PnFloatOption from xml node \"%s\"", node->name);
+      return;
+    }
+
+  val_str = xmlNodeGetContent (float_option_node);
+
+  if (val_str)
+    pn_float_option_set_value (float_option, strtod (val_str, NULL));
+  else
+    {
+      pn_error ("invalid float option value encountered at xml node \"%s\"", node->name);
+      return;
+    }
+
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+PnFloatOption*
+pn_float_option_new (const gchar *name, const gchar *desc)
+{
+  PnFloatOption *float_option;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (desc != NULL, NULL);
+
+  float_option =   (PnFloatOption *) g_object_new (PN_TYPE_FLOAT_OPTION, NULL);
+
+  pn_user_object_set_name (PN_USER_OBJECT (float_option), name);
+  pn_user_object_set_description (PN_USER_OBJECT (float_option), desc);
+
+  return float_option;
+}
+
+void
+pn_float_option_set_value (PnFloatOption *float_option, gfloat value)
+{
+  g_return_if_fail (float_option != NULL);
+  g_return_if_fail (PN_IS_FLOAT_OPTION (float_option));
+
+  float_option->value = CLAMP (value, float_option->min, float_option->max);
+}
+
+gfloat
+pn_float_option_get_value (PnFloatOption *float_option)
+{
+  g_return_val_if_fail (float_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_FLOAT_OPTION (float_option), FALSE);
+
+  return float_option->value;
+}
+
+void
+pn_float_option_set_min (PnFloatOption *float_option, gfloat min)
+{
+  g_return_if_fail (float_option != NULL);
+  g_return_if_fail (PN_IS_FLOAT_OPTION (float_option));
+
+  if (min > float_option->max)
+    {
+      float_option->min = float_option->max;
+      float_option->max = min;
+    }
+  else
+    float_option->min = min;
+
+  pn_float_option_set_value (float_option, float_option->value);
+}
+
+gfloat
+pn_float_option_get_min (PnFloatOption *float_option)
+{
+  g_return_val_if_fail (float_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_FLOAT_OPTION (float_option), FALSE);
+
+  return float_option->min;
+}
+
+void
+pn_float_option_set_max (PnFloatOption *float_option, gfloat max)
+{
+  g_return_if_fail (float_option != NULL);
+  g_return_if_fail (PN_IS_FLOAT_OPTION (float_option));
+
+  if (max < float_option->min)
+    {
+      float_option->max = float_option->min;
+      float_option->min = max;
+    }
+  else
+    float_option->max = max;
+
+  pn_float_option_set_value (float_option, float_option->value);
+}
+
+gfloat
+pn_float_option_get_max (PnFloatOption *float_option)
+{
+  g_return_val_if_fail (float_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_FLOAT_OPTION (float_option), FALSE);
+
+  return float_option->max;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnfloatoption.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,73 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_FLOAT_OPTION_H__
+#define __PN_FLOAT_OPTION_H__
+
+#include "pnoption.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_FLOAT_OPTION              (pn_float_option_get_type ())
+#define PN_FLOAT_OPTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_FLOAT_OPTION, PnFloatOption))
+#define PN_FLOAT_OPTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_FLOAT_OPTION, PnFloatOptionClass))
+#define PN_IS_FLOAT_OPTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_FLOAT_OPTION))
+#define PN_IS_FLOAT_OPTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_FLOAT_OPTION))
+#define PN_FLOAT_OPTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_FLOAT_OPTION, PnFloatOptionClass))
+
+typedef struct _PnFloatOption        PnFloatOption;
+typedef struct _PnFloatOptionClass   PnFloatOptionClass;
+
+struct _PnFloatOption
+{
+  PnOption parent;
+
+  gfloat value;
+  gfloat min;
+  gfloat max;
+};
+
+struct _PnFloatOptionClass
+{
+  PnOptionClass parent_class;
+};
+
+/* Creators */
+GType                 pn_float_option_get_type                (void);
+PnFloatOption      *pn_float_option_new                     (const gchar *name,
+								 const gchar *desc);
+
+/* Accessors */
+void                  pn_float_option_set_value               (PnFloatOption *float_option,
+								 gfloat value);
+gfloat                  pn_float_option_get_value               (PnFloatOption *float_option);
+void                  pn_float_option_set_min                 (PnFloatOption *float_option,
+								 gfloat min);
+gfloat                  pn_float_option_get_min                 (PnFloatOption *float_option);
+void                  pn_float_option_set_max                 (PnFloatOption *float_option,
+								 gfloat max);
+gfloat                  pn_float_option_get_max                 (PnFloatOption *float_option);
+
+
+
+
+
+
+#endif /* __PN_FLOAT_OPTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pngtk.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,29 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_GTK_H__
+#define __PN_GTK_H__
+
+/* FIXME: Take this out */
+#define PN_NO_GTK
+
+#ifndef PN_NO_GTK
+#include <gtk/gtk.h>
+#endif /* PN_NO_GTK */
+
+#endif /* __PN_GTK_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnimage.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,683 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pnimage.h"
+#include "pnerror.h"
+#include "pncpu.h"
+
+static void         pn_image_class_init       (PnImageClass *class);
+static void         pn_image_init             (PnImage *image,
+					       PnImageClass *class);
+
+/* GObject signals */
+static void         pn_image_finalize         (GObject *gobject);
+
+static PnObjectClass *parent_class = NULL;
+
+const gchar *pn_image_blend_mode_strings[] =
+{
+  "Ignore",
+  "Replace",
+  "50/50"
+};
+const guint pn_image_blend_mode_count = 3;
+
+GType
+pn_image_get_type (void)
+{
+  static GType image_type = 0;
+
+  if (! image_type)
+    {
+      static const GTypeInfo image_info =
+      {
+	sizeof (PnImageClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_image_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnImage),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_image_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      image_type = g_type_register_static (PN_TYPE_OBJECT,
+					 "PnImage",
+					 &image_info,
+					 0);
+    }
+  return image_type;
+}
+
+static void
+pn_image_class_init (PnImageClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+
+  /* GObject signals */
+  gobject_class->finalize = pn_image_finalize;
+}
+
+static void
+pn_image_init (PnImage *image, PnImageClass *class)
+{
+  image->render_mode = PN_BLEND_MODE_REPLACE;
+  image->transform_mode = PN_BLEND_MODE_REPLACE;
+}
+
+static void
+pn_image_finalize (GObject *gobject)
+{
+  PnImage *image;
+
+  image = (PnImage *) gobject;
+
+  if (image->image_buffer)
+    g_free (image->image_buffer);
+
+  if (image->transform_buffer)
+    g_free (image->transform_buffer);
+}
+
+/**
+ * pn_image_new
+ *
+ * Creates a new #PnImage object
+ *
+ * Returns: The new #PnImage object
+ */
+PnImage*
+pn_image_new (void)
+{
+  return (PnImage *) g_object_new (PN_TYPE_IMAGE, NULL);
+}
+
+/**
+ * pn_image_new_width_size
+ * @width: the width of the new image
+ * @height: the hight of the new image
+ *
+ * Creates a new #PnImage object with the given dimensions
+ *
+ * Returns: The new #PnImage object
+ */
+PnImage*
+pn_image_new_with_size (guint width, guint height)
+{
+  PnImage *image;
+
+  image = (PnImage *) g_object_new (PN_TYPE_IMAGE, NULL);
+
+  pn_image_set_size (image, width, height);
+
+  return image;
+}
+
+/**
+ * pn_image_set_size
+ * @image: a #PnImage
+ * @width: the new width of the image
+ * @height: the new height of the image
+ *
+ * Sets the size of the image contained in a #PnImage object
+ */
+void
+pn_image_set_size (PnImage *image, guint width, guint height)
+{
+  guint pitch;
+
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (width > 0 && height > 0);
+
+  pitch = width * sizeof (PnColor);
+
+  /* Align each row to 8 bytes */
+  if (pitch & 0x00000007)
+    pitch = (pitch & 0xfffffff8) + 8;
+
+  if (image->image_buffer)
+    g_free (image->image_buffer);
+
+  if (image->transform_buffer)
+    g_free (image->transform_buffer);
+
+  image->pitch = pitch;
+  image->width = width;
+  image->height = height;
+  image->image_buffer = g_malloc0 (pitch * height);
+  image->transform_buffer = g_malloc0 (pitch * height);
+}
+
+/**
+ * pn_image_get_width
+ * @image: a #PnImage
+ *
+ * Gets the width of a #PnImage
+ *
+ * Returns: The width of the image
+ */
+guint
+pn_image_get_width (PnImage *image)
+{
+  g_return_val_if_fail (image != NULL, 0);
+  g_return_val_if_fail (PN_IS_IMAGE (image), 0);
+
+  return image->width;
+}
+
+/**
+ * pn_image_get_height
+ * @image: a #PnImage
+ *
+ * Gets the height of a #PnImage
+ *
+ * Returns: The height of the image
+ */
+guint
+pn_image_get_height (PnImage *image)
+{
+  g_return_val_if_fail (image != NULL, 0);
+  g_return_val_if_fail (PN_IS_IMAGE (image), 0);
+
+  return image->height;
+}
+
+/**
+ * pn_image_get_pitch
+ * @image: a #PnImage
+ *
+ * Gets the pitch (width in bytes) of a #PnImage
+ *
+ * Returns: The pitch of the image
+ */
+guint
+pn_image_get_pitch (PnImage *image)
+{
+  g_return_val_if_fail (image != NULL, 0);
+  g_return_val_if_fail (PN_IS_IMAGE (image), 0);
+
+  return image->pitch;
+}
+
+/**
+ * pn_image_set_render_mode
+ * @image: a #PnImage
+ * @render_mode: the blend mode to use
+ *
+ * Sets the blend mode to be used by render functions.  The
+ * render functions are pn_image_render_pixel(),
+ * pn_image_render_pixel_by_offset(), and pn_image_render_line().
+ */
+void
+pn_image_set_render_mode (PnImage *image, PnBlendMode render_mode)
+{
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (render_mode < PN_BLEND_MODE_LAST);
+
+  image->render_mode = render_mode;
+}
+
+/**
+ * pn_image_set_transform_mode
+ * @image: a #PnImage
+ * @transform_mode: the blend mode to use
+ *
+ * Sets the blend mode to be used by pn_image_apply_transform().
+ */
+void
+pn_image_set_transform_mode (PnImage *image, PnBlendMode transform_mode)
+{
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (transform_mode < PN_BLEND_MODE_LAST);
+
+  image->transform_mode = transform_mode;
+}
+
+/**
+ * pn_image_get_image_buffer
+ * @image: a #PnImage
+ *
+ * Retrieves the image buffer (the 'front buffer') of a #PnImage.
+ *
+ * Returns: A pointer to the image buffer
+ */
+PnColor*
+pn_image_get_image_buffer (PnImage *image)
+{
+  g_return_val_if_fail (image != NULL, NULL);
+  g_return_val_if_fail (PN_IS_IMAGE (image), NULL);
+
+  return image->image_buffer;
+}
+
+/**
+ * pn_image_get_transform_buffer
+ * @image: a #PnImage
+ *
+ * Retrieves the transform buffer (the 'back buffer') of a #PnImage.
+ * The transform buffer should only be used internally by transform
+ * actuators.  *EVERY* pixel in the transform buffer *MUST* be set.
+ * The transform buffer can be 'copied' to the image buffer using
+ * pn_image_apply_transform().
+ *
+ * Returns: A pointer to the transform buffer
+ */
+PnColor*
+pn_image_get_transform_buffer (PnImage *image)
+{
+  g_return_val_if_fail (image != NULL, NULL);
+  g_return_val_if_fail (PN_IS_IMAGE (image), NULL);
+
+  return image->transform_buffer;
+}
+
+/**
+ * pn_image_render_pixel
+ * @image: a #PnImage
+ * @x: the x coordinate (left being 0)
+ * @y: the y coordinate (top being 0)
+ * @color: the color
+ *
+ * Renders a pixel to the image buffer of a #PnImage.  pn_image_set_render_mode()
+ * can be used to set the blend mode that is used by this function.
+ */
+void
+pn_image_render_pixel (PnImage *image, guint x, guint y, PnColor color)
+{
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (image->image_buffer != NULL);
+
+  if (x > image->width || y > image->height)
+    return;
+
+  switch (image->render_mode)
+    {
+    case PN_BLEND_MODE_LAST: break;
+    case PN_BLEND_MODE_IGNORE:
+      break;
+
+    case PN_BLEND_MODE_REPLACE:
+      image->image_buffer[(y * (image->pitch>>2)) + x] = color;
+      break;
+
+    case PN_BLEND_MODE_5050:
+      image->image_buffer[(y * (image->pitch>>2)) + x].red =
+	(image->image_buffer[(y * (image->pitch>>2)) + x].red + color.red) >> 1;
+      image->image_buffer[(y * (image->pitch>>2)) + x].green =
+	(image->image_buffer[(y * (image->pitch>>2)) + x].green + color.green) >> 1;
+      image->image_buffer[(y * (image->pitch>>2)) + x].blue =
+	(image->image_buffer[(y * (image->pitch>>2)) + x].blue + color.blue) >> 1;
+      break;
+    }
+}
+
+/**
+ * pn_image_render_pixel_by_offset
+ * @image: a #PnImage
+ * @offset: the pixel offset (0 being the top left) NOTE: Use (pitch>>2) rather
+ * than width
+ * @color: the color
+ *
+ * Renders a pixel to the image buffer of a #PnImage based on a pixel offset rather than
+ * rectangular coordinates.  This function should be used if there is a more optimum way
+ * to calculate the offset than multiplying at every pixel.  pn_image_set_render_mode()
+ * can be used to set the blend mode that is used by this function.
+ */
+void
+pn_image_render_pixel_by_offset (PnImage *image, guint offset, PnColor color)
+{
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (image->image_buffer != NULL);
+
+  if (offset > (image->pitch>>2) * image->height)
+    return;
+
+  switch (image->render_mode)
+    {
+    case PN_BLEND_MODE_LAST: break;
+    case PN_BLEND_MODE_IGNORE:
+      break;
+
+    case PN_BLEND_MODE_REPLACE:
+      image->image_buffer[offset] = color;
+      break;
+
+    case PN_BLEND_MODE_5050:
+      image->image_buffer[offset].red =
+	(image->image_buffer[offset].red + color.red) >> 1;
+      image->image_buffer[offset].green =
+	(image->image_buffer[offset].green + color.green) >> 1;
+      image->image_buffer[offset].blue =
+	(image->image_buffer[offset].blue + color.blue) >> 1;
+      break;
+    }
+}
+
+/* FIXME: Add clipping to this */
+/**
+ * pn_image_render_line
+ * @image: a #PnImage
+ * @x0: the x coordinate of the first point
+ * @y0: the y coordinate of the first point
+ * @x1: the x coordinate of the second point
+ * @y1: the y coordinate of the second point
+ * @color: the color
+ *
+ * Renders a line from (x0,y0) to (x1,y1) to the image buffer of a #PnImage.
+ * Currently ***NO CLIPPING IS CURRENTLY DONE!!!***
+ */
+void
+pn_image_render_line (PnImage *image, guint _x0, guint _y0, guint _x1, guint _y1, PnColor color)
+{
+  gint x0 = _x0;
+  gint y0 = _y0;
+  gint x1 = _x1;
+  gint y1 = _y1;
+
+  gint dy = y1 - y0;
+  gint dx = x1 - x0;
+  gint stepx, stepy;
+  gint fraction;
+
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (image->image_buffer != NULL);
+
+  if (dy < 0)
+    {
+      dy = -dy;
+      stepy = -(image->pitch>>2);
+    }
+  else
+    {
+      stepy = image->pitch>>2;
+    }
+  if (dx < 0)
+    {
+      dx = -dx;
+      stepx = -1;
+    }
+  else
+    {
+      stepx = 1;
+    }
+  dy <<= 1;
+  dx <<= 1;
+
+  y0 *= image->pitch>>2;
+  y1 *= image->pitch>>2;
+  pn_image_render_pixel_by_offset(image, x0+y0, color);
+  if (dx > dy)
+    {
+      fraction = dy - (dx >> 1);
+      while (x0 != x1)
+	{
+	  if (fraction >= 0)
+	    {
+	      y0 += stepy;
+	      fraction -= dx;
+	    }
+	  x0 += stepx;
+	  fraction += dy;
+	  pn_image_render_pixel_by_offset (image, x0+y0, color);
+	}
+    }
+  else
+    {
+      fraction = dx - (dy >> 1);
+      while (y0 != y1)
+	{
+	  if (fraction >= 0)
+	    {
+	      x0 += stepx;
+	      fraction -= dy;
+	    }
+	  y0 += stepy;
+	  fraction += dx;
+	  pn_image_render_pixel_by_offset (image, x0+y0, color);
+	}
+    }
+}
+
+static void
+pn_image_bufcopy_5050 (PnColor *dest, PnColor *src, guint bufsize)
+{
+  register guint i;
+  register PnColor *d, *s;
+
+  d = dest;
+  s = src;
+
+  for (i=0; i<bufsize; i++)
+    {
+      d->red = (s->red + d->red) >> 1;
+      d->green = (s->green + d->green) >> 1;
+      d->blue = (s->blue + d->blue) >> 1;
+      d++;
+      s++;
+    }
+}
+
+#ifdef PN_USE_MMX
+static void
+pn_image_bufcopy_5050_mmx (PnColor *dest, PnColor *src, guint bufsize)
+{
+  __asm__ __volatile__ (
+			"pxor %%mm7,%%mm7\n\t"      /* zero mm7 */
+
+			"10:\n\t"                   /* The start of the loop */
+
+			"movq (%0),%%mm0\n\t"       /* Read the pixels */
+			"movq (%1),%%mm2\n\t"
+			"movq %%mm0,%%mm1\n\t"
+			"movq %%mm2,%%mm3\n\t"
+
+			"punpcklbw %%mm7,%%mm0\n\t" /* Unpack the pixels */
+			"punpckhbw %%mm7,%%mm1\n\t"
+			"punpcklbw %%mm7,%%mm2\n\t"
+			"punpckhbw %%mm7,%%mm3\n\t"
+
+			"paddw %%mm2,%%mm0\n\t"     /* Add the pixels */
+			"paddw %%mm3,%%mm1\n\t"
+
+			"psrlw $1,%%mm0\n\t"        /* Divide the pixels by 2 */
+			"psrlw $1,%%mm1\n\t"
+
+			"packuswb %%mm1,%%mm0\n\t"  /* Pack it up & write it */
+			"movq %%mm0,(%0)\n\t"
+
+			"addl $8,%0\n\t"            /* Advance the pointers */
+			"addl $8,%1\n\t"
+
+			"decl %2\n\t"               /* See if we're done */
+			"jnz 10b\n\t"
+
+			"emms"
+			: /* no outputs */
+			: "r" (dest), "r" (src), "r" (bufsize >> 1)
+			);
+}
+
+/* FIXME: Should this be in a separate #define PN_USE_MMXEXT ? */
+static void
+pn_image_bufcopy_5050_mmxext (PnColor *dest, PnColor *src, guint bufsize)
+{
+  
+
+  __asm__ __volatile__ (
+			"10:\n\t"                   /* The non-unrolled loop */
+
+			"decl %2\n\t"               /* See if we're done */
+			"js 20f\n\t"
+
+			"movq (%0),%%mm0\n\t"       /* Read the pixels */
+			"movq (%1),%%mm1\n\t"
+			"pavgb %%mm1,%%mm0\n\t"     /* Average the pixels */
+
+			"movq %%mm0,(%0)\n\t"       /* Write the pixels */
+
+			"addl $8,%0\n\t"            /* Advance the pointers */
+			"addl $8,%1\n\t"
+
+			"20:\n\t"                   /* The unrolled loop */
+
+			"decl %3\n\t"               /* See if we're done */
+			"js 30f\n\t"
+
+			/* First 2 pixels */
+			"movq (%0),%%mm0\n\t"       /* Read the pixels */
+			"movq (%1),%%mm1\n\t"
+			"pavgb %%mm1,%%mm0\n\t"     /* Average the pixels */
+
+			/* Second 2 pixels */
+			"movq 8(%0),%%mm2\n\t"      /* Read the pixels */
+			"movq 8(%1),%%mm3\n\t"
+			"pavgb %%mm3,%%mm2\n\t"     /* Average the pixels */
+
+			/* Third 2 pixels */
+			"movq 16(%0),%%mm4\n\t"     /* Read the pixels */
+			"movq 16(%1),%%mm5\n\t"
+			"pavgb %%mm5,%%mm4\n\t"     /* Average the pixels */
+
+			/* Fourth 2 pixels */
+			"movq 24(%0),%%mm6\n\t"     /* Read the pixels */
+			"movq 24(%1),%%mm7\n\t"
+			"pavgb %%mm7,%%mm6\n\t"     /* Average the pixels */
+
+			/* Write them all */
+			"movq %%mm0,(%0)\n\t"
+			"movq %%mm2,8(%0)\n\t"
+			"movq %%mm4,16(%0)\n\t"
+			"movq %%mm6,24(%0)\n\t"
+
+			"addl $32,%0\n\t"           /* Advance the pointers */
+			"addl $32,%1\n\t"
+
+			"jmp 20b\n\t"               /* And again */
+
+			"30:\n\t"
+
+			"emms"
+			: /* no outputs */
+			: "r" (dest), "r" (src), "r" ((bufsize >> 1) & 0x3), "r" (bufsize >> 3)
+			);
+}
+
+#endif /* PN_USE_MMX */
+
+/**
+ * pn_image_apply_transform
+ * @image: a #PnImage
+ *
+ * Renders the transform buffer onto the image buffer.
+ * pn_image_set_transform_mode() may be used to set the blend mode that is
+ * used by this function.
+ */
+void
+pn_image_apply_transform (PnImage *image)
+{
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  switch (image->transform_mode)
+    {
+    case PN_BLEND_MODE_LAST:
+    case PN_BLEND_MODE_IGNORE:
+      return;
+
+    case PN_BLEND_MODE_REPLACE:
+      {
+	PnColor *tmp = image->image_buffer;
+	image->image_buffer = image->transform_buffer;
+	image->transform_buffer = tmp;
+      }
+      break;
+
+    case PN_BLEND_MODE_5050:
+#ifdef PN_USE_MMX
+      if (pn_cpu_get_caps () & PN_CPU_CAP_MMXEXT)
+	pn_image_bufcopy_5050_mmxext (image->image_buffer, image->transform_buffer,
+				      image->height * (image->pitch >> 2));
+      else if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+	pn_image_bufcopy_5050_mmx (image->image_buffer, image->transform_buffer,
+				   image->height * (image->pitch >> 2));
+      else
+#endif /* PN_USE_MMX */
+	pn_image_bufcopy_5050 (image->image_buffer, image->transform_buffer,
+			       image->height * (image->pitch >> 2));
+      break;
+    }
+}
+
+/**
+ * pn_image_render_image
+ * @image: a #PnImage
+ * @src: the source image
+ * @blend_mode: the blend mode to use
+ *
+ * Renders the image buffer of @src onto the image buffer of an image.
+ */
+void
+pn_image_render_image (PnImage *image, PnImage *src, PnBlendMode blend_mode)
+{
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (src != NULL);
+  g_return_if_fail (PN_IS_IMAGE (src));
+  g_return_if_fail (blend_mode < PN_BLEND_MODE_LAST);
+  g_return_if_fail (image->width == src->width);
+  g_return_if_fail (image->height == src->height);
+
+  switch (blend_mode)
+    {
+    case PN_BLEND_MODE_LAST:
+    case PN_BLEND_MODE_IGNORE:
+      return;
+
+    case PN_BLEND_MODE_REPLACE:
+      memcpy (image->image_buffer, src->image_buffer, image->height * (image->pitch >> 2) * sizeof (PnColor));
+      break;
+
+    case PN_BLEND_MODE_5050:
+#ifdef PN_USE_MMX
+      if (pn_cpu_get_caps () & PN_CPU_CAP_MMXEXT)
+	pn_image_bufcopy_5050_mmxext (image->image_buffer, src->image_buffer,
+				      image->height * (image->pitch >> 2));
+      else if (pn_cpu_get_caps () & PN_CPU_CAP_MMX)
+	pn_image_bufcopy_5050_mmx (image->image_buffer, src->image_buffer, image->height * (image->pitch >> 2));
+      else
+#endif /* PN_USE_MMX */
+	pn_image_bufcopy_5050 (image->image_buffer, src->image_buffer, image->height * (image->pitch >> 2));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnimage.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,136 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_IMAGE_H__
+#define __PN_IMAGE_H__
+
+#include <glib.h>
+#include "pnobject.h"
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  PN_BLEND_MODE_IGNORE, /* Ignore the source image */
+  PN_BLEND_MODE_REPLACE, /* Replace the destination image with the source */
+  PN_BLEND_MODE_5050, /* Use the mean of the source and destination images */
+  PN_BLEND_MODE_LAST /* INVALID */
+} PnBlendMode;
+extern const gchar *pn_image_blend_mode_strings[];
+extern const guint pn_image_blend_mode_count;
+
+#define PN_TYPE_IMAGE              (pn_image_get_type ())
+#define PN_IMAGE(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_IMAGE, PnImage))
+#define PN_IMAGE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_IMAGE, PnImageClass))
+#define PN_IS_IMAGE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_IMAGE))
+#define PN_IS_IMAGE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_IMAGE))
+#define PN_IMAGE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_IMAGE, PnImageClass))
+
+/* Member access macros */
+#define PN_IMAGE_PITCH(obj)        (PN_IMAGE (obj)->pitch)
+#define PN_IMAGE_WIDTH(obj)        (PN_IMAGE (obj)->width)
+#define PN_IMAGE_HEIGHT(obj)       (PN_IMAGE (obj)->height)
+#define PN_IMAGE_IMAGE_BUF(obj)    (PN_IMAGE (obj)->image_buffer)
+#define PN_IMAGE_XFORM_BUF(obj)    (PN_IMAGE (obj)->transform_buffer)
+
+/* This is to help with passing just the PnImage part of a
+ * PnImage (e.g. to assembly code)
+ */
+#define PN_IMAGE_START(obj)        (G_STRUCT_MEMBER_P (obj, G_STRUCT_OFFSET (PnImage, pitch)))
+
+typedef struct _PnColor PnColor;
+
+struct _PnColor
+{
+  guint8 red;
+  guint8 green;
+  guint8 blue;
+  guint8 unused;
+};
+
+typedef struct _PnImage        PnImage;
+typedef struct _PnImageClass   PnImageClass;
+
+struct _PnImage
+{
+  PnObject parent;
+
+  /* The width of the image buffers in bytes */
+  guint pitch;
+
+  /* The dimensions of the valid image area in pixels */
+  guint width;
+  guint height;
+
+  /* The pixel bleding modes to be used when rendering individual
+   * pixels and when applying the transform buffer to the
+   * image buffer
+   */
+  PnBlendMode render_mode;
+  PnBlendMode transform_mode;
+
+  /* The pixel buffers */
+  PnColor *image_buffer;
+  PnColor *transform_buffer;
+};
+
+struct _PnImageClass
+{
+  PnObjectClass parent_class;
+};
+
+/* Creators */
+GType                 pn_image_get_type                (void);
+PnImage              *pn_image_new                     (void);
+PnImage              *pn_image_new_with_size           (guint width,
+							guint height);
+
+/* Accessors */
+void                  pn_image_set_size                (PnImage *image,
+							guint width,
+							guint height);
+guint                 pn_image_get_width               (PnImage *image);
+guint                 pn_image_get_height              (PnImage *image);
+guint                 pn_image_get_pitch               (PnImage *image);
+void                  pn_image_set_render_mode         (PnImage *image,
+							PnBlendMode render_mode);
+void                  pn_image_set_transform_mode      (PnImage *image,
+							PnBlendMode transform_mode);
+PnColor              *pn_image_get_image_buffer        (PnImage *image);
+PnColor              *pn_image_get_transform_buffer    (PnImage *image);
+
+/* Actions */
+void                  pn_image_render_pixel            (PnImage *image,
+							guint x,
+							guint y,
+							PnColor color);
+void                  pn_image_render_pixel_by_offset  (PnImage *image,
+							guint offset,
+							PnColor color);
+void                  pn_image_render_line             (PnImage *image,
+							guint x0,
+							guint y0,
+							guint x1,
+							guint y1,
+							PnColor color);
+void                  pn_image_apply_transform         (PnImage *image);
+void                  pn_image_render_image            (PnImage *image,
+							PnImage *src,
+							PnBlendMode blend_mode);
+
+#endif /* __PN_IMAGE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnimagecontext.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,188 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include "pnimagecontext.h"
+#include "pnlistoption.h"
+
+static void         pn_image_context_class_init       (PnImageContextClass *class);
+static void         pn_image_context_init             (PnImageContext *image_context,
+						       PnImageContextClass *class);
+/* GObject methods */
+static void         pn_image_context_finalize         (GObject *gobject);
+
+/* PnActuator methods */
+static void         pn_image_context_prepare          (PnImageContext *image_context,
+						       PnImage *image);
+static void         pn_image_context_execute          (PnImageContext *image_context,
+						       PnImage *image,
+						       PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_image_context_get_type (void)
+{
+  static GType image_context_type = 0;
+
+  if (! image_context_type)
+    {
+      static const GTypeInfo image_context_info =
+      {
+	sizeof (PnImageContextClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_image_context_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnImageContext),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_image_context_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      image_context_type = g_type_register_static (PN_TYPE_CONTAINER,
+					      "PnImageContext",
+					      &image_context_info,
+					      0);
+    }
+  return image_context_type;
+}
+
+static void
+pn_image_context_class_init (PnImageContextClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* GObject methods */
+  gobject_class->finalize = pn_image_context_finalize;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_image_context_prepare;
+  actuator_class->execute = (PnActuatorExecFunc) pn_image_context_execute;
+}
+
+static void
+pn_image_context_finalize (GObject *gobject)
+{
+  PnImageContext *image_context;
+
+  image_context = (PnImageContext *) gobject;
+
+  if (image_context->image)
+    pn_object_unref (PN_OBJECT (image_context->image));
+}
+
+static void
+pn_image_context_init (PnImageContext *image_context, PnImageContextClass *class)
+{
+  PnListOption *input_mode_opt, *output_mode_opt;
+  guint i;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (image_context), "Container.Image_Context");
+  pn_user_object_set_description (PN_USER_OBJECT (image_context),
+				  "A container that executes all its actuators sequentially");
+
+  /* Set up the options */
+  input_mode_opt = pn_list_option_new ("input_mode", "The blend mode to be used when getting the image "
+				       "from the parent context");
+  output_mode_opt = pn_list_option_new ("output_mode", "The blend mode to be used when writing the image "
+					"to the parent context");
+
+  for (i=0; i<pn_image_blend_mode_count; i++)
+    {
+      pn_list_option_add_item (input_mode_opt, pn_image_blend_mode_strings[i]);
+      pn_list_option_add_item (output_mode_opt, pn_image_blend_mode_strings[i]);
+    }
+
+  pn_list_option_set_index (input_mode_opt, 0); /* default mode: Ignore */
+  pn_list_option_set_index (output_mode_opt, 1); /* default mode: Replace */
+
+  pn_actuator_add_option (PN_ACTUATOR (image_context), PN_OPTION (input_mode_opt));
+  pn_actuator_add_option (PN_ACTUATOR (image_context), PN_OPTION (output_mode_opt));
+
+  /* Create the new image */
+  image_context->image = pn_image_new ();
+  pn_object_ref (PN_OBJECT (image_context->image));
+  pn_object_sink (PN_OBJECT (image_context->image));
+}
+
+static void
+pn_image_context_prepare (PnImageContext *image_context, PnImage *image)
+{
+  g_return_if_fail (image_context != NULL);
+  g_return_if_fail (PN_IS_IMAGE_CONTEXT (image_context));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  pn_image_set_size (image_context->image, pn_image_get_width (image), pn_image_get_height (image));
+
+  if (PN_ACTUATOR_CLASS (parent_class)->prepare)
+    PN_ACTUATOR_CLASS (parent_class)->prepare (PN_ACTUATOR (image_context), image);
+}
+
+static void
+pn_image_context_execute (PnImageContext *image_context, PnImage *image,
+			  PnAudioData *audio_data)
+{
+  guint i;
+  GArray *actuators;
+  PnListOption *input_mode_opt, *output_mode_opt;
+
+  g_return_if_fail (image_context != NULL);
+  g_return_if_fail (PN_IS_IMAGE_CONTEXT (image_context));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+
+  actuators = ((PnContainer *) (image_context))->actuators;;
+
+  input_mode_opt = (PnListOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (image_context),
+								     PN_IMAGE_CONTEXT_OPT_INPUT_MODE);
+  output_mode_opt = (PnListOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (image_context),
+								      PN_IMAGE_CONTEXT_OPT_OUTPUT_MODE);
+
+  /* Get the image from the parent context */
+  pn_image_render_image (image_context->image, image, (PnBlendMode) pn_list_option_get_index (input_mode_opt));
+  
+  for (i=0; i<actuators->len; i++)
+    pn_actuator_execute (g_array_index (actuators, PnActuator *, i), image_context->image, audio_data);
+
+  /* Write the image to the parent context */
+  pn_image_render_image (image, image_context->image, (PnBlendMode) pn_list_option_get_index (output_mode_opt));
+
+  if (PN_ACTUATOR_CLASS (parent_class)->execute)
+    PN_ACTUATOR_CLASS (parent_class)->execute(PN_ACTUATOR (image_context), image, audio_data);
+}
+
+PnImageContext*
+pn_image_context_new (void)
+{
+  return (PnImageContext *) g_object_new (PN_TYPE_IMAGE_CONTEXT, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnimagecontext.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,61 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_IMAGE_CONTEXT_H__
+#define __PN_IMAGE_CONTEXT_H__
+
+#include "pncontainer.h"
+
+G_BEGIN_DECLS
+
+enum
+{
+  PN_IMAGE_CONTEXT_OPT_INPUT_MODE = PN_CONTAINER_OPT_LAST,
+  PN_IMAGE_CONTEXT_OPT_OUTPUT_MODE,
+  PN_IMAGE_CONTEXT_OPT_LAST
+};
+
+#define PN_TYPE_IMAGE_CONTEXT              (pn_image_context_get_type ())
+#define PN_IMAGE_CONTEXT(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_IMAGE_CONTEXT, PnImageContext))
+#define PN_IMAGE_CONTEXT_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_IMAGE_CONTEXT, PnImageContextClass))
+#define PN_IS_IMAGE_CONTEXT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_IMAGE_CONTEXT))
+#define PN_IS_IMAGE_CONTEXT_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_IMAGE_CONTEXT))
+#define PN_IMAGE_CONTEXT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_IMAGE_CONTEXT, PnImageContextClass))
+
+#define PN_IMAGE_CONTEXT_ACTUATORS(obj)    (PN_IMAGE_CONTEXT (obj)->actuators)
+
+typedef struct _PnImageContext        PnImageContext;
+typedef struct _PnImageContextClass   PnImageContextClass;
+
+struct _PnImageContext
+{
+  PnContainer parent;
+
+  PnImage *image;
+};
+
+struct _PnImageContextClass
+{
+  PnContainerClass parent_class;
+};
+
+/* Creators */
+GType                 pn_image_context_get_type                (void);
+PnImageContext       *pn_image_context_new                     (void);
+
+#endif /* __PN_IMAGE_CONTEXT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pninit.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,43 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pninit.h"
+#include "pncpu.h"
+#include "pnactuatorfactory.h"
+#include "pnbuiltins.h"
+
+guint pn_major_version = 1;
+guint pn_minor_version = 2;
+guint pn_micro_version = 0;
+
+static gboolean pn_ready = FALSE;
+
+void
+pn_init (void)
+{
+  if (pn_ready)
+    return;
+
+  g_type_init ();
+  pn_cpu_init ();
+  pn_actuator_factory_init ();
+  pn_builtins_register ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pninit.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,30 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_INIT_H__
+#define __PN_INIT_H__
+
+#include <glib.h>
+
+extern guint pn_major_version;
+extern guint pn_minor_version;
+extern guint pn_micro_version;
+
+void                  pn_init                                     (void);
+
+#endif /* __PN_INIT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnintegeroption.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,243 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <glib.h>
+#include "pnintegeroption.h"
+#include "pnxml.h"
+#include "pnerror.h"
+
+static void         pn_integer_option_class_init       (PnIntegerOptionClass *class);
+static void         pn_integer_option_init             (PnIntegerOption *integer_option,
+							PnIntegerOptionClass *class);
+
+/* PnUserObject methods */
+static void         pn_integer_option_save_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+static void         pn_integer_option_load_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_integer_option_get_type (void)
+{
+  static GType integer_option_type = 0;
+
+  if (! integer_option_type)
+    {
+      static const GTypeInfo integer_option_info =
+      {
+	sizeof (PnIntegerOptionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_integer_option_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnIntegerOption),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_integer_option_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      integer_option_type = g_type_register_static (PN_TYPE_OPTION,
+					      "PnIntegerOption",
+					      &integer_option_info,
+					      0);
+    }
+  return integer_option_type;
+}
+
+static void
+pn_integer_option_class_init (PnIntegerOptionClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnOptionClass *option_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  option_class = (PnOptionClass *) class;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_integer_option_save_thyself;
+  user_object_class->load_thyself = pn_integer_option_load_thyself;
+
+  /* PnOption methods */
+  /* FIXME: this needs to be uncommented when the widget is done */
+/*    option_class->widget_type = PN_TYPE_INTEGER_OPTION_WIDGET; */
+}
+
+static void
+pn_integer_option_init (PnIntegerOption *integer_option,
+			PnIntegerOptionClass *class)
+{
+  integer_option->min = INT_MIN;
+  integer_option->max = INT_MAX;
+}
+
+static void
+pn_integer_option_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnIntegerOption *integer_option;
+  xmlNodePtr value_node;
+  gchar str[16];
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_INTEGER_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  integer_option = (PnIntegerOption *) user_object;
+
+  value_node = xmlNewChild (node, NULL, "Value", NULL);
+  sprintf (str, "%i", integer_option->value);
+  xmlNodeSetContent (value_node, str);
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_integer_option_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnIntegerOption *integer_option;
+  xmlNodePtr integer_option_node;
+  gchar *val_str;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_INTEGER_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  integer_option = (PnIntegerOption *) user_object;
+
+  /* find the node for this class */
+  for (integer_option_node = node->xmlChildrenNode;
+       integer_option_node;
+       integer_option_node = integer_option_node->next)
+    if (g_strcasecmp (integer_option_node->name, "Value") == 0)
+      break;
+  if (! integer_option_node)
+    {
+      pn_error ("unable to load a PnIntegerOption from xml node \"%s\"", node->name);
+      return;
+    }
+
+  val_str = xmlNodeGetContent (integer_option_node);
+
+  if (val_str)
+    pn_integer_option_set_value (integer_option, strtol (val_str, NULL, 0));
+  else
+    {
+      pn_error ("invalid integer option value encountered at xml node \"%s\"", node->name);
+      return;
+    }
+
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+PnIntegerOption*
+pn_integer_option_new (const gchar *name, const gchar *desc)
+{
+  PnIntegerOption *integer_option;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (desc != NULL, NULL);
+
+  integer_option =   (PnIntegerOption *) g_object_new (PN_TYPE_INTEGER_OPTION, NULL);
+
+  pn_user_object_set_name (PN_USER_OBJECT (integer_option), name);
+  pn_user_object_set_description (PN_USER_OBJECT (integer_option), desc);
+
+  return integer_option;
+}
+
+void
+pn_integer_option_set_value (PnIntegerOption *integer_option, gint value)
+{
+  g_return_if_fail (integer_option != NULL);
+  g_return_if_fail (PN_IS_INTEGER_OPTION (integer_option));
+
+  integer_option->value = CLAMP (value, integer_option->min, integer_option->max);
+}
+
+gint
+pn_integer_option_get_value (PnIntegerOption *integer_option)
+{
+  g_return_val_if_fail (integer_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_INTEGER_OPTION (integer_option), FALSE);
+
+  return integer_option->value;
+}
+
+void
+pn_integer_option_set_min (PnIntegerOption *integer_option, gint min)
+{
+  g_return_if_fail (integer_option != NULL);
+  g_return_if_fail (PN_IS_INTEGER_OPTION (integer_option));
+
+  if (min > integer_option->max)
+    {
+      integer_option->min = integer_option->max;
+      integer_option->max = min;
+    }
+  else
+    integer_option->min = min;
+
+  pn_integer_option_set_value (integer_option, integer_option->value);
+}
+
+gint
+pn_integer_option_get_min (PnIntegerOption *integer_option)
+{
+  g_return_val_if_fail (integer_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_INTEGER_OPTION (integer_option), FALSE);
+
+  return integer_option->min;
+}
+
+void
+pn_integer_option_set_max (PnIntegerOption *integer_option, gint max)
+{
+  g_return_if_fail (integer_option != NULL);
+  g_return_if_fail (PN_IS_INTEGER_OPTION (integer_option));
+
+  if (max < integer_option->min)
+    {
+      integer_option->max = integer_option->min;
+      integer_option->min = max;
+    }
+  else
+    integer_option->max = max;
+
+  pn_integer_option_set_value (integer_option, integer_option->value);
+}
+
+gint
+pn_integer_option_get_max (PnIntegerOption *integer_option)
+{
+  g_return_val_if_fail (integer_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_INTEGER_OPTION (integer_option), FALSE);
+
+  return integer_option->max;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnintegeroption.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,73 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_INTEGER_OPTION_H__
+#define __PN_INTEGER_OPTION_H__
+
+#include "pnoption.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_INTEGER_OPTION              (pn_integer_option_get_type ())
+#define PN_INTEGER_OPTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_INTEGER_OPTION, PnIntegerOption))
+#define PN_INTEGER_OPTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_INTEGER_OPTION, PnIntegerOptionClass))
+#define PN_IS_INTEGER_OPTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_INTEGER_OPTION))
+#define PN_IS_INTEGER_OPTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_INTEGER_OPTION))
+#define PN_INTEGER_OPTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_INTEGER_OPTION, PnIntegerOptionClass))
+
+typedef struct _PnIntegerOption        PnIntegerOption;
+typedef struct _PnIntegerOptionClass   PnIntegerOptionClass;
+
+struct _PnIntegerOption
+{
+  PnOption parent;
+
+  gint value;
+  gint min;
+  gint max;
+};
+
+struct _PnIntegerOptionClass
+{
+  PnOptionClass parent_class;
+};
+
+/* Creators */
+GType                 pn_integer_option_get_type                (void);
+PnIntegerOption      *pn_integer_option_new                     (const gchar *name,
+								 const gchar *desc);
+
+/* Accessors */
+void                  pn_integer_option_set_value               (PnIntegerOption *integer_option,
+								 gint value);
+gint                  pn_integer_option_get_value               (PnIntegerOption *integer_option);
+void                  pn_integer_option_set_min                 (PnIntegerOption *integer_option,
+								 gint min);
+gint                  pn_integer_option_get_min                 (PnIntegerOption *integer_option);
+void                  pn_integer_option_set_max                 (PnIntegerOption *integer_option,
+								 gint max);
+gint                  pn_integer_option_get_max                 (PnIntegerOption *integer_option);
+
+
+
+
+
+
+#endif /* __PN_INTEGER_OPTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnlistoption.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,207 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <glib.h>
+#include "pnlistoption.h"
+#include "pnxml.h"
+#include "pnerror.h"
+
+static void         pn_list_option_class_init       (PnListOptionClass *class);
+static void         pn_list_option_init             (PnListOption *list_option,
+						     PnListOptionClass *class);
+
+/* PnUserObject methods */
+static void         pn_list_option_save_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+static void         pn_list_option_load_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_list_option_get_type (void)
+{
+  static GType list_option_type = 0;
+
+  if (! list_option_type)
+    {
+      static const GTypeInfo list_option_info =
+      {
+	sizeof (PnListOptionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_list_option_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnListOption),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_list_option_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      list_option_type = g_type_register_static (PN_TYPE_OPTION,
+					      "PnListOption",
+					      &list_option_info,
+					      0);
+    }
+  return list_option_type;
+}
+
+static void
+pn_list_option_class_init (PnListOptionClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnOptionClass *option_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  option_class = (PnOptionClass *) class;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_list_option_save_thyself;
+  user_object_class->load_thyself = pn_list_option_load_thyself;
+
+  /* PnOption methods */
+  /* FIXME: this needs to be uncommented when the widget is done */
+/*    option_class->widget_type = PN_TYPE_LIST_OPTION_WIDGET; */
+}
+
+static void
+pn_list_option_init (PnListOption *list_option, PnListOptionClass *class)
+{
+  list_option->items = g_array_new (FALSE, FALSE, sizeof (const gchar *));
+  list_option->index = -1;
+}
+
+static void
+pn_list_option_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnListOption *list_option;
+  xmlNodePtr value_node;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_LIST_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  list_option = (PnListOption *) user_object;
+
+  value_node = xmlNewChild (node, NULL, "Value", NULL);
+  xmlNodeSetContent (value_node, g_array_index (list_option->items, const gchar *, list_option->index));
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_list_option_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnListOption *list_option;
+  xmlNodePtr list_option_node;
+  gchar *val_str;
+  guint i;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_LIST_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  list_option = (PnListOption *) user_object;
+
+  /* find the node for this class */
+  for (list_option_node = node->xmlChildrenNode;
+       list_option_node;
+       list_option_node = list_option_node->next)
+    if (g_strcasecmp (list_option_node->name, "Value") == 0)
+      break;
+  if (! list_option_node)
+    {
+      pn_error ("unable to load a PnListOption from xml node \"%s\"", node->name);
+      return;
+    }
+
+  val_str = xmlNodeGetContent (list_option_node);
+  if (! val_str)
+    goto done;
+
+  for (i=0; i < list_option->items->len; i++)
+    if (g_strcasecmp (val_str, g_array_index (list_option->items, const gchar *, i)) == 0)
+      {
+	list_option->index = i;
+	goto done;
+      }
+
+  pn_error ("invalid list option value encountered at xml node \"%s\"", node->name);
+  return;
+
+ done:
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+PnListOption*
+pn_list_option_new (const gchar *name, const gchar *desc)
+{
+  PnListOption *list_option;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (desc != NULL, NULL);
+
+  list_option = (PnListOption *) g_object_new (PN_TYPE_LIST_OPTION, NULL);
+
+  pn_user_object_set_name (PN_USER_OBJECT (list_option), name);
+  pn_user_object_set_description (PN_USER_OBJECT (list_option), desc);
+
+  return list_option;
+}
+
+void
+pn_list_option_add_item (PnListOption *list_option, const gchar *item)
+{
+  g_return_if_fail (list_option != NULL);
+  g_return_if_fail (PN_IS_LIST_OPTION (list_option));
+  g_return_if_fail (item != NULL);
+
+  g_array_append_val (list_option->items, item);
+
+  if (list_option->index < 0)
+    list_option->index = 0;
+}
+
+void
+pn_list_option_set_index (PnListOption *list_option, guint index)
+{
+  g_return_if_fail (list_option != NULL);
+  g_return_if_fail (PN_IS_LIST_OPTION (list_option));
+  g_return_if_fail (index < list_option->items->len);
+
+  list_option->index = index;
+}
+
+gint
+pn_list_option_get_index (PnListOption *list_option)
+{
+  g_return_val_if_fail (list_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_LIST_OPTION (list_option), FALSE);
+
+  return list_option->index;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnlistoption.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,61 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_LIST_OPTION_H__
+#define __PN_LIST_OPTION_H__
+
+#include "pnoption.h"
+
+G_BEGIN_DECLS
+
+#define PN_TYPE_LIST_OPTION              (pn_list_option_get_type ())
+#define PN_LIST_OPTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_LIST_OPTION, PnListOption))
+#define PN_LIST_OPTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_LIST_OPTION, PnListOptionClass))
+#define PN_IS_LIST_OPTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_LIST_OPTION))
+#define PN_IS_LIST_OPTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_LIST_OPTION))
+#define PN_LIST_OPTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_LIST_OPTION, PnListOptionClass))
+
+typedef struct _PnListOption        PnListOption;
+typedef struct _PnListOptionClass   PnListOptionClass;
+
+struct _PnListOption
+{
+  PnOption parent;
+
+  GArray *items;
+  gint index;
+};
+
+struct _PnListOptionClass
+{
+  PnOptionClass parent_class;
+};
+
+/* Creators */
+GType                 pn_list_option_get_type                (void);
+PnListOption         *pn_list_option_new                     (const gchar *name,
+							      const gchar *desc);
+
+/* Accessors */
+void                  pn_list_option_add_item                (PnListOption *list_option,
+							      const gchar *item);
+void                  pn_list_option_set_index               (PnListOption *list_option,
+							      guint index);
+gint                  pn_list_option_get_index               (PnListOption *list_option);
+
+#endif /* __PN_LIST_OPTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnobject.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,210 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include "pnobject.h"
+
+enum
+{
+  DESTROY,
+  LAST_SIGNAL
+};
+
+/* Initialization */
+static void         pn_object_class_init       (PnObjectClass *class);
+static void         pn_object_init             (PnObject *object,
+						PnObjectClass *class);
+
+/* GObject signals */
+static void         pn_object_finalize         (GObject *gobject);
+static void         pn_object_dispose         (GObject *gobject);
+
+/* PnObject signals */
+static void         pn_object_real_destroy     (PnObject *object);
+
+static GObjectClass *parent_class = NULL;
+static guint         object_signals[LAST_SIGNAL] = { 0 };
+
+GType
+pn_object_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (! object_type)
+    {
+      static const GTypeInfo object_info =
+      {
+	sizeof (PnObjectClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_object_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnObject),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_object_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      object_type = g_type_register_static (G_TYPE_OBJECT,
+					    "PnObject",
+					    &object_info,
+					    G_TYPE_FLAG_ABSTRACT);
+    }
+  return object_type;
+}
+
+static void
+pn_object_class_init (PnObjectClass *class)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class->dispose = pn_object_dispose;
+  gobject_class->finalize = pn_object_finalize;
+
+  class->destroy = pn_object_real_destroy;
+
+  object_signals[DESTROY] =
+    g_signal_new ("destroy",
+		  G_TYPE_FROM_CLASS (class),
+		  G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+		  G_STRUCT_OFFSET (PnObjectClass, destroy),
+		  NULL,
+		  NULL,
+		  g_cclosure_marshal_VOID__VOID,
+		  G_TYPE_NONE,
+		  0);
+}
+
+static void
+pn_object_init (PnObject *object, PnObjectClass *class)
+{
+  object->flags = PN_FLOATING;
+}
+
+void
+pn_object_destroy (PnObject *object)
+{
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (PN_IS_OBJECT (object));
+  
+  if (!PN_OBJECT_DESTROYED (object))
+    {
+      /* need to hold a reference count around all class method
+       * invocations.
+       */
+      g_object_run_dispose (G_OBJECT (object));
+    }
+}
+
+static void
+pn_object_dispose (GObject *gobject)
+{
+  PnObject *object = PN_OBJECT (gobject);
+
+  /* guard against reinvocations during
+   * destruction with the PN_DESTROYED flag.
+   */
+  if (!PN_OBJECT_DESTROYED (object))
+    {
+      PN_OBJECT_SET_FLAGS (object, PN_DESTROYED);
+      
+      g_signal_emit (object, object_signals[DESTROY], 0);
+      
+      PN_OBJECT_UNSET_FLAGS (object, PN_DESTROYED);
+    }
+
+  G_OBJECT_CLASS (parent_class)->dispose (gobject);
+}
+
+static void
+pn_object_real_destroy (PnObject *object)
+{
+  g_signal_handlers_destroy (G_OBJECT (object));
+}
+
+static void
+pn_object_finalize (GObject *gobject)
+{
+  PnObject *object;
+
+  object = PN_OBJECT (gobject);
+
+  G_OBJECT_CLASS (parent_class)->finalize (gobject);
+}
+
+/**
+ * pn_object_sink
+ * @object: a #PnObject
+ *
+ * Removes floating reference on an object.  Any newly created object has
+ * a refcount of 1 and is FLOATING.  This function should be used when
+ * creating a new object to symbolically 'take ownership of' the object.
+ */
+void
+pn_object_sink (PnObject *object)
+{
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (PN_IS_OBJECT (object));
+
+  if (PN_OBJECT_FLOATING (object))
+    {
+      PN_OBJECT_UNSET_FLAGS (object, PN_FLOATING);
+      pn_object_unref (object);
+    }
+}
+
+/**
+ * pn_object_ref
+ * @object: a #PnObject
+ *
+ * Increments the reference count on an object
+ *
+ * Returns: A pointer to the object
+ */
+PnObject*
+pn_object_ref (PnObject *object)
+{
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (PN_IS_OBJECT (object), NULL);
+
+  g_object_ref ((GObject*) object);
+  
+  return object;
+}
+
+/**
+ * pn_object_unref
+ * @object: a #PnObject
+ *
+ * Decrements the reference count on an object.  If the object's reference
+ * count becomes 0, the object is freed from memory.
+ */
+void
+pn_object_unref (PnObject *object)
+{
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (PN_IS_OBJECT (object));
+
+  g_object_unref ((GObject*) object);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnobject.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,91 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_OBJECT_H__
+#define __PN_OBJECT_H__
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PN_TYPE_OBJECT              (pn_object_get_type ())
+#define PN_OBJECT(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_OBJECT, PnObject))
+#define PN_OBJECT_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_OBJECT, PnObjectClass))
+#define PN_IS_OBJECT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_OBJECT))
+#define PN_IS_OBJECT_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_OBJECT))
+#define PN_OBJECT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_OBJECT, PnObjectClass))
+#define PN_OBJECT_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define PN_OBJECT_CLASS_NAME(class) (g_type_name (PN_OBJECT_CLASS_TYPE (class)))
+
+#define PN_OBJECT_TYPE(obj)         (G_TYPE_FROM_INSTANCE (obj))
+#define PN_OBJECT_TYPE_NAME(obj)    (g_type_name (PN_OBJECT_TYPE (obj)))
+
+typedef enum
+{
+  PN_DESTROYED		= 1 << 0,
+  PN_FLOATING		= 1 << 1,
+  PN_RESERVED_1		= 1 << 2,
+  PN_RESERVED_2		= 1 << 3
+} PnObjectFlags;
+
+#define PN_OBJECT_FLAGS(obj)             (PN_OBJECT (obj)->flags)
+#define PN_OBJECT_DESTROYED(obj)         ((PN_OBJECT_FLAGS (obj) & PN_DESTROYED) != 0)
+#define PN_OBJECT_FLOATING(obj)	         ((PN_OBJECT_FLAGS (obj) & PN_FLOATING) != 0)
+#define PN_OBJECT_CONNECTED(obj)         ((PN_OBJECT_FLAGS (obj) & PN_CONNECTED) != 0)
+
+#define PN_OBJECT_SET_FLAGS(obj,flag)	 G_STMT_START{ (PN_OBJECT_FLAGS (obj) |= (flag)); }G_STMT_END
+#define PN_OBJECT_UNSET_FLAGS(obj,flag)  G_STMT_START{ (PN_OBJECT_FLAGS (obj) &= ~(flag)); }G_STMT_END
+
+typedef struct _PnObject        PnObject;
+typedef struct _PnObjectClass   PnObjectClass;
+
+struct _PnObject
+{
+  GObject parent;
+
+  /* Only the first four bits are used, so derived classes can use this
+   * for their own flags
+   */
+  guint32 flags;
+};
+
+struct _PnObjectClass
+{
+  GObjectClass parent_class;
+
+  /* if a class overrides this then it MUST call its superclass'
+   * implimentation
+   */
+  void (*destroy) (PnObject *object);
+};
+
+/* Creators */
+GType             pn_object_get_type                 (void);
+
+/* Referencing */
+PnObject*         pn_object_ref                      (PnObject *object);
+void              pn_object_unref                    (PnObject *object);
+void              pn_object_sink                     (PnObject *object);
+
+/* Destruction */
+void              pn_object_destroy                  (PnObject *object);
+
+#endif /* __PN_OBJECT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnoption.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,112 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pnoption.h"
+
+static void         pn_option_class_init       (PnOptionClass *class);
+static void         pn_option_init             (PnOption *option,
+						PnOptionClass *class);
+
+/* GObject signals */
+static void         pn_option_finalize         (GObject *gobject);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_option_get_type (void)
+{
+  static GType option_type = 0;
+
+  if (! option_type)
+    {
+      static const GTypeInfo option_info =
+      {
+	sizeof (PnOptionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_option_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnOption),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_option_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      option_type = g_type_register_static (PN_TYPE_USER_OBJECT,
+					      "PnOption",
+					      &option_info,
+					      G_TYPE_FLAG_ABSTRACT);
+    }
+  return option_type;
+}
+
+static void
+pn_option_class_init (PnOptionClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+
+  /* GObject signals */
+  gobject_class->finalize = pn_option_finalize;
+}
+
+static void
+pn_option_init (PnOption *option, PnOptionClass *class)
+{
+}
+
+static void
+pn_option_finalize (GObject *gobject)
+{
+  PnOption *option;
+
+  option = (PnOption *) gobject;
+
+  if (G_OBJECT_CLASS (parent_class)->finalize)
+    (* G_OBJECT_CLASS (parent_class)->finalize) (gobject);
+}
+
+PnOptionWidget*
+pn_option_new_widget (PnOption *option)
+{
+  PnOptionClass *class;
+
+  g_return_val_if_fail (option != NULL, NULL);
+  g_return_val_if_fail (PN_IS_OPTION (option), NULL);
+
+  class = PN_OPTION_GET_CLASS (option);
+
+#ifndef PN_NO_GTK
+  if (class->widget_type)
+    return PN_OPTION_WIDGET (g_object_new (class->widget_type, NULL));
+#endif /* PN_NO_GTK */
+
+  return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnoption.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,59 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_OPTION_H__
+#define __PN_OPTION_H__
+
+#include "pnuserobject.h"
+#include "pnoptionwidget.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_OPTION              (pn_option_get_type ())
+#define PN_OPTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_OPTION, PnOption))
+#define PN_OPTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_OPTION, PnOptionClass))
+#define PN_IS_OPTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_OPTION))
+#define PN_IS_OPTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_OPTION))
+#define PN_OPTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_OPTION, PnOptionClass))
+
+typedef struct _PnOption        PnOption;
+typedef struct _PnOptionClass   PnOptionClass;
+
+struct _PnOption
+{
+  PnUserObject parent;
+};
+
+struct _PnOptionClass
+{
+  PnUserObjectClass parent_class;
+
+  GType widget_type;
+};
+
+/* Creators */
+GType                 pn_option_get_type                (void);
+PnOptionWidget       *pn_option_new_widget              (PnOption *option);
+
+
+
+
+
+#endif /* __PN_OPTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnoptionwidget.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,26 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_OPTION_WIDGET_H__
+#define __PN_OPTION_WIDGET_H__
+
+#include "pngtk.h"
+
+#define PnOptionWidget gpointer
+
+#endif /* __PN_OPTION_WIDGET_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnrotozoom.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,339 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include <glib.h>
+#include "pnrotozoom.h"
+#include "pnstringoption.h"
+#include "pnscript.h"
+#include "pnsymboltable.h"
+#include "pncpu.h"
+
+static void         pn_roto_zoom_class_init       (PnRotoZoomClass *class);
+static void         pn_roto_zoom_init             (PnRotoZoom *roto_zoom,
+						   PnRotoZoomClass *class);
+
+/* PnObject signals */
+static void         pn_roto_zoom_destroy          (PnObject *object);
+
+/* PnActuator methods */
+static void         pn_roto_zoom_prepare          (PnRotoZoom *roto_zoom,
+						   PnImage *image);
+static void         pn_roto_zoom_execute          (PnRotoZoom *roto_zoom,
+						   PnImage *image,
+						   PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_roto_zoom_get_type (void)
+{
+  static GType roto_zoom_type = 0;
+
+  if (! roto_zoom_type)
+    {
+      static const GTypeInfo roto_zoom_info =
+      {
+	sizeof (PnRotoZoomClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_roto_zoom_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnRotoZoom),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_roto_zoom_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      roto_zoom_type = g_type_register_static (PN_TYPE_ACTUATOR,
+					       "PnRotoZoom",
+					       &roto_zoom_info,
+					       0);
+    }
+  return roto_zoom_type;
+}
+
+static void
+pn_roto_zoom_class_init (PnRotoZoomClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnObject signals */
+  object_class->destroy = pn_roto_zoom_destroy;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_roto_zoom_prepare;
+  actuator_class->execute = (PnActuatorExecFunc) pn_roto_zoom_execute;
+}
+
+static void
+pn_roto_zoom_init (PnRotoZoom *roto_zoom, PnRotoZoomClass *class)
+{
+  PnStringOption *init_script_opt, *frame_script_opt;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (roto_zoom), "Transform.Roto_Zoom");
+  pn_user_object_set_description (PN_USER_OBJECT (roto_zoom),
+				  "Rotate and zoom the image");
+
+  /* Set up the options */
+  init_script_opt = pn_string_option_new ("init_script", "The initialization script");
+  frame_script_opt = pn_string_option_new ("frame_script", "The per-frame script");
+
+  pn_actuator_add_option (PN_ACTUATOR (roto_zoom), PN_OPTION (init_script_opt));
+  pn_actuator_add_option (PN_ACTUATOR (roto_zoom), PN_OPTION (frame_script_opt));
+
+  /* Create the script objects and symbol table */
+  roto_zoom->init_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (roto_zoom->init_script));
+  pn_object_sink (PN_OBJECT (roto_zoom->init_script));
+  roto_zoom->frame_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (roto_zoom->frame_script));
+  pn_object_sink (PN_OBJECT (roto_zoom->frame_script));
+  roto_zoom->symbol_table = pn_symbol_table_new ();
+  pn_object_ref (PN_OBJECT (roto_zoom->symbol_table));
+  pn_object_sink (PN_OBJECT (roto_zoom->symbol_table));
+
+  /* Get the variables from the symbol table */
+  roto_zoom->zoom_var = pn_symbol_table_ref_variable_by_name (roto_zoom->symbol_table, "zoom");
+  roto_zoom->theta_var = pn_symbol_table_ref_variable_by_name (roto_zoom->symbol_table, "theta");
+  roto_zoom->volume_var = pn_symbol_table_ref_variable_by_name (roto_zoom->symbol_table, "volume");
+}
+
+static void
+pn_roto_zoom_destroy (PnObject *object)
+{
+  PnRotoZoom *roto_zoom;
+
+  roto_zoom = (PnRotoZoom *) object;
+
+  pn_object_unref (PN_OBJECT (roto_zoom->init_script));
+  pn_object_unref (PN_OBJECT (roto_zoom->frame_script));
+  pn_object_unref (PN_OBJECT (roto_zoom->symbol_table));
+}  
+
+static void
+pn_roto_zoom_prepare (PnRotoZoom *roto_zoom, PnImage *image)
+{
+  PnStringOption *init_script_opt, *frame_script_opt;
+
+  g_return_if_fail (roto_zoom != NULL);
+  g_return_if_fail (PN_IS_ROTO_ZOOM (roto_zoom));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  /* Parse the script strings */
+  init_script_opt =
+    (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (roto_zoom),
+							PN_ROTO_ZOOM_OPT_INIT_SCRIPT);
+  frame_script_opt =
+    (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (roto_zoom),
+							PN_ROTO_ZOOM_OPT_FRAME_SCRIPT);
+
+  pn_script_parse_string (roto_zoom->init_script, roto_zoom->symbol_table,
+			  pn_string_option_get_value (init_script_opt));
+  pn_script_parse_string (roto_zoom->frame_script, roto_zoom->symbol_table,
+			  pn_string_option_get_value (frame_script_opt));
+
+  /* Set up in-script vars for no rotozooming */
+  PN_VARIABLE_VALUE (roto_zoom->zoom_var) = 1.0;
+  PN_VARIABLE_VALUE (roto_zoom->theta_var) = 0.0;
+
+  /* Run the init script */
+  pn_script_execute (roto_zoom->init_script);
+
+  if (PN_ACTUATOR_CLASS (parent_class)->prepare)
+    PN_ACTUATOR_CLASS (parent_class)->prepare (PN_ACTUATOR (roto_zoom), image);
+}
+
+static void
+pn_roto_zoom_execute (PnRotoZoom *roto_zoom, PnImage *image, PnAudioData *audio_data)
+{
+  gint width, height, stride;
+  gdouble ax, ay, bx, by, cx, cy;
+  gint xdx, xdy, ydx, ydy;
+  gint xx, xy, yx, yy;
+  gint i, j;
+  gdouble zoom, theta, r;
+
+  PnColor *src, *dest;
+
+  g_return_if_fail (roto_zoom != NULL);
+  g_return_if_fail (PN_IS_ROTO_ZOOM (roto_zoom));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+  width = pn_image_get_width (image);
+  height = pn_image_get_height (image);
+  stride = pn_image_get_pitch (image) >> 2;
+  src = pn_image_get_image_buffer (image);
+  dest = pn_image_get_transform_buffer (image);
+
+  /* set up the volume in-script variable */
+  PN_VARIABLE_VALUE (roto_zoom->volume_var) = pn_audio_data_get_volume (audio_data);
+
+  /* run the frame scipt */
+  pn_script_execute (roto_zoom->frame_script);
+
+  /* get the in-script variable values */
+  zoom = PN_VARIABLE_VALUE (roto_zoom->zoom_var);
+  theta = PN_VARIABLE_VALUE (roto_zoom->theta_var);
+
+  if (zoom == 0.0)
+    return;
+
+  r = G_SQRT2 / zoom;
+
+  ax = r * cos ((G_PI *  .75) + theta);
+  ay = r * sin ((G_PI *  .75) + theta);
+  bx = r * cos ((G_PI *  .25) + theta);
+  by = r * sin ((G_PI *  .25) + theta);
+  cx = r * cos ((G_PI * 1.25) + theta);
+  cy = r * sin ((G_PI * 1.25) + theta);
+
+/*    fprintf (stderr, "ax: %f, ay: %f\n", ax, ay); */
+/*    fprintf (stderr, "bx: %f, by: %f\n", bx, by); */
+/*    fprintf (stderr, "cx: %f, cy: %f\n", cx, cy); */
+
+  ax = ((width-1)<<8) * ((ax + 1) * .5);
+  ay = ((height-1)<<8) * ((-ay + 1) * .5);
+  bx = ((width-1)<<8) * ((bx + 1) * .5);
+  by = ((height-1)<<8) * ((-by + 1) * .5);
+  cx = ((width-1)<<8) * ((cx + 1) * .5);
+  cy = ((height-1)<<8) * ((-cy + 1) * .5);
+
+/*    fprintf (stderr, "ax': %f, ay': %f\n", ax, ay); */
+/*    fprintf (stderr, "bx': %f, by': %f\n", bx, by); */
+/*    fprintf (stderr, "cx': %f, cy': %f\n", cx, cy); */
+
+  xdx = (bx - ax) / (width-1);
+  xdy = (by - ay) / (width-1);
+  ydx = (cx - ax) / (height-1);
+  ydy = (cy - ay) / (height-1);
+
+/*    fprintf (stderr, "xdx: %i, xdy: %i\n", xdx, xdy); */
+/*    fprintf (stderr, "ydx: %i, ydy: %i\n", ydx, ydy); */
+
+  yx = ax;
+  yy = ay;
+
+  for (j=0; j<height; j++)
+    {
+      while (yx < 0) yx += width<<8;
+      while (yy < 0) yy += height<<8;
+      while (yx >= width<<8) yx -= width<<8;
+      while (yy >= height<<8) yy -= height<<8;
+
+      xx = yx;
+      xy = yy;
+
+      for (i=0; i<width; i++)
+	{
+	  guint r, g, b, offset;
+	  guint xfrac, yfrac;
+
+	  while (xx < 0) xx += width<<8;
+	  while (xy < 0) xy += height<<8;
+	  while (xx >= width<<8) xx -= width<<8;
+	  while (xy >= height<<8) xy -= height<<8;
+
+	  offset = (xy >> 8) * stride + (xx >> 8);
+	  xfrac = xx & 0xff;
+	  yfrac = xy & 0xff;
+
+	  r = src[offset].red * (256 - xfrac) * (256 - yfrac);
+	  g = src[offset].green * (256 - xfrac) * (256 - yfrac);
+	  b = src[offset].blue * (256 - xfrac) * (256 - yfrac);
+
+	  if (xx >> 8 < width-1)
+	    {
+	      r += src[offset+1].red * xfrac * (256 - yfrac);
+	      g += src[offset+1].green * xfrac * (256 - yfrac);
+	      b += src[offset+1].blue * xfrac * (256 - yfrac);
+	    }
+	  else
+	    {
+	      r += src[(xy>>8) * stride].red * xfrac * (256 - yfrac);
+	      g += src[(xy>>8) * stride].green * xfrac * (256 - yfrac);
+	      b += src[(xy>>8) * stride].blue * xfrac * (256 - yfrac);
+	    }
+
+	  if (xy >> 8 < height-1)
+	    {
+	      r += src[offset+stride].red * (256 - xfrac) * yfrac;
+	      g += src[offset+stride].green * (256 - xfrac) * yfrac;
+	      b += src[offset+stride].blue * (256 - xfrac) * yfrac;
+	    }
+	  else
+	    {
+	      r += src[xx>>8].red * (256 - xfrac) * yfrac;
+	      g += src[xx>>8].green * (256 - xfrac) * yfrac;
+	      b += src[xx>>8].blue * (256 - xfrac) * yfrac;
+	    }
+
+	  if (xx >> 8 < width-1 && xy >> 8 < height-1)
+	    {
+	      r += src[offset+stride+1].red * xfrac * yfrac;
+	      g += src[offset+stride+1].green * xfrac * yfrac;
+	      b += src[offset+stride+1].blue * xfrac * yfrac;
+	    }
+	  else
+	    {
+	      r += src[0].red * xfrac * yfrac;
+	      g += src[0].green * xfrac * yfrac;
+	      b += src[0].blue * xfrac * yfrac;
+	    }
+
+	  dest[j * stride + i].red = r >> 16;
+	  dest[j * stride + i].green = g >> 16;
+	  dest[j * stride + i].blue = b >> 16;
+
+	  xx += xdx;
+	  xy += xdy;
+	}
+
+      yx += ydx;
+      yy += ydy;
+    }
+  
+/*    fprintf (stderr, "xx: %i, xy: %i\n", xx, xy); */
+
+  pn_image_apply_transform (image);
+
+  if (PN_ACTUATOR_CLASS (parent_class)->execute != NULL)
+    PN_ACTUATOR_CLASS (parent_class)->execute (PN_ACTUATOR (roto_zoom), image, audio_data);
+}
+
+PnRotoZoom*
+pn_roto_zoom_new (void)
+{
+  return (PnRotoZoom *) g_object_new (PN_TYPE_ROTO_ZOOM, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnrotozoom.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,70 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_ROTO_ZOOM_H__
+#define __PN_ROTO_ZOOM_H__
+
+#include "pnactuator.h"
+#include "pnscript.h"
+#include "pnsymboltable.h"
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_ROTO_ZOOM_OPT_INIT_SCRIPT = PN_ACTUATOR_OPT_LAST,
+  PN_ROTO_ZOOM_OPT_FRAME_SCRIPT,
+  PN_ROTO_ZOOM_OPT_LAST
+};
+
+#define PN_TYPE_ROTO_ZOOM              (pn_roto_zoom_get_type ())
+#define PN_ROTO_ZOOM(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_ROTO_ZOOM, PnRotoZoom))
+#define PN_ROTO_ZOOM_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_ROTO_ZOOM, PnRotoZoomClass))
+#define PN_IS_ROTO_ZOOM(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_ROTO_ZOOM))
+#define PN_IS_ROTO_ZOOM_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_ROTO_ZOOM))
+#define PN_ROTO_ZOOM_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_ROTO_ZOOM, PnRotoZoomClass))
+
+typedef struct _PnRotoZoom        PnRotoZoom;
+typedef struct _PnRotoZoomClass   PnRotoZoomClass;
+
+struct _PnRotoZoom
+{
+  PnActuator parent;
+
+  /* The script objects */
+  PnScript *init_script;
+  PnScript *frame_script;
+  PnSymbolTable *symbol_table;
+
+  /* The in-script variables */
+  PnVariable *zoom_var;
+  PnVariable *theta_var;
+  PnVariable *volume_var;
+};
+
+struct _PnRotoZoomClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                     pn_roto_zoom_get_type                (void);
+PnRotoZoom               *pn_roto_zoom_new                     (void);
+
+#endif /* __PN_ROTO_ZOOM_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnscope.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,316 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <math.h>
+#include <glib.h>
+#include "pnscope.h"
+#include "pnlistoption.h"
+#include "pnstringoption.h"
+
+enum
+{
+  PN_SCOPE_DRAW_METHOD_DOTS = 0,
+  PN_SCOPE_DRAW_METHOD_LINES
+};
+
+static void         pn_scope_class_init       (PnScopeClass *class);
+static void         pn_scope_init             (PnScope *scope,
+					       PnScopeClass *class);
+/* PnObject signals */
+static void         pn_scope_destroy          (PnObject *object);
+
+/* PnActuator methods */
+static void         pn_scope_prepare          (PnScope *scope,
+					       PnImage *image);
+static void         pn_scope_execute          (PnScope *scope,
+					       PnImage *image,
+					       PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_scope_get_type (void)
+{
+  static GType scope_type = 0;
+
+  if (! scope_type)
+    {
+      static const GTypeInfo scope_info =
+      {
+	sizeof (PnScopeClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_scope_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnScope),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_scope_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      scope_type = g_type_register_static (PN_TYPE_ACTUATOR,
+					      "PnScope",
+					      &scope_info,
+					      0);
+    }
+  return scope_type;
+}
+
+static void
+pn_scope_class_init (PnScopeClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnObject signals */
+  object_class->destroy = pn_scope_destroy;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_scope_prepare;
+  actuator_class->execute = (PnActuatorExecFunc) pn_scope_execute;
+}
+
+static void
+pn_scope_init (PnScope *scope, PnScopeClass *class)
+{
+  PnListOption *draw_method_opt;
+  PnStringOption *init_script_opt;
+  PnStringOption *frame_script_opt;
+  PnStringOption *sample_script_opt;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (scope), "Render.Scope");
+  pn_user_object_set_description (PN_USER_OBJECT (scope),
+				  "A test scope actuator");
+
+  /* Set up the options */
+  draw_method_opt = pn_list_option_new ("draw_method", "The way the points will be drawn");
+  init_script_opt = pn_string_option_new ("init_script", "The initialization script");
+  frame_script_opt = pn_string_option_new ("frame_script", "The per-frame script");
+  sample_script_opt = pn_string_option_new ("sample_script", "The per-sample script");
+
+  pn_list_option_add_item (draw_method_opt, "Dots");
+  pn_list_option_add_item (draw_method_opt, "Lines");
+
+  pn_actuator_add_option (PN_ACTUATOR (scope), PN_OPTION (draw_method_opt));
+  pn_actuator_add_option (PN_ACTUATOR (scope), PN_OPTION (init_script_opt));
+  pn_actuator_add_option (PN_ACTUATOR (scope), PN_OPTION (frame_script_opt));
+  pn_actuator_add_option (PN_ACTUATOR (scope), PN_OPTION (sample_script_opt));
+
+  /* Create the script objects and symbol table */
+  scope->init_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (scope->init_script));
+  pn_object_sink (PN_OBJECT (scope->init_script));
+  scope->frame_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (scope->frame_script));
+  pn_object_sink (PN_OBJECT (scope->frame_script));
+  scope->sample_script = pn_script_new ();
+  pn_object_ref (PN_OBJECT (scope->sample_script));
+  pn_object_sink (PN_OBJECT (scope->sample_script));
+  scope->symbol_table = pn_symbol_table_new ();
+  pn_object_ref (PN_OBJECT (scope->symbol_table));
+  pn_object_sink (PN_OBJECT (scope->symbol_table));
+
+  /* Get the variables from the symbol table */
+  scope->samples_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "samples");
+  scope->width_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "width");
+  scope->height_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "height");
+  scope->x_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "x");
+  scope->y_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "y");
+  scope->iteration_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "iteration");
+  scope->value_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "value");
+  scope->red_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "red");
+  scope->green_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "green");
+  scope->blue_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "blue");
+  scope->volume_var = pn_symbol_table_ref_variable_by_name (scope->symbol_table, "volume");
+
+  PN_VARIABLE_VALUE (scope->samples_var) = 0.0;
+  PN_VARIABLE_VALUE (scope->red_var) = 1.0;
+  PN_VARIABLE_VALUE (scope->green_var) = 1.0;
+  PN_VARIABLE_VALUE (scope->blue_var) = 1.0;
+}
+
+static void
+pn_scope_destroy (PnObject *object)
+{
+  PnScope *scope;
+
+  scope = (PnScope *) object;
+
+  pn_object_unref (PN_OBJECT (scope->init_script));
+  pn_object_unref (PN_OBJECT (scope->frame_script));
+  pn_object_unref (PN_OBJECT (scope->sample_script));
+  pn_object_unref (PN_OBJECT (scope->symbol_table));
+}
+
+static void
+pn_scope_prepare (PnScope *scope, PnImage *image)
+{
+  PnStringOption *init_script_opt;
+  PnStringOption *frame_script_opt;
+  PnStringOption *sample_script_opt;
+
+  g_return_if_fail (scope != NULL);
+  g_return_if_fail (PN_IS_SCOPE (scope));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  /* Parse the script strings */
+  init_script_opt = (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (scope),
+									PN_SCOPE_OPT_INIT_SCRIPT);
+  frame_script_opt = (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (scope),
+									 PN_SCOPE_OPT_FRAME_SCRIPT);
+  sample_script_opt = (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (scope),
+									  PN_SCOPE_OPT_SAMPLE_SCRIPT);
+
+  pn_script_parse_string (scope->init_script,
+			  scope->symbol_table,
+			  pn_string_option_get_value (init_script_opt));
+  pn_script_parse_string (scope->frame_script,
+			  scope->symbol_table,
+			  pn_string_option_get_value (frame_script_opt));
+  pn_script_parse_string (scope->sample_script,
+			  scope->symbol_table,
+			  pn_string_option_get_value (sample_script_opt));
+
+  /* Set up the width and height in-script variables */
+  PN_VARIABLE_VALUE (scope->width_var) = pn_image_get_width (image);
+  PN_VARIABLE_VALUE (scope->height_var) = pn_image_get_height (image);
+
+  /* Run the init script */
+  pn_script_execute (scope->init_script);
+
+  if (parent_class->prepare)
+    parent_class->prepare (PN_ACTUATOR (scope), image);
+}
+
+static void
+pn_scope_execute (PnScope *scope, PnImage *image, PnAudioData *audio_data)
+{
+  gdouble i, samples;
+  gdouble half_width, neg_half_height, increment = 0.0;
+  PnColor color = { 255, 255, 255 };
+  guint last_x = 0, last_y = 0, x, y;
+  PnListOption *draw_method_opt;
+  gboolean use_lines;
+
+  g_return_if_fail (scope != NULL);
+  g_return_if_fail (PN_IS_SCOPE (scope));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+  g_return_if_fail (PN_IS_AUDIO_DATA (audio_data));
+
+  half_width = (((gdouble) pn_image_get_width (image)) - 1.0) * 0.5;
+  neg_half_height = (((gdouble) pn_image_get_height (image)) - 1.0) * -0.5;
+
+  draw_method_opt = (PnListOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (scope),
+								      PN_SCOPE_OPT_DRAW_METHOD);
+  use_lines = pn_list_option_get_index (draw_method_opt) == PN_SCOPE_DRAW_METHOD_LINES;
+
+  /* Set the volume in-script variable */
+  PN_VARIABLE_VALUE (scope->volume_var) = pn_audio_data_get_volume (audio_data);
+
+  /* Run the frame script */
+  pn_script_execute (scope->frame_script);
+
+  /* Go through and draw each sample-point  */
+  samples = PN_VARIABLE_VALUE (scope->samples_var);
+  if (samples > 1)
+    {
+      increment = 1 / (samples - 1);
+      PN_VARIABLE_VALUE (scope->iteration_var) = -increment;
+    }
+  else if (samples > 0)
+    {
+      increment = 0;
+      PN_VARIABLE_VALUE (scope->iteration_var) = 0.0;
+    }
+  for (i=0; i < samples; i++)
+    {
+      /* Set up the in-script variables */
+      PN_VARIABLE_VALUE (scope->x_var) = 2.0;
+      PN_VARIABLE_VALUE (scope->y_var) = 2.0;
+      PN_VARIABLE_VALUE (scope->iteration_var) += increment;
+
+      /* FIXME: This should be done in PnAudioData */
+      /* Interpolate the sample value */
+      {
+	gdouble sample, bias;
+	guint lsamp, usamp;
+
+	sample = (gdouble)PN_AUDIO_DATA_PCM_SAMPLES(audio_data)
+	  * (gdouble)PN_VARIABLE_VALUE (scope->iteration_var);
+
+	lsamp = (guint) sample;
+	if (lsamp != sample)
+	  {
+	    usamp = lsamp + 1;
+
+	    bias = sample - (gdouble) lsamp;
+
+	    PN_VARIABLE_VALUE (scope->value_var) =
+	      (PN_AUDIO_DATA_PCM_DATA(audio_data, PN_CHANNEL_LEFT)[lsamp] * (1 - bias))
+	      + (PN_AUDIO_DATA_PCM_DATA(audio_data, PN_CHANNEL_LEFT)[lsamp] * bias);
+	  }
+	else
+	  PN_VARIABLE_VALUE (scope->value_var) =
+	    PN_AUDIO_DATA_PCM_DATA (audio_data, PN_CHANNEL_LEFT)[lsamp];
+      }
+
+      /* Run the sample script */
+      pn_script_execute (scope->sample_script);
+
+      /* Get the color */
+      color.red = CLAMP (PN_VARIABLE_VALUE (scope->red_var), 0.0, 1.0) * 255.0;
+      color.green = CLAMP (PN_VARIABLE_VALUE (scope->green_var), 0.0, 1.0) * 255.0;
+      color.blue = CLAMP (PN_VARIABLE_VALUE (scope->blue_var), 0.0, 1.0) * 255.0;
+
+      /* Render the point */
+      x = rint ((PN_VARIABLE_VALUE (scope->x_var) + 1.0) * ((gdouble) half_width ));
+      y = rint ((PN_VARIABLE_VALUE (scope->y_var) - 1.0) * ((gdouble) neg_half_height));
+
+      if (use_lines)
+	{
+	  if (i > 0)
+	    pn_image_render_line (image, last_x, last_y, x, y, color);
+
+	  last_x = x;
+	  last_y = y;
+	}
+      else
+	pn_image_render_pixel (image, x, y, color);
+    }
+
+  if (parent_class->execute)
+    parent_class->execute (PN_ACTUATOR (scope), image, audio_data);
+}
+
+PnScope*
+pn_scope_new (void)
+{
+  return (PnScope *) g_object_new (PN_TYPE_SCOPE, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnscope.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,86 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_SCOPE_H__
+#define __PN_SCOPE_H__
+
+#include "pnactuator.h"
+#include "pnscript.h"
+#include "pnsymboltable.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_SCOPE_OPT_DRAW_METHOD = PN_ACTUATOR_OPT_LAST,
+  PN_SCOPE_OPT_INIT_SCRIPT,
+  PN_SCOPE_OPT_FRAME_SCRIPT,
+  PN_SCOPE_OPT_SAMPLE_SCRIPT,
+  PN_SCOPE_OPT_LAST
+};
+
+#define PN_TYPE_SCOPE              (pn_scope_get_type ())
+#define PN_SCOPE(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_SCOPE, PnScope))
+#define PN_SCOPE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_SCOPE, PnScopeClass))
+#define PN_IS_SCOPE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_SCOPE))
+#define PN_IS_SCOPE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_SCOPE))
+#define PN_SCOPE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_SCOPE, PnScopeClass))
+
+typedef struct _PnScope        PnScope;
+typedef struct _PnScopeClass   PnScopeClass;
+
+struct _PnScope
+{
+  PnActuator parent;
+
+  /* The script objects */
+  PnScript *init_script;
+  PnScript *frame_script;
+  PnScript *sample_script;
+  PnSymbolTable *symbol_table;
+
+  /* The in-script variables */
+  PnVariable *samples_var;
+  PnVariable *width_var;
+  PnVariable *height_var;
+  PnVariable *x_var;
+  PnVariable *y_var;
+  PnVariable *iteration_var;
+  PnVariable *value_var;
+  PnVariable *red_var;
+  PnVariable *green_var;
+  PnVariable *blue_var;
+  PnVariable *volume_var;
+};
+
+struct _PnScopeClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                 pn_scope_get_type                (void);
+PnScope              *pn_scope_new                     (void);
+
+
+
+
+
+#endif /* __PN_SCOPE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnscript.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,278 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <math.h>
+#include "pnscript.h"
+
+/* Initialization */
+static void         pn_script_class_init             (PnScriptClass *class);
+
+/* Internal parser */
+gboolean            pn_script_internal_parse_string  (PnScript *script,
+						      const gchar *string);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+pn_script_get_type (void)
+{
+  static GType script_type = 0;
+
+  if (! script_type)
+    {
+      static const GTypeInfo script_info =
+      {
+	sizeof (PnScriptClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_script_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnScript),
+	0,              /* n_preallocs */
+	NULL            /* instance_init */
+      };
+
+      /* FIXME: should this be dynamic? */
+      script_type = g_type_register_static (PN_TYPE_OBJECT,
+					    "PnScript",
+					    &script_info,
+					    0);
+    }
+  return script_type;
+}
+
+static void
+pn_script_class_init (PnScriptClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+
+  parent_class = g_type_class_peek_parent (class);
+}
+
+static void
+pn_script_unref_variables (PnScript *script)
+{
+  g_return_if_fail (script != NULL);
+  g_return_if_fail (PN_IS_SCRIPT (script));
+
+  if (script->code && script->symbol_table)
+    {
+      guint *op;
+
+      for (op = script->code; *op != PN_OP_END; op++)
+	switch (*op)
+	  {
+	  case PN_OP_PUSHC:
+	    op++;
+	    break;
+
+	  case PN_OP_PUSHV:
+	    pn_symbol_table_unref_variable (script->symbol_table, PN_VARIABLE (*(++op)));
+	    break;
+
+	  case PN_OP_SET:
+	    pn_symbol_table_unref_variable (script->symbol_table, PN_VARIABLE (*(++op)));
+	    break;
+	  }
+    }
+}
+
+/**
+ * pn_script_new
+ *
+ * Creates a new #PnScript object.
+ *
+ * Returns: The newly created #PnScript object
+ */
+PnScript*
+pn_script_new (void)
+{
+  return (PnScript *) g_object_new (PN_TYPE_SCRIPT, NULL);
+}
+
+/**
+ * pn_script_parse_string
+ * @script: A #PnScript
+ * @symbol_table: the #PnSymbolTable to associate with the script
+ * @string: a string containing the script
+ *
+ * Parses a script, compiling it to a bytecode that is stored within the script object.
+ * All in-script variables within the script are added to the specified symbol table (if
+ * they are not already in it).  If errors are encountered while parsing the script,
+ * they are output using pn_error().
+ *
+ * Returns: %TRUE on success; %FALSE otherwise
+ */
+gboolean
+pn_script_parse_string (PnScript *script, PnSymbolTable *symbol_table, const gchar *string)
+{
+  g_return_val_if_fail (script != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_SCRIPT (script), FALSE);
+  g_return_val_if_fail (symbol_table != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_SYMBOL_TABLE (symbol_table), FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  /* Make sure if it's the same symbol table, we don't destroy it */
+  pn_object_ref (PN_OBJECT (symbol_table));
+  pn_object_sink (PN_OBJECT (symbol_table));
+
+  /* get rid of the old script */
+  if (script->symbol_table)
+    {
+      pn_script_unref_variables (script);
+      pn_object_unref (PN_OBJECT (script->symbol_table));
+    }
+  if (script->stack)
+    {
+      g_free (script->stack);
+      script->stack = NULL;
+    }
+  if (script->code)
+    {
+      g_free (script->code);
+      script->code = NULL;
+    }
+  if (script->constant_table)
+    {
+      g_free (script->constant_table);
+      script->constant_table = NULL;
+    }
+ 
+  /* Set our new symbol table */
+  script->symbol_table = symbol_table;
+
+  return pn_script_internal_parse_string (script, string);
+}
+
+/**
+ * pn_script_execute
+ * @script: a #PnScript
+ *
+ * Executes a script, updating all variabes in the associated symbol
+ * table as the script dictates.
+ */
+void
+pn_script_execute (PnScript *script)
+{
+  guint *op;
+  gdouble stack[64];
+  guint stack_top = 0;
+
+  g_return_if_fail (script != NULL);
+  g_return_if_fail (PN_IS_SCRIPT (script));
+
+  if (! script->code)
+    return;
+
+  for (op = script->code; *op != PN_OP_END; op++)
+    switch (*op)
+      {
+#define PUSH(f) stack[stack_top++] = f;
+#define POP stack_top--;
+#define POPV (stack[--stack_top])
+#define PEEK (stack[stack_top-1])
+#define PEEKN(n) (stack[stack_top-n])
+      case PN_OP_PUSHC:
+      case PN_OP_PUSHV:
+	PUSH (* (gdouble *)(*(++op)));
+	break;
+
+      case PN_OP_POP:
+	POP;
+	break;
+
+      case PN_OP_SET:
+	*(gdouble *)(*(++op)) = PEEK;
+	break;
+
+      case PN_OP_ADD:
+	PEEKN (2) += POPV;
+	break;
+
+      case PN_OP_SUB:
+	PEEKN (2) -= POPV;
+	break;
+
+      case PN_OP_MUL:
+	PEEKN (2) *= POPV;
+	break;
+
+      case PN_OP_DIV:
+	if (PEEK != 0)
+	  PEEKN (2) /= PEEK;
+	else
+	  PEEK = 0;
+	POP;
+	break;
+
+      case PN_OP_NEG:
+	PEEK = -PEEK;
+	break;
+
+      case PN_OP_POW:
+	PEEKN (2) = pow (PEEKN (2), PEEK);
+	POP;
+	break;
+
+      case PN_OP_ABS:
+	PEEK = ABS (PEEK);
+	break;
+
+      case PN_OP_MAX:
+	PEEKN (2) = MAX (PEEK, PEEKN (2));
+	POP;
+	break;
+
+      case PN_OP_MIN:
+	PEEKN (2) = MIN (PEEK, PEEKN (2));
+	POP;
+	break;
+
+      case PN_OP_SIN:
+	PEEK = sin (PEEK);
+	break;
+
+      case PN_OP_COS:
+	PEEK = cos (PEEK);
+	break;
+
+      case PN_OP_TAN:
+	PEEK = tan (PEEK);
+	break;
+
+      case PN_OP_ASIN:
+	PEEK = asin (PEEK);
+	break;
+
+      case PN_OP_ACOS:
+	PEEK = acos (PEEK);
+	break;
+
+      case PN_OP_ATAN:
+	PEEK = atan (PEEK);
+	break;
+      }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnscript.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,102 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_SCRIPT_H__
+#define __PN_SCRIPT_H__
+
+#include "pnobject.h"
+#include "pnsymboltable.h"
+
+
+G_BEGIN_DECLS
+
+
+/* Opcodes */
+enum
+{
+  PN_OP_NOP,
+  PN_OP_END,
+  PN_OP_PUSHV, /* Push a variable */
+  PN_OP_PUSHC, /* Push a constant */
+  PN_OP_POP,
+  PN_OP_SET,
+  /* Arithmetic operators */
+  PN_OP_ADD,
+  PN_OP_SUB,
+  PN_OP_MUL,
+  PN_OP_DIV,
+  PN_OP_NEG,
+  PN_OP_POW,
+  /* Functions */
+  PN_OP_ABS,
+  PN_OP_MAX,
+  PN_OP_MIN,
+  PN_OP_SIN,
+  PN_OP_COS,
+  PN_OP_TAN,
+  PN_OP_ASIN,
+  PN_OP_ACOS,
+  PN_OP_ATAN,
+  PN_OP_LAST
+};
+
+#define PN_TYPE_SCRIPT              (pn_script_get_type ())
+#define PN_SCRIPT(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_SCRIPT, PnScript))
+#define PN_SCRIPT_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_SCRIPT, PnScriptClass))
+#define PN_IS_SCRIPT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_SCRIPT))
+#define PN_IS_SCRIPT_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_SCRIPT))
+#define PN_SCRIPT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_SCRIPT, PnScriptClass))
+#define PN_SCRIPT_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define PN_SCRIPT_CLASS_NAME(class) (g_type_name (PN_SCRIPT_CLASS_TYPE (class)))
+
+typedef struct _PnScript        PnScript;
+typedef struct _PnScriptClass   PnScriptClass;
+
+struct _PnScript
+{
+  PnObject parent;
+
+  /* The symbol table that is being used by the current code */
+  PnSymbolTable *symbol_table;
+
+  /* The table of constants used by the script */
+  gdouble *constant_table;
+
+  /* The byte-compiled code */
+  guint32 *code;
+
+  /* The script stack used during script execution */
+  gdouble *stack;
+};
+
+struct _PnScriptClass
+{
+  PnObjectClass parent_class;
+};
+
+/* Creators */
+GType             pn_script_get_type             (void);
+PnScript         *pn_script_new                  (void);
+
+/* Actions */
+gboolean          pn_script_parse_string         (PnScript *script,
+						  PnSymbolTable *symbol_table,
+						  const gchar *string);
+void              pn_script_execute              (PnScript *script);
+
+#endif /* __PN_SCRIPT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnscriptparser.y	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,551 @@
+%{
+#define    yymaxdepth pn_script_parser_maxdepth
+#define    yyparse    pn_script_parser_parse
+#define    yylex      pn_script_parser_lex
+#define    yyerror    pn_script_parser_error
+#define    yylval     pn_script_parser_lval
+#define    yychar     pn_script_parser_char
+#define    yydebug    pn_script_parser_debug
+#define    yypact     pn_script_parser_pact
+#define    yyr1       pn_script_parser_r1
+#define    yyr2       pn_script_parser_r2
+#define    yydef      pn_script_parser_def
+#define    yychk      pn_script_parser_chk
+#define    yypgo      pn_script_parser_pgo
+#define    yyact      pn_script_parser_act
+#define    yyexca     pn_script_parser_exca
+#define    yyerrflag  pn_script_parser_errflag
+#define    ynerrs     pn_script_parser_nerrs
+#define    yyps       pn_script_parser_ps
+#define    yypv       pn_script_parser_pv
+#define    yys        pn_script_parser_s
+#define    yy_yys     pn_script_parser_yys
+#define    yystate    pn_script_parser_state
+#define    yytmp      pn_script_parser_tmp
+#define    yyv        pn_script_parser_v
+#define    yy_yyv     pn_script_parser_yyv
+#define    yyval      pn_script_parser_val
+#define    yylloc     pn_script_parser_lloc
+#define    yyreds     pn_script_parser_reds
+#define    yytoks     pn_script_parser_toks
+#define    yylhs      pn_script_parser_yylhs
+#define    yylen      pn_script_parser_yylen
+#define    yydefred   pn_script_parser_yydefred
+#define    yydgoto    pn_script_parser_yydgoto
+#define    yysindex   pn_script_parser_yysindex
+#define    yyrindex   pn_script_parser_yyrindex
+#define    yygindex   pn_script_parser_yygindex
+#define    yytable    pn_script_parser_yytable
+#define    yycheck    pn_script_parser_yycheck
+#define    yyname     pn_script_parser_yyname
+#define    yyrule     pn_script_parser_yyrule
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <pn/pnscript.h>
+
+/* define this to dump the parser output to stdout */
+/*  #define PN_PRINT_OPS 1 */
+
+int yyerror (char *s);
+int yylex (void); 
+
+static gboolean parse_failed;
+
+/* Are we on the size-determining pass? */
+static gboolean size_pass;
+
+/* Used during the size pass to determine the size of the constant table */
+static GArray *temp_constant_table = NULL; 
+
+/* The code size */
+static guint code_size;
+
+/* The current code byte */
+static guint *code_ptr;
+ 
+/* Input variables used during parsing  */ 
+static PnScript *parse_script;
+static const gchar *parse_string;
+%}
+
+%union {
+  gdouble     *constant;
+  PnVariable *variable;
+}
+
+%token <constant> CONSTANT
+%token <variable> VARIABLE
+/* Functions */
+%token ABS_FUNC
+%token MAX_FUNC
+%token MIN_FUNC
+%token SIN_FUNC
+%token COS_FUNC
+%token TAN_FUNC
+%token ASIN_FUNC
+%token ACOS_FUNC
+%token ATAN_FUNC
+
+
+%right '='
+%left '-' '+'
+%left '*' '/'
+%left NEG
+%right '^'
+
+%%
+
+script
+	: /* empty */
+	| script statement
+	;
+
+statement
+	: equation ';'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_POP;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("POP\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	;
+
+equation
+	: VARIABLE '=' expression
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint) + sizeof (gdouble *);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_SET;
+		      *code_ptr++ = (guint) $1;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("SET %s\n", $1->name);
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+
+expression
+	: CONSTANT
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint) + sizeof (gdouble *);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_PUSHC;
+		      *code_ptr++ = GPOINTER_TO_UINT ($1);
+
+#ifdef PN_PRINT_OPS
+		      g_print ("PUSHC %f\n", *$1);
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| VARIABLE
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint) + sizeof (gdouble *);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_PUSHV;
+		      *code_ptr++ = (guint) $1;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("PUSHV %s\n", $1->name);
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| equation
+	| ABS_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_ABS;
+#ifdef PN_PRINT_OPS
+		      g_print ("ABS\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| MAX_FUNC '(' expression ',' expression  ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_MAX;
+#ifdef PN_PRINT_OPS
+		      g_print ("MAX\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| MIN_FUNC '(' expression ',' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_MIN;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("MIN\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| SIN_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_SIN;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("SIN\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| COS_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_COS;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("COS\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| TAN_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_TAN;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("TAN\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| ASIN_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_ASIN;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("ASIN\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| ACOS_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_ACOS;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("ACOS\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| ATAN_FUNC '(' expression ')'
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_ATAN;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("ATAN\n");
+#endif /* PN_PRINT_OPS */
+		    }
+
+		}
+	| expression '+' expression
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_ADD;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("ADD\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| expression '-' expression
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_SUB;
+#ifdef PN_PRINT_OPS
+		      g_print ("SUB\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| expression '*' expression
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_MUL;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("MUL\n");
+#endif /* PN_PRINT_OPS */
+		    }		      
+		}
+	| expression '/' expression
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_DIV;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("DIV\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| '-' expression %prec NEG
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_NEG;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("NEG\n");
+#endif /* PN_PRINT_OPS */
+		    }
+		}
+	| expression '^' expression
+		{
+		  if (size_pass)
+		    code_size += sizeof (guint);
+		  else
+		    {
+		      *code_ptr++ = PN_OP_POW;
+
+#ifdef PN_PRINT_OPS
+		      g_print ("POW\n");
+#endif /* PN_PRINT_OPS  */
+		    }
+		}
+	| '(' expression ')'
+	;
+
+%%
+
+static gdouble
+get_named_constant_value (const gchar *name)
+{
+  if (g_strcasecmp (name, "pi") == 0)
+    return G_PI;
+
+  /* This is a failure, so don't make a "zero" :) */
+  return 0.0;
+}
+
+static guint
+get_function_token_type (const gchar *name)
+{
+  if (g_strcasecmp (name, "abs") == 0)
+    return ABS_FUNC;
+  if (g_strcasecmp (name, "max") == 0)
+    return MAX_FUNC;
+  if (g_strcasecmp (name, "min") == 0)
+    return MIN_FUNC;
+  if (g_strcasecmp (name, "sin") == 0)
+    return SIN_FUNC;
+  if (g_strcasecmp (name, "cos") == 0)
+    return COS_FUNC;
+  if (g_strcasecmp (name, "tan") == 0)
+    return TAN_FUNC;
+  if (g_strcasecmp (name, "asin") == 0)
+    return ASIN_FUNC;
+  if (g_strcasecmp (name, "acos") == 0)
+    return ACOS_FUNC;
+  if (g_strcasecmp (name, "atan") == 0)
+    return ATAN_FUNC;
+
+  return 0;
+}
+
+static gdouble*
+get_constant_ptr (gdouble value)
+{
+  guint i;
+
+  if (size_pass)
+    {
+      for (i=0; i<temp_constant_table->len; i++)
+	if (g_array_index (temp_constant_table, gdouble, i) == value)
+	  return (gdouble *) TRUE;
+
+      /* Add a constant */
+      g_array_append_val (temp_constant_table, value);
+      return (gdouble *) TRUE;
+    }
+  else
+    {
+      for (i=0; i<temp_constant_table->len; i++)
+	if (parse_script->constant_table[i] == value)
+	  return &parse_script->constant_table[i];
+
+      return NULL; /* This should never be reached */
+    }
+}
+
+int
+yylex (void)
+{
+  /* Skip whitespaces */
+  while (isspace (*parse_string)) parse_string++;
+
+  /* Handle the end of the string */
+  if (*parse_string == '\0')
+    return 0;
+
+  /* Handle unnamed (numeric) constants */
+  if (*parse_string == '.' || isdigit (*parse_string))
+    {
+      gdouble value;
+
+      value = strtod (parse_string, (char **) &parse_string);
+      yylval.constant = get_constant_ptr (value);
+
+      return CONSTANT;
+    }
+
+  /* Handle alphanumeric symbols */
+  if (isalpha (*parse_string))
+    {
+      const gchar *symbol_start = parse_string;
+      guint function_token;
+      gchar *symbol_name;
+
+      while (isalnum (*parse_string) || *parse_string == '_') parse_string++;
+
+      symbol_name = g_strndup (symbol_start, parse_string - symbol_start);
+
+      /* Handle a named constant (e.g. 'pi') */
+      if (get_named_constant_value (symbol_name))
+	{
+	  yylval.constant = get_constant_ptr (get_named_constant_value (symbol_name));
+
+	  g_free (symbol_name);
+
+	  return CONSTANT;
+	}
+
+      /* Handle a function (e.g. 'max') */
+      if ((function_token = get_function_token_type (symbol_name)))
+	{
+	  g_free (symbol_name);
+
+	  return function_token;
+	}
+
+      /* Handle a variable */
+      if (! size_pass)
+	yylval.variable = pn_symbol_table_ref_variable_by_name (parse_script->symbol_table,
+								symbol_name);
+
+      g_free (symbol_name);
+
+      return VARIABLE;
+    }
+
+  /* Handle a single-character symbol (or invalid tokens) */
+  return *parse_string++;
+}
+
+int
+yyerror (char *s)
+{
+  parse_failed = TRUE;
+
+  return 0;
+}
+
+gboolean
+pn_script_internal_parse_string (PnScript *script, const gchar *string)
+{
+  guint i;
+
+  g_return_val_if_fail (script != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_SCRIPT (script), FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  /* Make a new temp constant table if needed */
+  if (! temp_constant_table)
+    temp_constant_table = g_array_new (FALSE, FALSE, sizeof (gdouble));
+
+  parse_failed = FALSE;
+
+  parse_script = script;
+  parse_string = string;
+
+  /* First determine the code size */
+  size_pass = TRUE;
+  code_size = 0;
+  yyparse ();
+
+  if (parse_failed)
+    return FALSE;
+
+  if (code_size == 0)
+    return TRUE;
+
+  /* Now generate the real code */
+  size_pass = FALSE;
+  parse_string = string;
+  script->code = g_malloc (code_size);
+  script->constant_table = g_malloc (temp_constant_table->len * sizeof (gdouble));
+  for (i=0; i<temp_constant_table->len; i++)
+    script->constant_table[i] = g_array_index (temp_constant_table, gdouble, i);
+  code_ptr = script->code;
+  yyparse ();
+  g_array_set_size (temp_constant_table, 0);
+
+  /* Terminate the script, replacing the last POP with an END  */
+  *(code_ptr-1) = PN_OP_END;
+
+#ifdef PN_PRINT_OPS
+  g_print ("END\n");
+#endif /* PN_PRINT_OPS */
+
+  return TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnstringoption.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,185 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <glib.h>
+#include "pnstringoption.h"
+#include "pnxml.h"
+#include "pnerror.h"
+
+static void         pn_string_option_class_init       (PnStringOptionClass *class);
+static void         pn_string_option_init             (PnStringOption *string_option,
+						       PnStringOptionClass *class);
+
+/* PnUserObject methods */
+static void         pn_string_option_save_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+static void         pn_string_option_load_thyself     (PnUserObject *user_object,
+							xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+static gchar * const empty_string = "";
+
+GType
+pn_string_option_get_type (void)
+{
+  static GType string_option_type = 0;
+
+  if (! string_option_type)
+    {
+      static const GTypeInfo string_option_info =
+      {
+	sizeof (PnStringOptionClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_string_option_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnStringOption),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_string_option_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      string_option_type = g_type_register_static (PN_TYPE_OPTION,
+					      "PnStringOption",
+					      &string_option_info,
+					      0);
+    }
+  return string_option_type;
+}
+
+static void
+pn_string_option_class_init (PnStringOptionClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnOptionClass *option_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  option_class = (PnOptionClass *) class;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_string_option_save_thyself;
+  user_object_class->load_thyself = pn_string_option_load_thyself;
+
+  /* PnOption methods */
+  /* FIXME: this needs to be uncommented when the widget is done */
+/*    option_class->widget_type = PN_TYPE_STRING_OPTION_WIDGET; */
+}
+
+static void
+pn_string_option_init (PnStringOption *string_option, PnStringOptionClass *class)
+{
+  string_option->value = empty_string;
+}
+
+static void
+pn_string_option_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnStringOption *string_option;
+  xmlNodePtr value_node;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_STRING_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  string_option = (PnStringOption *) user_object;
+  value_node = xmlNewChild (node, NULL, "Value", NULL);
+  xmlNodeSetContent (value_node, string_option->value);
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_string_option_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnStringOption *string_option;
+  xmlNodePtr string_option_node;
+  gchar *val_str;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_STRING_OPTION (user_object));
+  g_return_if_fail (node != NULL);
+
+  string_option = (PnStringOption *) user_object;
+
+  for (string_option_node = node->xmlChildrenNode;
+       string_option_node;
+       string_option_node = string_option_node->next)
+    if (g_strcasecmp (string_option_node->name, "Value") == 0)
+      break;
+  if (! string_option_node)
+    {
+      pn_error ("unable to load a PnStringOption from xml node \"%s\"", node->name);
+      return;
+    }
+
+  val_str = xmlNodeGetContent (string_option_node);
+  if (val_str)
+    pn_string_option_set_value (string_option, val_str);
+  else
+    pn_string_option_set_value (string_option, empty_string);
+
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+PnStringOption*
+pn_string_option_new (const gchar *name, const gchar *desc)
+{
+  PnStringOption *string_option;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (desc != NULL, NULL);
+
+  string_option =   (PnStringOption *) g_object_new (PN_TYPE_STRING_OPTION, NULL);
+
+  pn_user_object_set_name (PN_USER_OBJECT (string_option), name);
+  pn_user_object_set_description (PN_USER_OBJECT (string_option), desc);
+
+  return string_option;
+}
+
+void
+pn_string_option_set_value (PnStringOption *string_option, const gchar *value)
+{
+  g_return_if_fail (string_option != NULL);
+  g_return_if_fail (PN_IS_STRING_OPTION (string_option));
+  g_return_if_fail (value != NULL);
+
+  if (string_option->value && string_option->value != empty_string)
+    g_free (string_option->value);
+
+  string_option->value = g_strdup (value);
+}
+
+gchar*
+pn_string_option_get_value (PnStringOption *string_option)
+{
+  g_return_val_if_fail (string_option != NULL, FALSE);
+  g_return_val_if_fail (PN_IS_STRING_OPTION (string_option), FALSE);
+
+  return string_option->value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnstringoption.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,64 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_STRING_OPTION_H__
+#define __PN_STRING_OPTION_H__
+
+#include "pnoption.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_STRING_OPTION              (pn_string_option_get_type ())
+#define PN_STRING_OPTION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_STRING_OPTION, PnStringOption))
+#define PN_STRING_OPTION_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_STRING_OPTION, PnStringOptionClass))
+#define PN_IS_STRING_OPTION(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_STRING_OPTION))
+#define PN_IS_STRING_OPTION_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_STRING_OPTION))
+#define PN_STRING_OPTION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_STRING_OPTION, PnStringOptionClass))
+
+typedef struct _PnStringOption        PnStringOption;
+typedef struct _PnStringOptionClass   PnStringOptionClass;
+
+struct _PnStringOption
+{
+  PnOption parent;
+
+  gchar *value;
+};
+
+struct _PnStringOptionClass
+{
+  PnOptionClass parent_class;
+};
+
+/* Creators */
+GType                 pn_string_option_get_type                (void);
+PnStringOption      *pn_string_option_new                     (const gchar *name,
+								 const gchar *desc);
+
+/* Accessors */
+void                  pn_string_option_set_value               (PnStringOption *string_option,
+								 const gchar *value);
+gchar                *pn_string_option_get_value               (PnStringOption *string_option);
+
+
+
+
+
+#endif /* __PN_STRING_OPTION_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnsymboltable.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,168 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include "pnsymboltable.h"
+
+/* Initialization */
+static void         pn_symbol_table_class_init        (PnSymbolTableClass *class);
+
+static GObjectClass *parent_class = NULL;
+
+
+
+GType
+pn_symbol_table_get_type (void)
+{
+  static GType symbol_table_type = 0;
+
+  if (! symbol_table_type)
+    {
+      static const GTypeInfo symbol_table_info =
+      {
+	sizeof (PnSymbolTableClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_symbol_table_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnSymbolTable),
+	0,              /* n_preallocs */
+	NULL            /* instance_init */
+      };
+
+      /* FIXME: should this be dynamic? */
+      symbol_table_type = g_type_register_static (PN_TYPE_OBJECT,
+					    "PnSymbolTable",
+					    &symbol_table_info,
+					    0);
+    }
+  return symbol_table_type;
+}
+
+static void
+pn_symbol_table_class_init (PnSymbolTableClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+
+  parent_class = g_type_class_peek_parent (class);
+}
+
+/**
+ * pn_symbol_table_new
+ *
+ * Creates a new #PnSymbolTable object.
+ *
+ * Returns: The newly created #PnSymbolTable object
+ */
+PnSymbolTable*
+pn_symbol_table_new (void)
+{
+  return (PnSymbolTable *) g_object_new (PN_TYPE_SYMBOL_TABLE, NULL);
+}
+
+/**
+ * pn_symbol_table_ref_variable_by_name
+ * @symbol_table: a #PnSymbolTable
+ * @name: the name a an in-script variable
+ *
+ * Retrieves an in-script variable contained within a symbol table and increments the
+ * variable's reference count. If the variable is not yet in the symbol table, it is
+ * added (with a value of 0.0).
+ *
+ * Returns: A pointer to the variable object
+ */
+PnVariable*
+pn_symbol_table_ref_variable_by_name (PnSymbolTable *symbol_table, const gchar *name)
+{
+  GList *cur;
+  PnVariable *variable;
+  
+  g_return_val_if_fail (symbol_table != NULL, NULL);
+  g_return_val_if_fail (PN_IS_SYMBOL_TABLE (symbol_table), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  /* If the variable already exists, return it */
+  for (cur = symbol_table->variables; cur; cur = cur->next)
+    if (g_strcasecmp (PN_VARIABLE (cur->data)->name, name) == 0)
+      {
+	PN_VARIABLE (cur->data)->refs++;
+	return PN_VARIABLE (cur->data);
+      }
+
+  /* We need to make a new variable */
+  variable = g_new (PnVariable, 1);
+  variable->value = 0.0;
+  variable->name = g_strdup (name);
+  variable->refs = 1;
+
+  /* Add the variable to the list */
+  symbol_table->variables = g_list_prepend (symbol_table->variables, variable);
+
+  return variable;
+}
+
+/**
+ * pn_symbol_table_ref_variable
+ * @symbol_table: a #PnSymbolTable
+ * @variable: an in-script variable belonging to @symbol_table
+ *
+ * Increments the reference count of an in-script variable contained within
+ * a symbol table.
+ */
+void
+pn_symbol_table_ref_variable (PnSymbolTable *symbol_table, PnVariable *variable)
+{
+  g_return_if_fail (symbol_table != NULL);
+  g_return_if_fail (PN_IS_SYMBOL_TABLE (symbol_table));
+  g_return_if_fail (variable != NULL);
+
+  /* FIXME: Check to ensure the variable belongs to the symtab */
+
+  variable->refs++;
+}
+
+/**
+ * pn_symbol_table_unref_variable
+ * @symbol_table: a #PnSymbolTable
+ * @variable: an in-script variable belonging to @symbol_table
+ *
+ * Decrements the reference count of an in-script variable.  If the reference
+ * count becomes 0, the variable is freed from memory.
+ */ 
+void
+pn_symbol_table_unref_variable (PnSymbolTable *symbol_table, PnVariable *variable)
+{
+  g_return_if_fail (symbol_table != NULL);
+  g_return_if_fail (PN_IS_SYMBOL_TABLE (symbol_table));
+  g_return_if_fail (variable != NULL);
+
+  variable->refs--;
+
+  if (variable->refs <= 0)
+    {
+      g_free (variable->name);
+      g_free (variable);
+      symbol_table->variables = g_list_remove (symbol_table->variables, variable);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnsymboltable.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,83 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_SYMBOL_TABLE_H__
+#define __PN_SYMBOL_TABLE_H__
+
+#include "pnobject.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_SYMBOL_TABLE              (pn_symbol_table_get_type ())
+#define PN_SYMBOL_TABLE(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_SYMBOL_TABLE, PnSymbolTable))
+#define PN_SYMBOL_TABLE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_SYMBOL_TABLE, PnSymbolTableClass))
+#define PN_IS_SYMBOL_TABLE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_SYMBOL_TABLE))
+#define PN_IS_SYMBOL_TABLE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_SYMBOL_TABLE))
+#define PN_SYMBOL_TABLE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_SYMBOL_TABLE, PnSymbolTableClass))
+#define PN_SYMBOL_TABLE_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define PN_SYMBOL_TABLE_CLASS_NAME(class) (g_type_name (PN_SYMBOL_TABLE_CLASS_TYPE (class)))
+
+#define PN_VARIABLE(var)                  ((PnVariable *) var)
+#define PN_VARIABLE_VALUE(var)            (PN_VARIABLE (var)->value)
+#define PN_VARIABLE_NAME(var)             (PN_VARIABLE (var)->name)
+
+typedef struct _PnVariable           PnVariable;
+typedef struct _PnSymbolTable        PnSymbolTable;
+typedef struct _PnSymbolTableClass   PnSymbolTableClass;
+
+struct _PnVariable
+{
+  /*< public >*/
+  gdouble value; /* read-write */
+  gchar *name;   /* read-only */
+
+  /*< private >*/
+  guint refs;
+};
+
+struct _PnSymbolTable
+{
+  PnObject parent;
+
+  GList *variables;
+};
+
+struct _PnSymbolTableClass
+{
+  PnObjectClass parent_class;
+};
+
+/* Creators */
+GType             pn_symbol_table_get_type             (void);
+PnSymbolTable    *pn_symbol_table_new                  (void);
+
+/* Accessors */
+PnVariable       *pn_symbol_table_ref_variable_by_name (PnSymbolTable *symbol_table,
+							const gchar *name);
+void              pn_symbol_table_ref_variable         (PnSymbolTable *symbol_table,
+							PnVariable *variable);
+void              pn_symbol_table_unref_variable       (PnSymbolTable *symbol_table,
+							PnVariable *variable);
+
+
+
+
+
+#endif /* __PN_SYMBOL_TABLE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pntestactuator.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,180 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include "pntestactuator.h"
+#include "pnbooleanoption.h"
+#include "pnintegeroption.h"
+#include "pnfloatoption.h"
+#include "pnstringoption.h"
+#include "pnerror.h"
+
+static void         pn_test_actuator_class_init       (PnTestActuatorClass *class);
+static void         pn_test_actuator_init             (PnTestActuator *test_actuator,
+						       PnTestActuatorClass *class);
+/* PnActuator methods */
+static void         pn_test_actuator_prepare          (PnTestActuator *test_actuator,
+						       PnImage *image);
+static void         pn_test_actuator_execute          (PnTestActuator *test_actuator,
+						       PnImage *image,
+						       PnAudioData *audio_data);
+
+static PnActuatorClass *parent_class = NULL;
+
+GType
+pn_test_actuator_get_type (void)
+{
+  static GType test_actuator_type = 0;
+
+  if (! test_actuator_type)
+    {
+      static const GTypeInfo test_actuator_info =
+      {
+	sizeof (PnTestActuatorClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_test_actuator_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnTestActuator),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_test_actuator_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      test_actuator_type = g_type_register_static (PN_TYPE_ACTUATOR,
+					      "PnTestActuator",
+					      &test_actuator_info,
+					      0);
+    }
+  return test_actuator_type;
+}
+
+static void
+pn_test_actuator_class_init (PnTestActuatorClass *class)
+{
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+  PnActuatorClass *actuator_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+  actuator_class = (PnActuatorClass *) class;
+
+  /* PnActuator methods */
+  actuator_class->prepare = (PnActuatorPrepFunc) pn_test_actuator_prepare;
+  actuator_class->execute = (PnActuatorExecFunc) pn_test_actuator_execute;
+}
+
+static void
+pn_test_actuator_init (PnTestActuator *test_actuator, PnTestActuatorClass *class)
+{
+  PnBooleanOption *test_bool_opt;
+  PnIntegerOption *test_int_opt;
+  PnFloatOption *test_float_opt;
+  PnStringOption *test_str_opt;
+
+  /* Set up the name and description */
+  pn_user_object_set_name (PN_USER_OBJECT (test_actuator), "Test.Test");
+  pn_user_object_set_description (PN_USER_OBJECT (test_actuator),
+				  "An actuator to test the functionality of the PnActuator base class");
+
+  /* Set up the options */
+  test_bool_opt = pn_boolean_option_new ("test_boolean_option", "A boolean test option");
+  pn_boolean_option_set_value (test_bool_opt, TRUE);
+
+  test_int_opt = pn_integer_option_new ("test_integer_option", "An integer test option");
+  pn_integer_option_set_value (test_int_opt, 32);
+  pn_integer_option_set_min (test_int_opt, 16);
+  pn_integer_option_set_max (test_int_opt, 64);
+
+  test_float_opt = pn_float_option_new ("test_float_option", "A float test option");
+  pn_float_option_set_value (test_float_opt, 0.7);
+  pn_float_option_set_min (test_float_opt, 0.0);
+  pn_float_option_set_max (test_float_opt, 1.0);
+
+  test_str_opt = pn_string_option_new ("test_string_option", "A string test option");
+
+  pn_actuator_add_option (PN_ACTUATOR (test_actuator), PN_OPTION (test_bool_opt));
+  pn_actuator_add_option (PN_ACTUATOR (test_actuator), PN_OPTION (test_int_opt));
+  pn_actuator_add_option (PN_ACTUATOR (test_actuator), PN_OPTION (test_float_opt));
+  pn_actuator_add_option (PN_ACTUATOR (test_actuator), PN_OPTION (test_str_opt));
+}
+
+static void
+pn_test_actuator_prepare (PnTestActuator *test_actuator, PnImage *image)
+{
+  g_return_if_fail (test_actuator != NULL);
+  g_return_if_fail (PN_IS_TEST_ACTUATOR (test_actuator));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+
+  pn_error ("pn_test_actuator_prepare called");
+}
+
+static void
+pn_test_actuator_execute (PnTestActuator *test_actuator, PnImage *image,
+			  PnAudioData *audio_data)
+{
+  PnOption *test_bool_opt, *test_int_opt, *test_float_opt, *test_str_opt;
+  PnColor color = { 0, 0, 0, 0 };
+  guint i;
+
+  g_return_if_fail (test_actuator != NULL);
+  g_return_if_fail (PN_IS_TEST_ACTUATOR (test_actuator));
+  g_return_if_fail (image != NULL);
+  g_return_if_fail (PN_IS_IMAGE (image));
+  g_return_if_fail (audio_data != NULL);
+/*    g_return_if_fail (PN_IS_AUDIO_DATA (audio_data)); */
+
+  test_bool_opt = pn_actuator_get_option_by_index (PN_ACTUATOR (test_actuator),
+						   PN_TEST_ACTUATOR_OPT_TEST_BOOL);
+  test_int_opt = pn_actuator_get_option_by_index (PN_ACTUATOR (test_actuator),
+						  PN_TEST_ACTUATOR_OPT_TEST_INT);
+  test_float_opt = pn_actuator_get_option_by_index (PN_ACTUATOR (test_actuator),
+						    PN_TEST_ACTUATOR_OPT_TEST_FLOAT);
+  test_str_opt = pn_actuator_get_option_by_index (PN_ACTUATOR (test_actuator),
+						  PN_TEST_ACTUATOR_OPT_TEST_STR);
+
+/*    printf ("pn_test_actuator_execute: %s = %d\n", */
+/*  	  pn_user_object_get_name (PN_USER_OBJECT (test_bool_opt)), */
+/*  	  pn_boolean_option_get_value (PN_BOOLEAN_OPTION (test_bool_opt))); */
+/*    printf ("pn_test_actuator_execute: %s = %d\n", */
+/*  	  pn_user_object_get_name (PN_USER_OBJECT (test_int_opt)), */
+/*  	  pn_integer_option_get_value (PN_INTEGER_OPTION (test_int_opt))); */
+/*    printf ("pn_test_actuator_execute: %s = %f\n", */
+/*  	  pn_user_object_get_name (PN_USER_OBJECT (test_float_opt)), */
+/*  	  pn_float_option_get_value (PN_FLOAT_OPTION (test_float_opt))); */
+/*    printf ("pn_test_actuator_execute: %s = \"%s\"\n", */
+/*  	  pn_user_object_get_name (PN_USER_OBJECT (test_str_opt)), */
+/*  	  pn_string_option_get_value (PN_STRING_OPTION (test_str_opt))); */
+
+  for (i=0; i<pn_image_get_width (image) *  64; i++)
+    {
+      color.red = i % 256;
+      pn_image_render_pixel_by_offset (image, i, color);
+    }
+}
+
+PnTestActuator*
+pn_test_actuator_new (void)
+{
+  return (PnTestActuator *) g_object_new (PN_TYPE_TEST_ACTUATOR, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pntestactuator.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,61 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_TEST_ACTUATOR_H__
+#define __PN_TEST_ACTUATOR_H__
+
+#include "pnactuator.h"
+
+
+G_BEGIN_DECLS
+
+
+enum
+{
+  PN_TEST_ACTUATOR_OPT_TEST_BOOL = PN_ACTUATOR_OPT_LAST,
+  PN_TEST_ACTUATOR_OPT_TEST_INT,
+  PN_TEST_ACTUATOR_OPT_TEST_FLOAT,
+  PN_TEST_ACTUATOR_OPT_TEST_STR,
+  PN_TEST_ACTUATOR_OPT_LAST
+};
+
+#define PN_TYPE_TEST_ACTUATOR              (pn_test_actuator_get_type ())
+#define PN_TEST_ACTUATOR(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_TEST_ACTUATOR, PnTestActuator))
+#define PN_TEST_ACTUATOR_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_TEST_ACTUATOR, PnTestActuatorClass))
+#define PN_IS_TEST_ACTUATOR(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_TEST_ACTUATOR))
+#define PN_IS_TEST_ACTUATOR_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_TEST_ACTUATOR))
+#define PN_TEST_ACTUATOR_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_TEST_ACTUATOR, PnTestActuatorClass))
+
+typedef struct _PnTestActuator        PnTestActuator;
+typedef struct _PnTestActuatorClass   PnTestActuatorClass;
+
+struct _PnTestActuator
+{
+  PnActuator parent;
+};
+
+struct _PnTestActuatorClass
+{
+  PnActuatorClass parent_class;
+};
+
+/* Creators */
+GType                 pn_test_actuator_get_type                (void);
+PnTestActuator       *pn_test_actuator_new                     (void);
+
+#endif /* __PN_TEST_ACTUATOR_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnuserobject.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,178 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include "pnuserobject.h"
+
+/* Initialization */
+static void         pn_user_object_class_init        (PnUserObjectClass *class);
+
+/* PnUserObject methods */
+static void         pn_user_object_real_save_thyself (PnUserObject *user_object,
+						      xmlNodePtr node);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+pn_user_object_get_type (void)
+{
+  static GType user_object_type = 0;
+
+  if (! user_object_type)
+    {
+      static const GTypeInfo user_object_info =
+      {
+	sizeof (PnUserObjectClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_user_object_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnUserObject),
+	0,              /* n_preallocs */
+	NULL            /* instance_init */
+      };
+
+      /* FIXME: should this be dynamic? */
+      user_object_type = g_type_register_static (PN_TYPE_OBJECT,
+					    "PnUserObject",
+					    &user_object_info,
+					    G_TYPE_FLAG_ABSTRACT);
+    }
+  return user_object_type;
+}
+
+static void
+pn_user_object_class_init (PnUserObjectClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+
+  /* PnUserObject methods */
+  class->save_thyself = pn_user_object_real_save_thyself;
+
+  parent_class = g_type_class_peek_parent (class);
+}
+
+static void
+pn_user_object_real_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (user_object));
+  g_return_if_fail (node != NULL);
+
+  xmlNodeSetName (node, user_object->name);
+}
+
+void
+pn_user_object_set_name (PnUserObject *user_object, const gchar *name)
+{
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (user_object));
+  g_return_if_fail (name != NULL);
+
+  if (user_object->name)
+    g_free (user_object->name);
+
+  user_object->name = g_strdup (name);
+}
+
+gchar*
+pn_user_object_get_name (PnUserObject *user_object)
+{
+  g_return_val_if_fail (user_object != NULL, NULL);
+  g_return_val_if_fail (PN_IS_USER_OBJECT (user_object), NULL);
+
+  return user_object->name;
+}
+
+void
+pn_user_object_set_description (PnUserObject *user_object, const gchar *desc)
+{
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (user_object));
+  g_return_if_fail (desc != NULL);
+
+  if (user_object->desc)
+    g_free (user_object->desc);
+
+  user_object->desc = g_strdup (desc);
+}
+
+gchar*
+pn_user_object_get_description (PnUserObject *user_object)
+{
+  g_return_val_if_fail (user_object != NULL, NULL);
+  g_return_val_if_fail (PN_IS_USER_OBJECT (user_object), NULL);
+
+  return user_object->desc;
+}
+
+void
+pn_user_object_set_owner (PnUserObject *user_object, PnUserObject *owner)
+{
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (user_object));
+  g_return_if_fail (owner != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (owner));
+
+  user_object->owner = owner;
+}
+
+PnUserObject*
+pn_user_object_get_owner (PnUserObject *user_object)
+{
+  g_return_val_if_fail (user_object != NULL, NULL);
+  g_return_val_if_fail (PN_IS_USER_OBJECT (user_object), NULL);
+
+  return user_object->owner;
+}
+
+void
+pn_user_object_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnUserObjectClass *class;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (user_object));
+  g_return_if_fail (node != NULL);
+
+  class = PN_USER_OBJECT_GET_CLASS (user_object);
+
+  if (class->save_thyself)
+    class->save_thyself (user_object, node);
+}
+
+void
+pn_user_object_load_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnUserObjectClass *class;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_USER_OBJECT (user_object));
+  g_return_if_fail (node != NULL);
+
+  class = PN_USER_OBJECT_GET_CLASS (user_object);
+
+  if (class->load_thyself)
+    class->load_thyself (user_object, node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnuserobject.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,91 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_USER_OBJECT_H__
+#define __PN_USER_OBJECT_H__
+
+#include "pnobject.h"
+#include "pnxml.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_USER_OBJECT              (pn_user_object_get_type ())
+#define PN_USER_OBJECT(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_USER_OBJECT, PnUserObject))
+#define PN_USER_OBJECT_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_USER_OBJECT, PnUserObjectClass))
+#define PN_IS_USER_OBJECT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_USER_OBJECT))
+#define PN_IS_USER_OBJECT_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_USER_OBJECT))
+#define PN_USER_OBJECT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_USER_OBJECT, PnUserObjectClass))
+#define PN_USER_OBJECT_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define PN_USER_OBJECT_CLASS_NAME(class) (g_type_name (PN_USER_OBJECT_CLASS_TYPE (class)))
+
+#define PN_USER_OBJECT_TYPE(obj)         (G_TYPE_FROM_INSTANCE (obj))
+#define PN_USER_OBJECT_TYPE_NAME(obj)    (g_type_name (PN_USER_OBJECT_TYPE (obj)))
+
+#define PN_USER_OBJECT_NAME(obj)         (PN_USER_OBJECT (obj)->name)
+#define PN_USER_OBJECT_DESC(obj)         (PN_USER_OBJECT (obj)->desc)
+#define PN_USER_OBJECT_OWNER(obj)        (PN_USER_OBJECT (obj)->owner)
+
+typedef struct _PnUserObject        PnUserObject;
+typedef struct _PnUserObjectClass   PnUserObjectClass;
+
+struct _PnUserObject
+{
+  PnObject parent;
+
+  gchar *name;
+  gchar *desc;
+  PnUserObject *owner;
+};
+
+struct _PnUserObjectClass
+{
+  PnObjectClass parent_class;
+
+  void (* save_thyself) (PnUserObject *user_object,
+			 xmlNodePtr node);
+  void (* load_thyself) (PnUserObject *user_object,
+			 xmlNodePtr node);
+};
+
+GType             pn_user_object_get_type             (void);
+#define           pn_user_object_destroy(object)      pn_object_destroy (PN_OBJECT (object))
+
+/* Accessors */
+void              pn_user_object_set_name             (PnUserObject *user_object,
+						       const gchar *name);
+gchar            *pn_user_object_get_name             (PnUserObject *user_object);
+void              pn_user_object_set_description      (PnUserObject *user_object,
+						       const gchar *desc);
+gchar            *pn_user_object_get_description      (PnUserObject *user_object);
+void              pn_user_object_set_owner            (PnUserObject *user_object,
+						       PnUserObject *owner);
+PnUserObject     *pn_user_object_get_owner            (PnUserObject *user_object);
+
+/* Actions */
+void              pn_user_object_save_thyself         (PnUserObject *user_object,
+						       xmlNodePtr node);
+void              pn_user_object_load_thyself         (PnUserObject *user_object,
+						       xmlNodePtr node);
+
+
+
+
+
+#endif /* __PN_USER_OBJECT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnvis.c	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,323 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "pnvis.h"
+#include "pnactuatorfactory.h"
+#include "pnerror.h"
+
+static void         pn_vis_class_init       (PnVisClass *class);
+static void         pn_vis_init             (PnVis *vis,
+					     PnVisClass *class);
+
+/* GObject signals */
+static void         pn_vis_finalize         (GObject *gobject);
+
+/* PnObject signals */
+static void         pn_vis_destroy          (PnObject *object);
+
+/* PnUserObject methods */
+static void         pn_vis_save_thyself     (PnUserObject *user_object,
+					     xmlNodePtr node);
+static void         pn_vis_load_thyself     (PnUserObject *user_object,
+					     xmlNodePtr node);
+
+static PnUserObjectClass *parent_class = NULL;
+
+GType
+pn_vis_get_type (void)
+{
+  static GType vis_type = 0;
+
+  if (! vis_type)
+    {
+      static const GTypeInfo vis_info =
+      {
+	sizeof (PnVisClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) pn_vis_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+        sizeof (PnVis),
+	0,              /* n_preallocs */
+	(GInstanceInitFunc) pn_vis_init
+      };
+
+      /* FIXME: should this be dynamic? */
+      vis_type = g_type_register_static (PN_TYPE_USER_OBJECT,
+					 "PnVis",
+					 &vis_info,
+					 0);
+    }
+  return vis_type;
+}
+
+static void
+pn_vis_class_init (PnVisClass *class)
+{
+  GObjectClass *gobject_class;
+  PnObjectClass *object_class;
+  PnUserObjectClass *user_object_class;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  gobject_class = (GObjectClass *) class;
+  object_class = (PnObjectClass *) class;
+  user_object_class = (PnUserObjectClass *) class;
+
+  /* GObject signals */
+  gobject_class->finalize = pn_vis_finalize;
+
+  /* PnObject signals */
+  object_class->destroy = pn_vis_destroy;
+
+  /* PnUserObject methods */
+  user_object_class->save_thyself = pn_vis_save_thyself;
+  user_object_class->load_thyself = pn_vis_load_thyself;
+}
+
+static void
+pn_vis_init (PnVis *vis, PnVisClass *class)
+{
+  /* Set a name for xml stuffs */
+  pn_user_object_set_name (PN_USER_OBJECT (vis), "Paranormal_Visualization");
+
+  /* Create a new image context */
+  vis->root_image = pn_image_new ();
+  pn_object_ref (PN_OBJECT (vis->root_image));
+  pn_object_sink (PN_OBJECT (vis->root_image));
+}
+
+static void
+pn_vis_destroy (PnObject *object)
+{
+  PnVis *vis = (PnVis *) object;
+
+  if (vis->root_actuator)
+    pn_object_unref (PN_OBJECT (vis->root_actuator));
+
+  if (vis->root_image)
+    pn_object_unref (PN_OBJECT (vis->root_image));
+}
+
+static void
+pn_vis_finalize (GObject *gobject)
+{
+  PnVis *vis;
+
+  vis = (PnVis *) gobject;
+}
+
+static void
+pn_vis_save_thyself (PnUserObject *user_object, xmlNodePtr node)
+{
+  PnVis *vis;
+  xmlNsPtr ns;
+  xmlNodePtr actuators_node, actuator_node;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_VIS (user_object));
+  g_return_if_fail (node != NULL);
+
+  vis = (PnVis *) user_object;
+
+  ns = xmlNewNs (node, PN_XML_NS_HREF, "pn");
+  xmlSetNs (node, ns);
+
+  actuators_node = xmlNewChild (node, NULL, "Actuators", NULL);
+  actuator_node = xmlNewChild (actuators_node, NULL, "BUG", NULL);
+  if (vis->root_actuator)
+    pn_user_object_save_thyself (PN_USER_OBJECT (vis->root_actuator), actuator_node);
+
+  if (parent_class->save_thyself)
+    parent_class->save_thyself (user_object, node);
+}
+
+static void
+pn_vis_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
+{
+  PnVis *vis;
+  xmlNodePtr actuators_node, actuator_node;
+  PnActuator *root_actuator;
+
+  g_return_if_fail (user_object != NULL);
+  g_return_if_fail (PN_IS_VIS (user_object));
+  g_return_if_fail (node != NULL);
+
+  vis = (PnVis *) user_object;
+
+  /* find the 'Actuators' node */
+  for (actuators_node = node->xmlChildrenNode; actuators_node; actuators_node = actuators_node->next)
+    if (g_strcasecmp (actuators_node->name, "Actuators") == 0)
+      break;
+  if (! actuators_node)
+    {
+      pn_error ("unable to load a PnVis from xml node \"%s\"", node->name);
+      return;
+    }
+      
+  /* get the root actuator's node */
+  actuator_node = actuators_node->xmlChildrenNode;
+  if (! actuator_node)
+    goto done;
+
+  /* Create a new actuator */
+  root_actuator = pn_actuator_factory_new_actuator_from_xml (actuator_node);
+  if (! root_actuator)
+    pn_error ("Unknown actuator \"%s\"", actuator_node->name);
+
+  pn_vis_set_root_actuator (vis, root_actuator);
+
+ done:
+  if (parent_class->load_thyself)
+    parent_class->load_thyself (user_object, node);
+}
+
+PnVis*
+pn_vis_new (guint image_width, guint image_height)
+{
+  PnVis *vis;
+
+  g_return_val_if_fail (image_width > 0, NULL);
+  g_return_val_if_fail (image_height > 0, NULL);
+
+  vis = (PnVis *) g_object_new (PN_TYPE_VIS, NULL);
+  pn_vis_set_image_size (vis, image_width, image_height);
+
+  return vis;
+}
+
+void
+pn_vis_set_root_actuator (PnVis *vis, PnActuator *actuator)
+{
+  g_return_if_fail (vis != NULL);
+  g_return_if_fail (PN_IS_VIS (vis));
+  g_return_if_fail (actuator != NULL);
+  g_return_if_fail (PN_IS_ACTUATOR (actuator));
+
+  if (vis->root_actuator)
+    pn_object_unref (PN_OBJECT (vis->root_actuator));
+
+  vis->root_actuator = actuator;
+
+  pn_object_ref (PN_OBJECT (actuator));
+  pn_object_sink (PN_OBJECT (actuator));
+  pn_user_object_set_owner (PN_USER_OBJECT (actuator), PN_USER_OBJECT (vis));
+
+  pn_actuator_prepare (actuator, vis->root_image);
+}
+
+PnActuator*
+pn_vis_get_root_actuator (PnVis *vis)
+{
+  g_return_val_if_fail (vis != NULL, NULL);
+  g_return_val_if_fail (PN_IS_VIS (vis), NULL);
+
+  return vis->root_actuator;
+}
+
+void
+pn_vis_set_image_size (PnVis *vis, guint width, guint height)
+{
+  g_return_if_fail (vis != NULL);
+  g_return_if_fail (PN_IS_VIS (vis));
+
+  pn_image_set_size (vis->root_image, width, height);
+
+  if (vis->root_actuator)
+    pn_actuator_prepare (vis->root_actuator, vis->root_image);
+}
+
+gboolean
+pn_vis_save_to_file (PnVis *vis, const gchar *fname)
+{
+  xmlDocPtr doc;
+
+  doc = xmlNewDoc ("1.0");
+
+  doc->xmlRootNode = xmlNewDocNode (doc, NULL, "BUG", NULL);
+
+  pn_user_object_save_thyself (PN_USER_OBJECT (vis), doc->xmlRootNode);
+
+  if ( xmlSaveFile (fname, doc) == -1)
+    {
+      xmlFreeDoc (doc);
+      return FALSE;
+    }
+
+  xmlFreeDoc (doc);
+  return TRUE;
+}
+
+gboolean
+pn_vis_load_from_file (PnVis *vis, const gchar *fname)
+{
+  xmlDocPtr doc;
+  xmlNodePtr root_node;
+  xmlNsPtr ns;
+
+  doc = xmlParseFile (fname);
+  if (! doc)
+    {
+      pn_error ("unable to parse file \"%s\"", fname);
+      return FALSE;
+    }
+
+  root_node = xmlDocGetRootElement (doc);
+  if (! root_node)
+    {
+      pn_error ("no root element for file \"%s\"", fname);
+      return FALSE;
+    }
+
+  ns = xmlSearchNsByHref (doc, root_node, PN_XML_NS_HREF);
+  if (! ns)
+    {
+      pn_error ("invalid file format: paranormal namespace not found");
+      return FALSE;
+    }
+
+  if (g_strcasecmp (root_node->name, pn_user_object_get_name (PN_USER_OBJECT (vis))))
+    {
+      pn_error ("invalid file format: this file does not contain a Paranormal visualization");
+      return FALSE;
+    }
+
+  pn_user_object_load_thyself (PN_USER_OBJECT (vis), root_node);
+
+  return TRUE;
+}
+
+PnImage*
+pn_vis_render (PnVis *vis, PnAudioData *audio_data)
+{
+  g_return_val_if_fail (vis != NULL, NULL);
+  g_return_val_if_fail (PN_IS_VIS (vis), NULL);
+  g_return_val_if_fail (audio_data != NULL, NULL);
+/*    g_return_val_if_fail (PN_IS_AUDIO_DATA (audio_data), NULL); */
+
+  if (vis->root_actuator)
+      pn_actuator_execute (vis->root_actuator,
+			   vis->root_image,
+			   audio_data);
+
+  return vis->root_image;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnvis.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,80 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_VIS_H__
+#define __PN_VIS_H__
+
+#include <glib.h>
+#include "pnuserobject.h"
+#include "pnactuator.h"
+#include "pnimage.h"
+#include "pnaudiodata.h"
+
+
+G_BEGIN_DECLS
+
+
+#define PN_TYPE_VIS              (pn_vis_get_type ())
+#define PN_VIS(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), PN_TYPE_VIS, PnVis))
+#define PN_VIS_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), PN_TYPE_VIS, PnVisClass))
+#define PN_IS_VIS(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PN_TYPE_VIS))
+#define PN_IS_VIS_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), PN_TYPE_VIS))
+#define PN_VIS_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PN_TYPE_VIS, PnVisClass))
+
+typedef struct _PnVis        PnVis;
+typedef struct _PnVisClass   PnVisClass;
+
+struct _PnVis
+{
+  PnUserObject parent;
+
+  PnActuator *root_actuator;
+  PnImage *root_image;
+};
+
+struct _PnVisClass
+{
+  PnUserObjectClass parent_class;
+};
+
+/* Creators */
+GType                 pn_vis_get_type                (void);
+PnVis                *pn_vis_new                     (guint image_width,
+						      guint image_height);
+
+/* Accessors */
+void                  pn_vis_set_root_actuator       (PnVis *vis,
+						      PnActuator *actuator);
+PnActuator           *pn_vis_get_root_actuator       (PnVis *vis);
+void                  pn_vis_set_image_size          (PnVis *vis,
+						      guint width,
+						      guint height);
+
+/* Actions */
+gboolean              pn_vis_save_to_file            (PnVis *vis,
+						      const gchar *fname);
+gboolean              pn_vis_load_from_file          (PnVis *vis,
+						      const gchar *fname);
+PnImage              *pn_vis_render                  (PnVis *vis,
+						      PnAudioData *audio_data);
+
+
+
+
+
+#endif /* __PN_VIS_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Visualization/paranormal/pn/pnxml.h	Sun Aug 06 01:53:29 2006 -0700
@@ -0,0 +1,33 @@
+/* Paranormal - A highly customizable audio visualization library
+ * Copyright (C) 2001  Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PN_XML_H__
+#define __PN_XML_H__
+
+#include <libxml/parser.h>
+
+/* compatibility w/ libxml1 */
+#ifndef xmlChildrenNode
+#define xmlChildrenNode childs
+#define xmlRootNode root
+#endif
+
+/* The namespace href */
+#define PN_XML_NS_HREF "http://paranormal.sf.net/pnvis/1.0/"
+
+#endif /* __PN_XML_H__ */