Mercurial > audlegacy
diff Plugins/Visualization/paranormal/pn/pncontainer.c @ 1507:0c5fdcf3f947 trunk
[svn] - incomplete stuff
author | nenolod |
---|---|
date | Sun, 06 Aug 2006 01:53:29 -0700 |
parents | |
children | 8b57cc165216 |
line wrap: on
line diff
--- /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); +}