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.
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
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_GC_OBJECT
)
39 swfdec_interval_mark (SwfdecGcObject
*object
)
42 SwfdecInterval
*interval
= SWFDEC_INTERVAL (object
);
44 swfdec_gc_object_mark (interval
->sandbox
);
45 if (interval
->fun_name
)
46 swfdec_as_string_mark (interval
->fun_name
);
47 for (i
= 0; i
< interval
->n_args
+ 1; i
++) {
48 swfdec_as_value_mark (&interval
->args
[i
]);
51 SWFDEC_GC_OBJECT_CLASS (swfdec_interval_parent_class
)->mark (object
);
55 swfdec_interval_dispose (GObject
*object
)
57 SwfdecInterval
*interval
= SWFDEC_INTERVAL (object
);
58 SwfdecAsContext
*cx
= swfdec_gc_object_get_context (interval
);
61 swfdec_as_context_unuse_mem (cx
,
62 (interval
->n_args
+ 1) * sizeof (SwfdecAsValue
));
63 g_slice_free1 ((interval
->n_args
+ 1) * sizeof (SwfdecAsValue
), interval
->args
);
64 interval
->args
= NULL
;
67 /* needed here when GC'ed by closing the player */
68 if (interval
->timeout
.callback
!= NULL
) {
69 swfdec_player_remove_timeout (SWFDEC_PLAYER (cx
), &interval
->timeout
);
70 interval
->timeout
.callback
= NULL
;
73 G_OBJECT_CLASS (swfdec_interval_parent_class
)->dispose (object
);
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
;
88 swfdec_interval_init (SwfdecInterval
*array
)
93 swfdec_interval_trigger (SwfdecTimeout
*timeout
)
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 (player
, timeout
);
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 SwfdecAsObject
*object
= swfdec_as_value_to_object (context
, interval
->args
[0]);
112 swfdec_as_object_call (object
,
113 interval
->fun_name
, interval
->n_args
, interval
->args
, &ret
);
116 /* we check that the relay's type is correct upon adding the interval */
117 swfdec_as_function_call (SWFDEC_AS_FUNCTION (
118 SWFDEC_AS_VALUE_GET_OBJECT (interval
->args
[0])->relay
),
119 NULL
, interval
->n_args
, &interval
->args
[1], &ret
);
121 swfdec_sandbox_unuse (interval
->sandbox
);
125 swfdec_interval_new (SwfdecPlayer
*player
, guint msecs
, gboolean repeat
,
126 const SwfdecAsValue
*src
, const char *fun_name
,
127 guint n_args
, const SwfdecAsValue
*args
)
129 SwfdecAsContext
*context
;
130 SwfdecInterval
*interval
;
132 context
= SWFDEC_AS_CONTEXT (player
);
133 if (!swfdec_as_context_try_use_mem (context
, (n_args
+ 1) * sizeof (SwfdecAsValue
))) {
134 swfdec_as_context_abort (context
,
135 "Too many arguments passed to setInterval/setTimeout");
138 interval
= g_object_new (SWFDEC_TYPE_INTERVAL
, "context", context
, NULL
);
140 interval
->id
= ++player
->priv
->interval_id
;
141 interval
->sandbox
= swfdec_sandbox_get (player
);
142 interval
->msecs
= msecs
;
143 interval
->repeat
= repeat
;
144 interval
->fun_name
= fun_name
;
145 interval
->n_args
= n_args
;
146 interval
->args
= g_slice_alloc ((n_args
+ 1) * sizeof (SwfdecAsValue
));
147 interval
->args
[0] = *src
;
149 memcpy (&interval
->args
[1], args
, n_args
* sizeof (SwfdecAsValue
));
150 interval
->timeout
.timestamp
= player
->priv
->time
+ SWFDEC_MSECS_TO_TICKS (interval
->msecs
);
151 interval
->timeout
.callback
= swfdec_interval_trigger
;
152 swfdec_player_add_timeout (player
, &interval
->timeout
);
154 player
->priv
->intervals
=
155 g_list_prepend (player
->priv
->intervals
, interval
);
161 swfdec_interval_new_function (SwfdecPlayer
*player
, guint msecs
, gboolean repeat
,
162 SwfdecAsFunction
*fun
, guint n_args
, const SwfdecAsValue
*args
)
166 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), 0);
167 g_return_val_if_fail (msecs
> 0, 0);
168 g_return_val_if_fail (SWFDEC_IS_AS_FUNCTION (fun
), 0);
169 g_return_val_if_fail (n_args
== 0 || args
!= NULL
, 0);
171 SWFDEC_AS_VALUE_SET_OBJECT (&val
,
172 swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (fun
)));
173 return swfdec_interval_new (player
, msecs
, repeat
, &val
, NULL
, n_args
, args
);
177 swfdec_interval_new_object (SwfdecPlayer
*player
, guint msecs
, gboolean repeat
,
178 const SwfdecAsValue
*thisp
, const char *fun_name
,
179 guint n_args
, const SwfdecAsValue
*args
)
181 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), 0);
182 g_return_val_if_fail (msecs
> 0, 0);
183 g_return_val_if_fail (thisp
!= NULL
, 0);
184 g_return_val_if_fail (fun_name
!= NULL
, 0);
185 g_return_val_if_fail (n_args
== 0 || args
!= NULL
, 0);
187 return swfdec_interval_new (player
, msecs
, repeat
, thisp
, fun_name
, n_args
, args
);
191 swfdec_interval_remove (SwfdecPlayer
*player
, guint id
)
195 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
197 for (walk
= player
->priv
->intervals
; walk
; walk
= walk
->next
) {
198 SwfdecInterval
*interval
= walk
->data
;
199 if (interval
->id
!= id
)
202 player
->priv
->intervals
= g_list_delete_link (player
->priv
->intervals
, walk
);
203 swfdec_player_remove_timeout (player
, &interval
->timeout
);
204 interval
->timeout
.callback
= NULL
;