comparison src/paranormal-ng/containers.c @ 2078:1fa3c8cd366a

paranormal-ng: a GL visualiser. lots to do, most stuff won't work, but hey, this will do cool stuff too soon
author William Pitcock <nenolod@atheme.org>
date Mon, 15 Oct 2007 06:20:13 -0500
parents
children f1b6f1b2cdb3
comparison
equal deleted inserted replaced
2077:e5b639ab62b0 2078:1fa3c8cd366a
1 /*
2 * paranormal: iterated pipeline-driven visualization plugin
3 * Copyright (c) 2006, 2007 William Pitcock <nenolod@dereferenced.org>
4 * Portions copyright (c) 2001 Jamie Gennis <jgennis@mindspring.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; under version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <config.h>
21
22 #include <stdio.h>
23
24 #include <glib.h>
25
26 #include "actuators.h"
27 #include "paranormal.h"
28
29 /* **************** all containers **************** */
30
31 /* Add a actuator to a container (end of list) */
32 void
33 container_add_actuator (struct pn_actuator *container, struct pn_actuator *a)
34 {
35 g_assert (container->desc->flags & ACTUATOR_FLAG_CONTAINER);
36 g_assert (a);
37
38 *((GSList **)container->data) =
39 g_slist_append (*(GSList **)container->data, a);
40 }
41
42 void
43 container_remove_actuator (struct pn_actuator *container, struct pn_actuator *a)
44 {
45 g_assert (container->desc->flags & ACTUATOR_FLAG_CONTAINER);
46 g_assert (a);
47
48 *((GSList **)container->data) =
49 g_slist_remove (*(GSList **)container->data, a);
50 }
51
52 /* clear the containee list */
53 void
54 container_unlink_actuators (struct pn_actuator *container)
55 {
56 g_assert (container->desc->flags & ACTUATOR_FLAG_CONTAINER);
57
58 g_slist_free (*(GSList **)container->data);
59 *(GSList **)container->data = NULL;
60 }
61
62 /* this does NOT free data */
63 static void
64 container_cleanup (GSList** data)
65 {
66 GSList *child;
67
68 for (child = *data; child; child = child->next)
69 destroy_actuator ((struct pn_actuator *) child->data);
70
71 g_slist_free (*data);
72 }
73
74 /* **************** container_simple **************** */
75 static void
76 container_simple_init (GSList ***data)
77 {
78 *data = g_new0 (GSList *, 1);
79 }
80
81 static void
82 container_simple_cleanup (GSList **data)
83 {
84 container_cleanup (data);
85 g_free (data);
86 }
87
88 static void
89 container_simple_exec (const struct pn_actuator_option *opts,
90 GSList **data)
91 {
92 GSList *child;
93
94 for (child = *data; child; child = child->next)
95 exec_actuator ((struct pn_actuator *) child->data);
96 }
97
98 struct pn_actuator_desc builtin_container_simple =
99 {
100 "container_simple",
101 "Simple Container",
102 "A simple (unconditional) container\n\n"
103 "This is usually used as the root actuator of a list",
104 ACTUATOR_FLAG_CONTAINER, NULL,
105 PN_ACTUATOR_INIT_FUNC (container_simple_init),
106 PN_ACTUATOR_CLEANUP_FUNC (container_simple_cleanup),
107 PN_ACTUATOR_EXEC_FUNC (container_simple_exec)
108 };
109
110 /* **************** container_once **************** */
111 struct container_once_data
112 {
113 GSList *children; /* This MUST be first! */
114
115 gboolean done;
116 };
117
118 static void
119 container_once_init (struct container_once_data **data)
120 {
121 *data = g_new0 (struct container_once_data, 1);
122 }
123
124 static void
125 container_once_cleanup (GSList **data)
126 {
127 container_cleanup (data);
128 g_free (data);
129 }
130
131 static void
132 container_once_exec (const struct pn_actuator_option *opts,
133 struct container_once_data *data)
134 {
135 if (! data->done)
136 {
137 GSList *child;
138
139 for (child = data->children; child; child = child->next)
140 exec_actuator ((struct pn_actuator *) child->data);
141
142 data->done = TRUE;
143 }
144 }
145
146 struct pn_actuator_desc builtin_container_once =
147 {
148 "container_once",
149 "Initialization Container",
150 "A container whose contents get executed exactly once.\n\n"
151 "This is often used to set initial graphics states such as the\n"
152 "pixel depth, or to display some text (such as credits)",
153 ACTUATOR_FLAG_CONTAINER, NULL,
154 PN_ACTUATOR_INIT_FUNC (container_once_init),
155 PN_ACTUATOR_CLEANUP_FUNC (container_once_cleanup),
156 PN_ACTUATOR_EXEC_FUNC (container_once_exec)
157 };
158
159 /* **************** container_cycle ***************** */
160 static struct pn_actuator_option_desc container_cycle_opts[] =
161 {
162 { "change_interval", "The number of seconds between changing the "
163 "child to be executed", OPT_TYPE_INT, { ival: 20 } },
164 { "beat", "Whether or not the change should only occur on a beat",
165 OPT_TYPE_BOOLEAN, { bval: TRUE } },
166 { NULL }
167 };
168
169 struct container_cycle_data
170 {
171 GSList *children;
172 GSList *current;
173 int last_change;
174 };
175
176 static void
177 container_cycle_init (gpointer *data)
178 {
179 *data = g_new0 (struct container_cycle_data, 1);
180 }
181
182 static void
183 container_cycle_cleanup (gpointer data)
184 {
185 container_cleanup (data);
186 g_free (data);
187 }
188
189 static void
190 container_cycle_exec (const struct pn_actuator_option *opts,
191 gpointer data)
192 {
193 struct container_cycle_data *cdata = (struct container_cycle_data*)data;
194 int now;
195
196 /*
197 * Change branch if all of the requirements are met for the branch to change.
198 */
199 if ((opts[1].val.bval == TRUE && pn_new_beat != FALSE) || opts[1].val.bval == FALSE)
200 {
201 now = SDL_GetTicks();
202
203 if (now - cdata->last_change
204 > opts[0].val.ival * 1000)
205 {
206 cdata->last_change = now;
207
208 /* FIXME: add randomization support */
209 if (cdata->current)
210 cdata->current = cdata->current->next;
211 }
212 }
213
214 if (! cdata->current)
215 cdata->current = cdata->children;
216
217 if (cdata->current)
218 exec_actuator ((struct pn_actuator*)cdata->current->data);
219 }
220
221 struct pn_actuator_desc builtin_container_cycle =
222 {
223 "container_cycle",
224 "Branched-execution Container",
225 "A container that alternates which of its children is executed; it "
226 "can either change on an interval, or only on a beat.",
227 ACTUATOR_FLAG_CONTAINER, container_cycle_opts,
228 container_cycle_init, container_cycle_cleanup, container_cycle_exec
229 };
230
231 /* **************** container_onbeat **************** */
232 static void
233 container_onbeat_init (GSList ***data)
234 {
235 *data = g_new0 (GSList *, 1);
236 }
237
238 static void
239 container_onbeat_cleanup (GSList **data)
240 {
241 container_cleanup (data);
242 g_free (data);
243 }
244
245 static void
246 container_onbeat_exec (const struct pn_actuator_option *opts,
247 GSList **data)
248 {
249 GSList *child;
250
251 if (pn_new_beat == TRUE)
252 {
253 for (child = *data; child; child = child->next)
254 exec_actuator ((struct pn_actuator *) child->data);
255 }
256 }
257
258 struct pn_actuator_desc builtin_container_onbeat =
259 {
260 "container_onbeat",
261 "OnBeat Container",
262 "A simple container which only triggers on a beat.",
263 ACTUATOR_FLAG_CONTAINER, NULL,
264 PN_ACTUATOR_INIT_FUNC (container_onbeat_init),
265 PN_ACTUATOR_CLEANUP_FUNC (container_onbeat_cleanup),
266 PN_ACTUATOR_EXEC_FUNC (container_onbeat_exec)
267 };