make swfdec_as_function_call() automatically do swfdec_as_context_run()
[swfdec.git] / swfdec / swfdec_interval.c
blobdd0c39036bf96cb07356d477bc12781623070f7b
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <stdlib.h>
25 #include <string.h>
27 #include "swfdec_interval.h"
28 #include "swfdec_as_context.h"
29 #include "swfdec_as_frame_internal.h"
30 #include "swfdec_as_function.h"
31 #include "swfdec_as_internal.h"
32 #include "swfdec_debug.h"
33 #include "swfdec_player_internal.h"
34 #include "swfdec_resource.h"
36 G_DEFINE_TYPE (SwfdecInterval, swfdec_interval, SWFDEC_TYPE_AS_OBJECT)
38 static void
39 swfdec_interval_mark (SwfdecGcObject *object)
41 guint i;
42 SwfdecInterval *interval = SWFDEC_INTERVAL (object);
44 swfdec_gc_object_mark (interval->object);
45 swfdec_gc_object_mark (interval->sandbox);
46 if (interval->fun_name)
47 swfdec_as_string_mark (interval->fun_name);
48 for (i = 0; i < interval->n_args; i++) {
49 swfdec_as_value_mark (&interval->args[i]);
52 SWFDEC_GC_OBJECT_CLASS (swfdec_interval_parent_class)->mark (object);
55 static void
56 swfdec_interval_dispose (GObject *object)
58 SwfdecInterval *interval = SWFDEC_INTERVAL (object);
60 if (interval->n_args) {
61 swfdec_as_context_unuse_mem (swfdec_gc_object_get_context (interval),
62 interval->n_args * sizeof (SwfdecAsValue));
63 g_free (interval->args);
64 interval->args = NULL;
65 interval->n_args = 0;
67 /* needed here when GC'ed by closing the player */
68 if (interval->timeout.callback != NULL) {
69 swfdec_player_remove_timeout (SWFDEC_PLAYER (swfdec_gc_object_get_context (object)), &interval->timeout);
70 interval->timeout.callback = NULL;
73 G_OBJECT_CLASS (swfdec_interval_parent_class)->dispose (object);
76 static void
77 swfdec_interval_class_init (SwfdecIntervalClass *klass)
79 GObjectClass *object_class = G_OBJECT_CLASS (klass);
80 SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
82 object_class->dispose = swfdec_interval_dispose;
84 gc_class->mark = swfdec_interval_mark;
87 static void
88 swfdec_interval_init (SwfdecInterval *array)
92 static void
93 swfdec_interval_trigger (SwfdecTimeout *timeout)
95 SwfdecAsValue ret;
96 SwfdecInterval *interval = SWFDEC_INTERVAL ((void *) (((guchar *) timeout)
97 - G_STRUCT_OFFSET (SwfdecInterval, timeout)));
98 SwfdecAsContext *context = swfdec_gc_object_get_context (interval);
99 SwfdecPlayer *player = SWFDEC_PLAYER (context);
101 if (interval->repeat) {
102 timeout->timestamp += SWFDEC_MSECS_TO_TICKS (interval->msecs);
103 swfdec_player_add_timeout (SWFDEC_PLAYER (context), timeout);
104 } else {
105 player->priv->intervals = g_list_remove (player->priv->intervals, interval);
106 interval->timeout.callback = NULL;
108 swfdec_sandbox_use (interval->sandbox);
109 if (interval->fun_name) {
110 swfdec_as_object_call (interval->object,
111 interval->fun_name, interval->n_args, interval->args, &ret);
112 } else {
113 swfdec_as_function_call (SWFDEC_AS_FUNCTION (interval->object), NULL,
114 interval->n_args, interval->args, &ret);
116 swfdec_sandbox_unuse (interval->sandbox);
119 static guint
120 swfdec_interval_new (SwfdecPlayer *player, guint msecs, gboolean repeat,
121 SwfdecAsObject *object, const char *fun_name,
122 guint n_args, const SwfdecAsValue *args)
124 SwfdecAsContext *context;
125 SwfdecInterval *interval;
127 context = SWFDEC_AS_CONTEXT (player);
128 if (n_args && !swfdec_as_context_try_use_mem (context, n_args * sizeof (SwfdecAsValue))) {
129 swfdec_as_context_abort (context,
130 "Too many arguments passed to setInterval/setTimeout");
131 return 0;
133 interval = g_object_new (SWFDEC_TYPE_INTERVAL, "context", context, NULL);
135 interval->id = ++player->priv->interval_id;
136 interval->sandbox = SWFDEC_SANDBOX (context->global);
137 interval->msecs = msecs;
138 interval->repeat = repeat;
139 interval->object = object;
140 interval->fun_name = fun_name;
141 interval->n_args = n_args;
142 interval->args = g_memdup (args, n_args * sizeof (SwfdecAsValue));
143 interval->timeout.timestamp = player->priv->time + SWFDEC_MSECS_TO_TICKS (interval->msecs);
144 interval->timeout.callback = swfdec_interval_trigger;
145 swfdec_player_add_timeout (player, &interval->timeout);
147 player->priv->intervals =
148 g_list_prepend (player->priv->intervals, interval);
150 return interval->id;
153 guint
154 swfdec_interval_new_function (SwfdecPlayer *player, guint msecs, gboolean repeat,
155 SwfdecAsFunction *fun, guint n_args, const SwfdecAsValue *args)
157 g_return_val_if_fail (SWFDEC_IS_PLAYER (player), 0);
158 g_return_val_if_fail (msecs > 0, 0);
159 g_return_val_if_fail (SWFDEC_IS_AS_FUNCTION (fun), 0);
160 g_return_val_if_fail (n_args == 0 || args != NULL, 0);
162 return swfdec_interval_new (player, msecs, repeat, SWFDEC_AS_OBJECT (fun), NULL, n_args, args);
165 guint
166 swfdec_interval_new_object (SwfdecPlayer *player, guint msecs, gboolean repeat,
167 SwfdecAsObject *thisp, const char *fun_name,
168 guint n_args, const SwfdecAsValue *args)
170 g_return_val_if_fail (SWFDEC_IS_PLAYER (player), 0);
171 g_return_val_if_fail (msecs > 0, 0);
172 g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (thisp), 0);
173 g_return_val_if_fail (fun_name != NULL, 0);
174 g_return_val_if_fail (n_args == 0 || args != NULL, 0);
176 return swfdec_interval_new (player, msecs, repeat, thisp, fun_name, n_args, args);
179 void
180 swfdec_interval_remove (SwfdecPlayer *player, guint id)
182 GList *walk;
184 g_return_if_fail (SWFDEC_IS_PLAYER (player));
186 for (walk = player->priv->intervals; walk; walk = walk->next) {
187 SwfdecInterval *interval = walk->data;
188 if (interval->id != id)
189 continue;
191 player->priv->intervals = g_list_delete_link (player->priv->intervals, walk);
192 swfdec_player_remove_timeout (player, &interval->timeout);
193 interval->timeout.callback = NULL;
194 return;