add blend mode tests
[swfdec.git] / swfdec / swfdec_player_as.c
blob8051be31867b7e680e6d21bc0b065cca99b5ba0e
1 /* Swfdec
2 * Copyright (C) 2006-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 /* NB: include this first, it redefines SWFDEC_AS_NATIVE */
25 #include "swfdec_asnative.h"
27 #include "swfdec_player_internal.h"
28 #include "swfdec_as_function.h"
29 #include "swfdec_as_internal.h"
30 #include "swfdec_as_native_function.h"
31 #include "swfdec_as_object.h"
32 #include "swfdec_as_strings.h"
33 #include "swfdec_debug.h"
34 #include "swfdec_internal.h"
35 #include "swfdec_interval.h"
36 #include "swfdec_as_frame_internal.h"
38 /*** INTERVALS ***/
40 static void
41 swfdec_player_do_set_interval (gboolean repeat, SwfdecAsContext *cx, guint argc,
42 SwfdecAsValue *argv, SwfdecAsValue *rval)
44 SwfdecPlayer *player = SWFDEC_PLAYER (cx);
45 SwfdecAsObject *object;
46 guint id, msecs;
47 #define MIN_INTERVAL_TIME 10
49 if (argc < 2) {
50 SWFDEC_WARNING ("setInterval needs at least 2 arguments");
51 return;
54 if (!SWFDEC_AS_VALUE_IS_COMPOSITE (argv[0]) ||
55 (object = SWFDEC_AS_VALUE_GET_COMPOSITE (argv[0])) == NULL) {
56 SWFDEC_WARNING ("first argument to setInterval is not an object");
57 return;
59 if (SWFDEC_IS_AS_FUNCTION (object->relay)) {
60 msecs = swfdec_as_value_to_integer (cx, argv[1]);
61 if (msecs < MIN_INTERVAL_TIME) {
62 SWFDEC_INFO ("interval duration is %u, making it %u msecs", msecs, MIN_INTERVAL_TIME);
63 msecs = MIN_INTERVAL_TIME;
65 id = swfdec_interval_new_function (player, msecs, repeat,
66 SWFDEC_AS_FUNCTION (object->relay), argc - 2, &argv[2]);
67 } else {
68 const char *name;
69 if (argc < 3) {
70 SWFDEC_WARNING ("setInterval needs 3 arguments when not called with function");
71 return;
73 name = swfdec_as_value_to_string (cx, argv[1]);
74 msecs = swfdec_as_value_to_integer (cx, argv[2]);
75 if (msecs < MIN_INTERVAL_TIME) {
76 SWFDEC_INFO ("interval duration is %u, making it %u msecs", msecs, MIN_INTERVAL_TIME);
77 msecs = MIN_INTERVAL_TIME;
79 id = swfdec_interval_new_object (player, msecs, repeat, &argv[0], name, argc - 3, &argv[3]);
81 *rval = swfdec_as_value_from_integer (cx, id);
84 SWFDEC_AS_NATIVE (2, 0, swfdec_player_ASnew)
85 void
86 swfdec_player_ASnew (SwfdecAsContext *cx, SwfdecAsObject *obj,
87 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
89 g_return_if_fail (cx->frame->next != NULL);
91 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, cx->frame->next->construct);
94 SWFDEC_AS_NATIVE (250, 0, swfdec_player_setInterval)
95 void
96 swfdec_player_setInterval (SwfdecAsContext *cx, SwfdecAsObject *obj,
97 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
99 swfdec_player_do_set_interval (TRUE, cx, argc, argv, rval);
102 SWFDEC_AS_NATIVE (250, 2, swfdec_player_setTimeout)
103 void
104 swfdec_player_setTimeout (SwfdecAsContext *cx, SwfdecAsObject *obj,
105 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
107 swfdec_player_do_set_interval (FALSE, cx, argc, argv, rval);
110 SWFDEC_AS_NATIVE (250, 1, swfdec_player_clearInterval)
111 void
112 swfdec_player_clearInterval (SwfdecAsContext *cx, SwfdecAsObject *object,
113 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
115 SwfdecPlayer *player = SWFDEC_PLAYER (cx);
116 guint id;
118 SWFDEC_AS_CHECK (0, NULL, "i", &id);
120 swfdec_interval_remove (player, id);
123 /*** VARIOUS ***/
125 SWFDEC_AS_NATIVE (100, 4, swfdec_player_trace)
126 void
127 swfdec_player_trace (SwfdecAsContext *cx, SwfdecAsObject *obj,
128 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
130 SWFDEC_FIXME ("Is _global.trace supposed to do something?");
133 SWFDEC_AS_NATIVE (9, 0, swfdec_player_updateAfterEvent)
134 void
135 swfdec_player_updateAfterEvent (SwfdecAsContext *cx, SwfdecAsObject *obj,
136 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
138 SWFDEC_STUB ("updateAfterEvent");
141 SWFDEC_AS_NATIVE (1021, 1, swfdec_player_showRedrawRegions)
142 void
143 swfdec_player_showRedrawRegions (SwfdecAsContext *cx, SwfdecAsObject *obj,
144 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
146 SWFDEC_STUB ("showRedrawRegions");
149 static void
150 swfdec_player_enableDebugConsole (SwfdecAsContext *cx, SwfdecAsObject *obj,
151 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
153 SWFDEC_STUB ("enableDebugConsole");
156 static void
157 swfdec_player_do_nothing (SwfdecAsContext *cx, SwfdecAsObject *object,
158 guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval)
162 static SwfdecAsFunction *
163 swfdec_get_asnative (SwfdecAsContext *cx, guint x, guint y)
165 gboolean x_exists;
166 guint i;
168 x_exists = FALSE;
169 for (i = 0; native_funcs[i].func != NULL; i++) {
170 if (native_funcs[i].x == x)
171 x_exists = TRUE;
172 if (native_funcs[i].x == x && native_funcs[i].y == y) {
173 SwfdecAsFunction *fun = swfdec_as_native_function_new (cx, native_funcs[i].name,
174 native_funcs[i].func);
175 return fun;
178 SWFDEC_WARNING ("no ASnative (%u, %u)", x, y);
179 if (x_exists) {
180 SwfdecAsFunction *func;
181 char *name = g_strdup_printf ("ASnative (%u, %u)", x, y);
182 func = swfdec_as_native_function_new (cx, name, swfdec_player_do_nothing);
183 g_free (name);
184 return func;
185 } else {
186 return NULL;
190 // same as ASnative, but also sets prototype
191 static void
192 swfdec_player_ASconstructor (SwfdecAsContext *cx, SwfdecAsObject *object,
193 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
195 SwfdecAsValue val;
196 SwfdecAsObject *proto, *func_object;
197 SwfdecAsFunction *func;
198 guint x, y;
200 SWFDEC_AS_CHECK (0, NULL, "ii", &x, &y);
202 func = swfdec_get_asnative (cx, x, y);
203 if (func) {
204 proto = swfdec_as_object_new (cx, SWFDEC_AS_STR_Object, NULL);
205 func_object = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (func));
207 SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
208 swfdec_as_object_set_variable_and_flags (func_object,
209 SWFDEC_AS_STR_prototype, &val,
210 SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
212 SWFDEC_AS_VALUE_SET_OBJECT (&val, func_object);
213 swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR_constructor,
214 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
216 SWFDEC_AS_VALUE_SET_OBJECT (rval, func_object);
220 static void
221 swfdec_player_ASnative (SwfdecAsContext *cx, SwfdecAsObject *object,
222 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
224 SwfdecAsFunction *func;
225 guint x, y;
227 SWFDEC_AS_CHECK (0, NULL, "ii", &x, &y);
229 func = swfdec_get_asnative (cx, x, y);
230 if (func) {
231 SWFDEC_AS_VALUE_SET_OBJECT (rval, swfdec_as_relay_get_as_object SWFDEC_AS_RELAY (func));
235 SWFDEC_AS_NATIVE (4, 0, ASSetNative)
236 void
237 ASSetNative (SwfdecAsContext *cx, SwfdecAsObject *object,
238 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
240 SwfdecAsFunction *function;
241 SwfdecAsObject *target;
242 SwfdecAsValue val;
243 SwfdecAsVariableFlag flags;
244 const char *s;
245 char **names;
246 guint i, x, y;
248 SWFDEC_AS_CHECK (0, NULL, "ois", &target, &x, &s);
250 if (argc > 3)
251 y = swfdec_as_value_to_integer (cx, argv[3]);
252 else
253 y = 0;
254 names = g_strsplit (s, ",", -1);
255 for (i = 0; names[i]; i++) {
256 s = names[i];
257 flags = 0;
258 if (s[0] == '6') {
259 flags |= SWFDEC_AS_VARIABLE_VERSION_6_UP;
260 s++;
261 } else if (s[0] == '7') {
262 flags |= SWFDEC_AS_VARIABLE_VERSION_7_UP;
263 s++;
264 } else if (s[0] == '8') {
265 flags |= SWFDEC_AS_VARIABLE_VERSION_8_UP;
266 s++;
267 } else if (s[0] == '9') {
268 flags |= SWFDEC_AS_VARIABLE_VERSION_9_UP;
269 s++;
271 function = swfdec_get_asnative (cx, x, y);
272 if (function == NULL)
273 break;
274 SWFDEC_AS_VALUE_SET_OBJECT (&val, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (function)));
275 swfdec_as_object_set_variable_and_flags (target,
276 swfdec_as_context_get_string (cx, s), &val, flags);
277 y++;
279 g_strfreev (names);
282 SWFDEC_AS_NATIVE (4, 1, ASSetNativeAccessor)
283 void
284 ASSetNativeAccessor (SwfdecAsContext *cx, SwfdecAsObject *object,
285 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
287 SwfdecAsFunction *get, *set;
288 SwfdecAsObject *target;
289 SwfdecAsVariableFlag flags;
290 const char *s;
291 char **names;
292 guint i, x, y = 0;
294 SWFDEC_AS_CHECK (0, NULL, "ois|i", &target, &x, &s, &y);
296 names = g_strsplit (s, ",", -1);
297 for (i = 0; names[i]; i++) {
298 s = names[i];
299 flags = 0;
300 if (s[0] == '6') {
301 flags |= SWFDEC_AS_VARIABLE_VERSION_6_UP;
302 s++;
303 } else if (s[0] == '7') {
304 flags |= SWFDEC_AS_VARIABLE_VERSION_7_UP;
305 s++;
306 } else if (s[0] == '8') {
307 flags |= SWFDEC_AS_VARIABLE_VERSION_8_UP;
308 s++;
309 } else if (s[0] == '9') {
310 flags |= SWFDEC_AS_VARIABLE_VERSION_9_UP;
311 s++;
313 get = swfdec_get_asnative (cx, x, y++);
314 set = swfdec_get_asnative (cx, x, y++);
315 if (get == NULL) {
316 SWFDEC_ERROR ("no getter for %s", s);
317 break;
319 swfdec_as_object_add_variable (target, swfdec_as_context_get_string (cx, s),
320 get, set, flags);
322 g_strfreev (names);
325 SWFDEC_AS_NATIVE (101, 8, swfdec_player_object_registerClass)
326 void
327 swfdec_player_object_registerClass (SwfdecAsContext *cx, SwfdecAsObject *object,
328 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
330 const char *name;
332 SWFDEC_AS_CHECK (0, NULL, "s", &name);
334 if (argc < 2 || !SWFDEC_AS_VALUE_IS_OBJECT (argv[1])) {
335 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
336 return;
339 swfdec_player_set_export_class (SWFDEC_PLAYER (cx), name,
340 SWFDEC_AS_VALUE_GET_OBJECT (argv[1]));
341 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);
344 /* This is ran at the beginning of swfdec_as_context_startup.
345 * Yes, this is a hack */
346 void
347 swfdec_player_preinit_global (SwfdecAsContext *context)
349 SwfdecAsObject *o;
350 SwfdecAsFunction *f;
351 SwfdecAsValue val;
353 f = swfdec_as_native_function_new_bare (context,
354 SWFDEC_AS_STR_ASnative, swfdec_player_ASnative);
355 o = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (f));
356 SWFDEC_AS_VALUE_SET_OBJECT (&val, o);
357 swfdec_as_object_set_variable_and_flags (context->global, SWFDEC_AS_STR_ASnative,
358 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
360 f = swfdec_as_native_function_new_bare (context,
361 SWFDEC_AS_STR_ASconstructor, swfdec_player_ASconstructor);
362 o = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (f));
363 SWFDEC_AS_VALUE_SET_OBJECT (&val, o);
364 swfdec_as_object_set_variable_and_flags (context->global, SWFDEC_AS_STR_ASconstructor,
365 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
367 f = swfdec_as_native_function_new_bare (context,
368 SWFDEC_AS_STR_enableDebugConsole, swfdec_player_enableDebugConsole);
369 o = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (f));
370 SWFDEC_AS_VALUE_SET_OBJECT (&val, o);
371 swfdec_as_object_set_variable_and_flags (context->global, SWFDEC_AS_STR_enableDebugConsole,
372 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);