fix build for --disable-gtk-doc
[swfdec.git] / swfdec / swfdec_actor.c
blobcafaa7c5aeb0b2f43f5e05972d298bb01e466bfc
1 /* Swfdec
2 * Copyright (C) 2006-2008 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 "swfdec_actor.h"
25 #include "swfdec_as_internal.h"
26 #include "swfdec_as_strings.h"
27 #include "swfdec_debug.h"
28 #include "swfdec_button_movie.h"
29 #include "swfdec_player_internal.h"
30 #include "swfdec_resource.h"
31 #include "swfdec_sandbox.h"
32 #include "swfdec_sprite_movie.h"
35 G_DEFINE_ABSTRACT_TYPE (SwfdecActor, swfdec_actor, SWFDEC_TYPE_MOVIE)
37 static void
38 swfdec_actor_dispose (GObject *object)
40 SwfdecActor *actor = SWFDEC_ACTOR (object);
42 if (actor->events) {
43 swfdec_event_list_free (actor->events);
44 actor->events = NULL;
47 G_OBJECT_CLASS (swfdec_actor_parent_class)->dispose (object);
50 static gboolean
51 swfdec_actor_iterate_end (SwfdecActor *actor)
53 SwfdecMovie *movie = SWFDEC_MOVIE (actor);
55 return movie->parent == NULL ||
56 movie->state < SWFDEC_MOVIE_STATE_REMOVED;
59 static gboolean
60 swfdec_actor_mouse_events (SwfdecActor *actor)
62 SwfdecAsObject *object;
64 /* root movies don't get event */
65 if (SWFDEC_MOVIE (actor)->parent == NULL)
66 return FALSE;
67 /* look if we have a script that gets events */
68 if (actor->events && swfdec_event_list_has_mouse_events (actor->events))
69 return TRUE;
70 /* otherwise, require at least one of the custom script handlers */
71 object = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (actor));
72 if (swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onRollOver) ||
73 swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onRollOut) ||
74 swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onDragOver) ||
75 swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onDragOut) ||
76 swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onPress) ||
77 swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onRelease) ||
78 swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onReleaseOutside))
79 return TRUE;
80 return FALSE;
83 static void
84 swfdec_actor_mouse_in (SwfdecActor *actor)
86 if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor))))
87 swfdec_actor_queue_script (actor, SWFDEC_EVENT_DRAG_OVER);
88 else
89 swfdec_actor_queue_script (actor, SWFDEC_EVENT_ROLL_OVER);
92 static void
93 swfdec_actor_mouse_out (SwfdecActor *actor)
95 if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor))))
96 swfdec_actor_queue_script (actor, SWFDEC_EVENT_DRAG_OUT);
97 else
98 swfdec_actor_queue_script (actor, SWFDEC_EVENT_ROLL_OUT);
101 static void
102 swfdec_actor_mouse_press (SwfdecActor *actor, guint button)
104 if (button != 0)
105 return;
106 swfdec_actor_queue_script (actor, SWFDEC_EVENT_PRESS);
109 static void
110 swfdec_actor_mouse_release (SwfdecActor *actor, guint button)
112 SwfdecPlayer *player;
114 if (button != 0)
115 return;
117 player = SWFDEC_PLAYER (swfdec_gc_object_get_context (actor));
118 if (player->priv->mouse_below == actor)
119 swfdec_actor_queue_script (actor, SWFDEC_EVENT_RELEASE);
120 else
121 swfdec_actor_queue_script (actor, SWFDEC_EVENT_RELEASE_OUTSIDE);
124 static void
125 swfdec_actor_mouse_move (SwfdecActor *actor, double x, double y)
127 /* nothing to do here, it's just there so we don't need to check for NULL */
130 static void
131 swfdec_actor_key_press (SwfdecActor *actor, guint keycode, guint character)
133 swfdec_actor_queue_script (actor, SWFDEC_EVENT_KEY_DOWN);
136 static void
137 swfdec_actor_key_release (SwfdecActor *actor, guint keycode, guint character)
139 swfdec_actor_queue_script (actor, SWFDEC_EVENT_KEY_UP);
142 static GObject *
143 swfdec_actor_constructor (GType type, guint n_construct_properties,
144 GObjectConstructParam *construct_properties)
146 SwfdecPlayerPrivate *priv;
147 GObject *object;
149 object = G_OBJECT_CLASS (swfdec_actor_parent_class)->constructor (type,
150 n_construct_properties, construct_properties);
152 priv = SWFDEC_PLAYER (swfdec_gc_object_get_context (object))->priv;
153 /* NB: adding to the movies list happens before swfdec_movie_initialize().
154 * swfdec_movie_initialize() does a gotoAndPlay(0) for Sprites which can
155 * cause new movies to be created (and added to this list).
157 priv->actors = g_list_prepend (priv->actors, object);
159 return object;
162 static void
163 swfdec_actor_class_init (SwfdecActorClass *klass)
165 GObjectClass *object_class = G_OBJECT_CLASS (klass);
167 object_class->constructor = swfdec_actor_constructor;
168 object_class->dispose = swfdec_actor_dispose;
170 klass->iterate_end = swfdec_actor_iterate_end;
171 klass->mouse_events = swfdec_actor_mouse_events;
172 klass->mouse_in = swfdec_actor_mouse_in;
173 klass->mouse_out = swfdec_actor_mouse_out;
174 klass->mouse_press = swfdec_actor_mouse_press;
175 klass->mouse_release = swfdec_actor_mouse_release;
176 klass->mouse_move = swfdec_actor_mouse_move;
177 klass->key_press = swfdec_actor_key_press;
178 klass->key_release = swfdec_actor_key_release;
181 static void
182 swfdec_actor_init (SwfdecActor *actor)
184 swfdec_sound_matrix_init_identity (&actor->sound_matrix);
187 static gboolean
188 swfdec_sprite_movie_set_constructor (SwfdecSpriteMovie *movie)
190 SwfdecMovie *mov = SWFDEC_MOVIE (movie);
191 SwfdecAsContext *context = swfdec_gc_object_get_context (movie);
192 SwfdecAsObject *constructor = NULL;
193 SwfdecAsObject *object = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (movie));
195 g_assert (mov->resource != NULL);
197 if (movie->sprite) {
198 const char *name;
200 name = swfdec_resource_get_export_name (mov->resource,
201 SWFDEC_CHARACTER (movie->sprite));
202 if (name != NULL) {
203 name = swfdec_as_context_get_string (context, name);
204 constructor = swfdec_player_get_export_class (SWFDEC_PLAYER (context),
205 name);
208 if (constructor == NULL) {
209 swfdec_sandbox_use (SWFDEC_MOVIE (movie)->resource->sandbox);
210 swfdec_as_object_set_constructor_by_name (object,
211 SWFDEC_AS_STR_MovieClip, NULL);
212 swfdec_sandbox_unuse (SWFDEC_MOVIE (movie)->resource->sandbox);
213 return FALSE;
214 } else {
215 swfdec_as_object_set_constructor (object, constructor);
216 return TRUE;
220 void
221 swfdec_actor_execute (SwfdecActor *actor, SwfdecEventType condition,
222 guint8 key)
224 SwfdecMovie *thisp;
225 const char *name;
226 guint version;
227 gboolean need_constructor = FALSE;
229 g_return_if_fail (SWFDEC_IS_ACTOR (actor));
231 version = swfdec_movie_get_version (SWFDEC_MOVIE (actor));
233 if (SWFDEC_IS_BUTTON_MOVIE (actor)) {
234 /* these conditions don't exist for buttons */
235 if (condition == SWFDEC_EVENT_CONSTRUCT || condition < SWFDEC_EVENT_PRESS)
236 return;
237 thisp = SWFDEC_MOVIE (actor)->parent;
238 if (version <= 5) {
239 while (!SWFDEC_IS_SPRITE_MOVIE (thisp))
240 thisp = SWFDEC_MOVIE (thisp)->parent;
242 g_assert (thisp);
243 } else {
244 thisp = SWFDEC_MOVIE (actor);
247 /* special cases */
248 if (condition == SWFDEC_EVENT_CONSTRUCT) {
249 if (version <= 5)
250 return;
251 need_constructor = swfdec_sprite_movie_set_constructor (SWFDEC_SPRITE_MOVIE (actor));
252 } else if (condition == SWFDEC_EVENT_ENTER) {
253 if (SWFDEC_MOVIE (actor)->state >= SWFDEC_MOVIE_STATE_REMOVED)
254 return;
255 } else if (condition == SWFDEC_EVENT_SCROLL || condition == SWFDEC_EVENT_CHANGED) {
256 SwfdecAsValue argv[2];
257 SwfdecMovie *movie = SWFDEC_MOVIE (actor);
259 if (condition == SWFDEC_EVENT_SCROLL)
260 SWFDEC_AS_VALUE_SET_STRING (&argv[0], SWFDEC_AS_STR_onScroller);
261 else
262 SWFDEC_AS_VALUE_SET_STRING (&argv[0], SWFDEC_AS_STR_onChanged);
263 SWFDEC_AS_VALUE_SET_MOVIE (&argv[1], movie);
264 swfdec_sandbox_use (movie->resource->sandbox);
265 swfdec_as_relay_call (SWFDEC_AS_RELAY (actor),
266 SWFDEC_AS_STR_broadcastMessage, 2, argv, NULL);
267 swfdec_sandbox_unuse (movie->resource->sandbox);
268 return;
271 swfdec_sandbox_use (SWFDEC_MOVIE (actor)->resource->sandbox);
272 if (actor->events) {
273 swfdec_event_list_execute (actor->events, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (thisp)),
274 condition, key);
276 /* FIXME: how do we compute the version correctly here? */
277 if (version > 5) {
278 name = swfdec_event_type_get_name (condition);
279 if (name != NULL) {
280 swfdec_as_relay_call (SWFDEC_AS_RELAY (actor), name, 0, NULL, NULL);
282 if (condition == SWFDEC_EVENT_CONSTRUCT && need_constructor)
283 swfdec_as_relay_call (SWFDEC_AS_RELAY (thisp), SWFDEC_AS_STR_constructor, 0, NULL, NULL);
285 swfdec_sandbox_unuse (SWFDEC_MOVIE (actor)->resource->sandbox);
289 * swfdec_actor_queue_script_with_key:
290 * @movie: a #SwfdecMovie
291 * @condition: the event that should happen
292 * @key: the key for this event
294 * Queues execution of all scripts associated with the given event and key.
296 void
297 swfdec_actor_queue_script_with_key (SwfdecActor *actor,
298 SwfdecEventType condition, guint8 key)
300 SwfdecPlayer *player;
301 guint importance;
303 g_return_if_fail (SWFDEC_IS_ACTOR (actor));
305 if (!SWFDEC_IS_SPRITE_MOVIE (actor) && !SWFDEC_IS_BUTTON_MOVIE (actor))
306 return;
307 /* can happen for mouse/keyboard events on the initial movie */
308 if (SWFDEC_MOVIE (actor)->resource->sandbox == NULL) {
309 SWFDEC_INFO ("movie %s not yet initialized, skipping event", SWFDEC_MOVIE (actor)->name);
310 return;
313 switch (condition) {
314 case SWFDEC_EVENT_INITIALIZE:
315 importance = SWFDEC_PLAYER_ACTION_QUEUE_INIT;
316 break;
317 case SWFDEC_EVENT_CONSTRUCT:
318 importance = SWFDEC_PLAYER_ACTION_QUEUE_CONSTRUCT;
319 break;
320 case SWFDEC_EVENT_LOAD:
321 case SWFDEC_EVENT_ENTER:
322 case SWFDEC_EVENT_UNLOAD:
323 case SWFDEC_EVENT_MOUSE_MOVE:
324 case SWFDEC_EVENT_MOUSE_DOWN:
325 case SWFDEC_EVENT_MOUSE_UP:
326 case SWFDEC_EVENT_KEY_UP:
327 case SWFDEC_EVENT_KEY_DOWN:
328 case SWFDEC_EVENT_DATA:
329 case SWFDEC_EVENT_PRESS:
330 case SWFDEC_EVENT_RELEASE:
331 case SWFDEC_EVENT_RELEASE_OUTSIDE:
332 case SWFDEC_EVENT_ROLL_OVER:
333 case SWFDEC_EVENT_ROLL_OUT:
334 case SWFDEC_EVENT_DRAG_OVER:
335 case SWFDEC_EVENT_DRAG_OUT:
336 case SWFDEC_EVENT_KEY_PRESS:
337 case SWFDEC_EVENT_CHANGED:
338 case SWFDEC_EVENT_SCROLL:
339 importance = SWFDEC_PLAYER_ACTION_QUEUE_NORMAL;
340 break;
341 default:
342 g_return_if_reached ();
345 player = SWFDEC_PLAYER (swfdec_gc_object_get_context (actor));
346 swfdec_player_add_action (player, actor, condition, key, importance);
350 * swfdec_actor_queue_script:
351 * @movie: a #SwfdecMovie
352 * @condition: the event that should happen
354 * Queues execution of all scripts associated with the given event.
356 void
357 swfdec_actor_queue_script (SwfdecActor *actor, SwfdecEventType condition)
359 swfdec_actor_queue_script_with_key (actor, condition, 0);
363 * swfdec_actor_get_mouse_events:
364 * @movie: a #SwfdecActor
366 * Checks if this actor should respond to mouse events.
368 * Returns: %TRUE if this movie can receive mouse events
370 gboolean
371 swfdec_actor_get_mouse_events (SwfdecActor *actor)
373 SwfdecActorClass *klass;
375 g_return_val_if_fail (SWFDEC_IS_ACTOR (actor), FALSE);
377 klass = SWFDEC_ACTOR_GET_CLASS (actor);
378 if (klass->mouse_events)
379 return klass->mouse_events (actor);
380 else
381 return FALSE;
384 gboolean
385 swfdec_actor_has_focusrect (SwfdecActor *actor)
387 g_return_val_if_fail (SWFDEC_IS_ACTOR (actor), FALSE);
389 if (!SWFDEC_IS_BUTTON_MOVIE (actor) &&
390 !SWFDEC_IS_SPRITE_MOVIE (actor))
391 return FALSE;
393 if (actor->focusrect == SWFDEC_FLASH_MAYBE) {
394 actor = SWFDEC_ACTOR (swfdec_movie_get_root (SWFDEC_MOVIE (actor)));
396 g_assert (actor->focusrect != SWFDEC_FLASH_MAYBE);
398 return actor->focusrect != SWFDEC_FLASH_NO;