1507
|
1 /* Paranormal - A highly customizable audio visualization library
|
|
2 * Copyright (C) 2001 Jamie Gennis <jgennis@mindspring.com>
|
|
3 *
|
|
4 * This library is free software; you can redistribute it and/or
|
|
5 * modify it under the terms of the GNU Library General Public
|
|
6 * License as published by the Free Software Foundation; either
|
|
7 * version 2 of the License, or (at your option) any later version.
|
|
8 *
|
|
9 * This library is distributed in the hope that it will be useful,
|
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12 * Library General Public License for more details.
|
|
13 *
|
|
14 * You should have received a copy of the GNU Library General Public
|
|
15 * License along with this library; if not, write to the Free
|
|
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
17 */
|
|
18
|
|
19 #include <config.h>
|
|
20
|
|
21 #include <glib.h>
|
|
22 #include "pnactuator.h"
|
|
23 #include "pnerror.h"
|
|
24
|
|
25 static void pn_actuator_class_init (PnActuatorClass *class);
|
|
26 static void pn_actuator_init (PnActuator *actuator,
|
|
27 PnActuatorClass *class);
|
|
28
|
|
29 /* GObject signals */
|
|
30 static void pn_actuator_finalize (GObject *gobject);
|
|
31
|
|
32 /* PnObject signals */
|
|
33 static void pn_actuator_destroy (PnObject *object);
|
|
34
|
|
35 /* PnUserObject methods */
|
|
36 static void pn_actuator_save_thyself (PnUserObject *user_object,
|
|
37 xmlNodePtr node);
|
|
38 static void pn_actuator_load_thyself (PnUserObject *user_object,
|
|
39 xmlNodePtr node);
|
|
40
|
|
41 static PnUserObjectClass *parent_class = NULL;
|
|
42
|
|
43 GType
|
|
44 pn_actuator_get_type (void)
|
|
45 {
|
|
46 static GType actuator_type = 0;
|
|
47
|
|
48 if (! actuator_type)
|
|
49 {
|
|
50 static const GTypeInfo actuator_info =
|
|
51 {
|
|
52 sizeof (PnActuatorClass),
|
|
53 NULL, /* base_init */
|
|
54 NULL, /* base_finalize */
|
|
55 (GClassInitFunc) pn_actuator_class_init,
|
|
56 NULL, /* class_finalize */
|
|
57 NULL, /* class_data */
|
|
58 sizeof (PnActuator),
|
|
59 0, /* n_preallocs */
|
|
60 (GInstanceInitFunc) pn_actuator_init
|
|
61 };
|
|
62
|
|
63 /* FIXME: should this be dynamic? */
|
|
64 actuator_type = g_type_register_static (PN_TYPE_USER_OBJECT,
|
|
65 "PnActuator",
|
|
66 &actuator_info,
|
|
67 G_TYPE_FLAG_ABSTRACT);
|
|
68 }
|
|
69 return actuator_type;
|
|
70 }
|
|
71
|
|
72 static void
|
|
73 pn_actuator_class_init (PnActuatorClass *class)
|
|
74 {
|
|
75 GObjectClass *gobject_class;
|
|
76 PnObjectClass *object_class;
|
|
77 PnUserObjectClass *user_object_class;
|
|
78
|
|
79
|
|
80 parent_class = g_type_class_peek_parent (class);
|
|
81
|
|
82 gobject_class = (GObjectClass *) class;
|
|
83 object_class = (PnObjectClass *) class;
|
|
84 user_object_class = (PnUserObjectClass *) class;
|
|
85
|
|
86 /* GObject signals */
|
|
87 gobject_class->finalize = pn_actuator_finalize;
|
|
88
|
|
89 /* PnObject signals */
|
|
90 object_class->destroy = pn_actuator_destroy;
|
|
91
|
|
92 /* PnUserObject methods */
|
|
93 user_object_class->save_thyself = pn_actuator_save_thyself;
|
|
94 user_object_class->load_thyself = pn_actuator_load_thyself;
|
|
95 }
|
|
96
|
|
97 static void
|
|
98 pn_actuator_init (PnActuator *actuator, PnActuatorClass *class)
|
|
99 {
|
|
100 actuator->options = g_array_new (FALSE, FALSE, sizeof (PnOption *));
|
|
101 }
|
|
102
|
|
103 static void
|
|
104 pn_actuator_destroy (PnObject *object)
|
|
105 {
|
|
106 PnActuator *actuator = (PnActuator *) object;
|
|
107 gint i;
|
|
108
|
|
109 for (i=0; i < actuator->options->len; i++)
|
|
110 pn_object_unref (g_array_index (actuator->options, PnObject *, i));
|
|
111 }
|
|
112
|
|
113 static void
|
|
114 pn_actuator_finalize (GObject *gobject)
|
|
115 {
|
|
116 PnActuator *actuator = (PnActuator *) gobject;
|
|
117
|
|
118 g_array_free (actuator->options, FALSE);
|
|
119
|
|
120 if (G_OBJECT_CLASS (parent_class)->finalize)
|
|
121 G_OBJECT_CLASS (parent_class)->finalize (gobject);
|
|
122 }
|
|
123
|
|
124 static void
|
|
125 pn_actuator_save_thyself (PnUserObject *user_object, xmlNodePtr node)
|
|
126 {
|
|
127 PnActuator *actuator;
|
|
128 gint i;
|
|
129 xmlNodePtr options_node, option_node;
|
|
130 PnOption *option;
|
|
131
|
|
132 g_return_if_fail (user_object != NULL);
|
|
133 g_return_if_fail (PN_IS_ACTUATOR (user_object));
|
|
134 g_return_if_fail (node != NULL);
|
|
135
|
|
136 actuator = (PnActuator *) user_object;
|
|
137
|
|
138 options_node = xmlNewChild (node, NULL, "Options", NULL);
|
|
139
|
|
140 /* Save all the options */
|
|
141 for (i=0; i < actuator->options->len; i++)
|
|
142 {
|
|
143 option = g_array_index (actuator->options, PnOption *, i);
|
|
144 option_node = xmlNewChild (options_node, NULL, "BUG", NULL);
|
|
145 pn_user_object_save_thyself (PN_USER_OBJECT (option), option_node);
|
|
146 }
|
|
147
|
|
148 if (parent_class->save_thyself)
|
|
149 parent_class->save_thyself (user_object, node);
|
|
150 }
|
|
151
|
|
152 static void
|
|
153 pn_actuator_load_thyself (PnUserObject *user_object, const xmlNodePtr node)
|
|
154 {
|
|
155 PnActuator *actuator;
|
|
156 xmlNodePtr options_node, option_node;
|
|
157 PnOption *option;
|
|
158
|
|
159 g_return_if_fail (user_object != NULL);
|
|
160 g_return_if_fail (PN_IS_ACTUATOR (user_object));
|
|
161 g_return_if_fail (node != NULL);
|
|
162
|
|
163 actuator = (PnActuator *) user_object;
|
|
164
|
|
165 /* FIXME: should these 'xmlChildrenNode' be 'xmlRootNode'? */
|
|
166
|
|
167 /* find the 'options' node */
|
|
168 for (options_node = node->xmlChildrenNode; options_node; options_node = options_node->next)
|
|
169 if (g_strcasecmp (options_node->name, "Options") == 0)
|
|
170 break;
|
|
171
|
|
172 /* load each of the options */
|
|
173 if (options_node)
|
|
174 {
|
|
175 for (option_node = options_node->xmlChildrenNode; option_node; option_node = option_node->next)
|
|
176 {
|
|
177 option = pn_actuator_get_option_by_name (actuator, option_node->name);
|
|
178 if (option)
|
|
179 pn_user_object_load_thyself (PN_USER_OBJECT (option), option_node);
|
|
180 else
|
|
181 pn_error ("unknown actuator option ecountered in actuator \"%s\": %s",
|
|
182 node->name,
|
|
183 option_node->name);
|
|
184 }
|
|
185 }
|
|
186
|
|
187 if (parent_class->load_thyself)
|
|
188 parent_class->load_thyself (user_object, node);
|
|
189 }
|
|
190
|
|
191 /**
|
|
192 * pn_actuator_add_option
|
|
193 * @actuator: a #PnActuator
|
|
194 * @option: the #PnOption to add
|
|
195 *
|
|
196 * Adds a #PnOption to the actuator.
|
|
197 */
|
|
198 void
|
|
199 pn_actuator_add_option (PnActuator *actuator, PnOption *option)
|
|
200 {
|
|
201 g_return_if_fail (actuator != NULL);
|
|
202 g_return_if_fail (PN_IS_ACTUATOR (actuator));
|
|
203 g_return_if_fail (option != NULL);
|
|
204 g_return_if_fail (PN_IS_OPTION (option));
|
|
205 g_return_if_fail (! pn_actuator_get_option_by_name (actuator, PN_USER_OBJECT_NAME (option)));
|
|
206
|
|
207 g_array_append_val (actuator->options, option);
|
|
208 pn_object_ref (PN_OBJECT (option));
|
|
209 pn_object_sink (PN_OBJECT (option));
|
|
210 pn_user_object_set_owner (PN_USER_OBJECT (option), PN_USER_OBJECT (actuator));
|
|
211 }
|
|
212
|
|
213 /**
|
|
214 * pn_actuator_get_option_by_index
|
|
215 * @actuator: a #PnActuator
|
|
216 * @index: the index of the option to retrieve
|
|
217 *
|
|
218 * Retrieves a #PnOption associated with the actuator based on
|
|
219 * the index of the option. Indices start at 0 and are determined
|
|
220 * by the order in which the options were added.
|
|
221 *
|
|
222 * Returns: The #PnOption at index @index
|
|
223 */
|
|
224 PnOption*
|
|
225 pn_actuator_get_option_by_index (PnActuator *actuator, guint index)
|
|
226 {
|
|
227 g_return_val_if_fail (actuator != NULL, NULL);
|
|
228 g_return_val_if_fail (PN_IS_ACTUATOR (actuator), NULL);
|
|
229 g_return_val_if_fail (index < actuator->options->len, NULL);
|
|
230
|
|
231 return g_array_index (actuator->options, PnOption *, index);
|
|
232 }
|
|
233
|
|
234 /**
|
|
235 * pn_actuator_get_option_by_name
|
|
236 * @actuator: a #PnActuator
|
|
237 * @name: the name of the option to retrieve
|
|
238 *
|
|
239 * Retrieves the first #PnOption associated with the actuator
|
|
240 * based on the name of the option.
|
|
241 *
|
|
242 * Returns: The first #PnOption with the name @name
|
|
243 */
|
|
244 PnOption*
|
|
245 pn_actuator_get_option_by_name (PnActuator *actuator, const gchar *name)
|
|
246 {
|
|
247 gint i;
|
|
248 PnOption *option;
|
|
249
|
|
250 g_return_val_if_fail (actuator != NULL, NULL);
|
|
251 g_return_val_if_fail (PN_IS_ACTUATOR (actuator), NULL);
|
|
252 g_return_val_if_fail (name != NULL, NULL);
|
|
253
|
|
254 for (i=0; i < actuator->options->len; i++)
|
|
255 {
|
|
256 option = g_array_index (actuator->options, PnOption *, i);
|
|
257 if (g_strcasecmp (pn_user_object_get_name (PN_USER_OBJECT (option)), name) == 0)
|
|
258 return option;
|
|
259 }
|
|
260
|
|
261 return NULL;
|
|
262 }
|
|
263
|
|
264 /**
|
|
265 * pn_actuator_prepare
|
|
266 * @actuator: a #PnActuator
|
|
267 * @image: the #PnImage for which the actuator should prepare
|
|
268 *
|
|
269 * Prepares an actuator to act upon a given #PnImage.
|
|
270 */
|
|
271 void
|
|
272 pn_actuator_prepare (PnActuator *actuator, PnImage *image)
|
|
273 {
|
|
274 PnActuatorClass *class;
|
|
275
|
|
276 g_return_if_fail (actuator != NULL);
|
|
277 g_return_if_fail (PN_IS_ACTUATOR (actuator));
|
|
278 g_return_if_fail (image != NULL);
|
|
279 g_return_if_fail (PN_IS_IMAGE (image));
|
|
280
|
|
281 class = PN_ACTUATOR_GET_CLASS (actuator);
|
|
282
|
|
283 if (class->prepare)
|
|
284 class->prepare (actuator, image);
|
|
285 }
|
|
286
|
|
287 /**
|
|
288 * pn_actuator_execute
|
|
289 * @actuator: a #PnActuator
|
|
290 * @image: the #PnImage to act upon
|
|
291 * @audio_data: the #PnAudioData to use when basing effects on sound
|
|
292 *
|
|
293 * Causes the actuator to perform its function on @image. The pn_actuator_prepare()
|
|
294 * *MUST* have previously been called with the same @actuator and @image arguments.
|
|
295 */
|
|
296 void
|
|
297 pn_actuator_execute (PnActuator *actuator, PnImage *image, PnAudioData *audio_data)
|
|
298 {
|
|
299 PnActuatorClass *class;
|
|
300
|
|
301 g_return_if_fail (actuator != NULL);
|
|
302 g_return_if_fail (PN_IS_ACTUATOR (actuator));
|
|
303 g_return_if_fail (image != NULL);
|
|
304 g_return_if_fail (PN_IS_IMAGE (image));
|
|
305 g_return_if_fail (audio_data != NULL);
|
|
306 /* g_return_if_fail (PN_IS_AUDIO_DATA (audio_data)); */
|
|
307
|
|
308 class = PN_ACTUATOR_GET_CLASS (actuator);
|
|
309
|
|
310 if (class->execute)
|
|
311 class->execute (actuator, image, audio_data);
|
|
312 }
|