diff Plugins/Visualization/paranormal/pn/pnvis.c @ 1507:0c5fdcf3f947 trunk

[svn] - incomplete stuff
author nenolod
date Sun, 06 Aug 2006 01:53:29 -0700
parents
children 98a9c54459f0
line wrap: on
line diff
--- /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;
+}