[Swfdec] 6 commits - libswfdec/Makefile.am libswfdec/swfdec_js.c libswfdec/swfdec_js_mouse.c libswfdec/swfdec_listener.c libswfdec/swfdec_listener.h libswfdec/swfdec_movie.c libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_root_movie.c libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_types.h player/swfdebug.c player/swfdec_player_manager.c

Benjamin Otte company at kemper.freedesktop.org
Thu Feb 22 08:32:38 PST 2007


 libswfdec/Makefile.am              |    2 
 libswfdec/swfdec_js.c              |    5 +
 libswfdec/swfdec_js_mouse.c        |   30 +++++-
 libswfdec/swfdec_listener.c        |  184 +++++++++++++++++++++++++++++++++++++
 libswfdec/swfdec_listener.h        |   42 ++++++++
 libswfdec/swfdec_movie.c           |    3 
 libswfdec/swfdec_player.c          |   55 +++++++++--
 libswfdec/swfdec_player_internal.h |   12 +-
 libswfdec/swfdec_root_movie.c      |    2 
 libswfdec/swfdec_sprite_movie.c    |   11 +-
 libswfdec/swfdec_types.h           |    1 
 player/swfdebug.c                  |   35 +++++--
 player/swfdec_player_manager.c     |    5 +
 13 files changed, 357 insertions(+), 30 deletions(-)

New commits:
diff-tree f5d0f071e911b84ac0c2c840d965a7d3f16c4be5 (from f1457b93b4d9cb43650b0e595bbe41096230281f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Feb 21 10:42:05 2007 +0100

    handle NULL input when converting args

diff --git a/player/swfdec_player_manager.c b/player/swfdec_player_manager.c
index 82d55ed..31e9772 100644
--- a/player/swfdec_player_manager.c
+++ b/player/swfdec_player_manager.c
@@ -325,6 +325,7 @@ swfdec_player_manager_send_message (Swfd
 const char *
 parse_skip (const char *input)
 {
+  g_assert (input);
   if (g_ascii_isspace (*input))
     input++;
   return input;
@@ -336,6 +337,8 @@ parse_string (const char *input, char **
   const char *start = input;
 
   g_assert (output);
+  if (input == NULL)
+    return NULL;
 
   while (*input && !g_ascii_isspace (*input))
     input++;
@@ -352,6 +355,8 @@ parse_uint (const char *input, guint *ou
   guint result;
 
   g_assert (output);
+  if (input == NULL)
+    return NULL;
 
   result = strtoul (input, &end, 10);
   if (input == end || (*end != '\0' && !g_ascii_isspace (*end)))
diff-tree f1457b93b4d9cb43650b0e595bbe41096230281f (from c37787b576447a80f90421643ffdf4dfbeae9350)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Feb 20 15:02:29 2007 +0100

    implement Mouse.addListener() and Mouse.removeListener()

diff --git a/libswfdec/swfdec_js_mouse.c b/libswfdec/swfdec_js_mouse.c
index dfea1c2..2a31248 100644
--- a/libswfdec/swfdec_js_mouse.c
+++ b/libswfdec/swfdec_js_mouse.c
@@ -23,9 +23,33 @@
 
 #include "swfdec_js.h"
 #include "swfdec_debug.h"
+#include "swfdec_listener.h"
 #include "swfdec_player_internal.h"
 
 static JSBool
+swfdec_js_mouse_add_listener (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecPlayer *player = JS_GetContextPrivate (cx);
+
+  g_assert (player);
+  if (!JSVAL_IS_OBJECT (argv[0]) || argv[0] == JSVAL_NULL)
+    return JS_TRUE;
+  return swfdec_listener_add (player->mouse_listener, JSVAL_TO_OBJECT (argv[0]));
+}
+
+static JSBool
+swfdec_js_mouse_remove_listener (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecPlayer *player = JS_GetContextPrivate (cx);
+
+  g_assert (player);
+  if (!JSVAL_IS_OBJECT (argv[0]) || argv[0] == JSVAL_NULL)
+    return JS_TRUE;
+  swfdec_listener_remove (player->mouse_listener, JSVAL_TO_OBJECT (argv[0]));
+  return JS_TRUE;
+}
+
+static JSBool
 swfdec_js_mouse_show (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
   SwfdecPlayer *player = JS_GetContextPrivate (cx);
@@ -46,8 +70,10 @@ swfdec_js_mouse_hide (JSContext *cx, JSO
 }
 
 static JSFunctionSpec mouse_methods[] = {
-    {"show",		swfdec_js_mouse_show,	0, 0, 0 },
-    {"hide",		swfdec_js_mouse_hide,	0, 0, 0 },
+    {"addListener",   	swfdec_js_mouse_add_listener,		1, 0, 0 },
+    {"hide",		swfdec_js_mouse_hide,			0, 0, 0 },
+    {"removeListener",	swfdec_js_mouse_remove_listener,	1, 0, 0 },
+    {"show",		swfdec_js_mouse_show,			0, 0, 0 },
     {0,0,0,0,0}
 };
 
diff-tree c37787b576447a80f90421643ffdf4dfbeae9350 (from 4ce0d0abb3f64d0b93d9718051344275be5bdedb)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Feb 20 15:01:58 2007 +0100

    call _perform_actions after scheduling timeouts
    
    This ensures that timeouts added via setInterval that schedule actions
    (most likely gotoFrame) get executed properly and we don't hit assertions
    that want the action count to be empty.
    The patch also adds some debugging.

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 2f7deef..76c93e7 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -207,6 +207,7 @@ swfdec_player_add_action (SwfdecPlayer *
   g_return_if_fail (action_func != NULL);
 
   action = swfdec_ring_buffer_push (player->actions);
+  SWFDEC_LOG ("adding action %p %p %p", object, action_func, action_data);
   if (action == NULL) {
     /* FIXME: limit number of actions to not get inf loops due to scripts? */
     swfdec_ring_buffer_set_size (player->actions,
@@ -239,8 +240,11 @@ swfdec_player_remove_all_actions (Swfdec
   for (i = 0; i < swfdec_ring_buffer_get_n_elements (player->actions); i++) {
     action = swfdec_ring_buffer_peek_nth (player->actions, i);
 
-    if (action->object == object)
+    if (action->object == object) {
+      SWFDEC_LOG ("removing action %p %p %p", 
+	  action->object, action->func, action->data);
       action->object = NULL;
+    }
   }
 }
 
@@ -256,6 +260,8 @@ swfdec_player_do_action (SwfdecPlayer *p
   } while (action->object == NULL); /* skip removed actions */
 
   action->func (action->object, action->data);
+  SWFDEC_LOG ("executing action %p %p %p", 
+      action->object, action->func, action->data);
 
   return TRUE;
 }
@@ -648,6 +654,7 @@ swfdec_player_do_advance (SwfdecPlayer *
     SWFDEC_LOG ("activating timeout %p now (timeout is %"G_GUINT64_FORMAT", target time is %"G_GUINT64_FORMAT,
 	timeout, timeout->timestamp, target_time);
     timeout->callback (timeout);
+    swfdec_player_perform_actions (player);
   }
   if (target_time > player->time) {
     frames_now = SWFDEC_TICKS_TO_SAMPLES (target_time) -
@@ -696,6 +703,7 @@ swfdec_player_lock (SwfdecPlayer *player
   g_assert (swfdec_rect_is_empty (&player->invalid));
 
   g_object_freeze_notify (G_OBJECT (player));
+  SWFDEC_DEBUG ("LOCKED");
 }
 
 void
@@ -704,6 +712,7 @@ swfdec_player_unlock (SwfdecPlayer *play
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
   g_assert (swfdec_ring_buffer_get_n_elements (player->actions) == 0);
 
+  SWFDEC_DEBUG ("UNLOCK");
   swfdec_player_update_mouse_cursor (player);
   g_object_thaw_notify (G_OBJECT (player));
   swfdec_player_emit_signals (player);
diff-tree 4ce0d0abb3f64d0b93d9718051344275be5bdedb (from e5d04657bbb051abe723a80ecd28df4bdc0f4ba4)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Feb 20 13:00:28 2007 +0100

    add SwfdecListener
    
    SwfdecListener is supposed to be used for implementing addListener/removeListener
    functionality for Mouse and Key objects.

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 0216266..1fd20c9 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -51,6 +51,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_js_mouse.c \
 	swfdec_js_movie.c \
 	swfdec_js_sound.c \
+	swfdec_listener.c \
 	swfdec_loader.c \
 	swfdec_loadertarget.c \
 	swfdec_marshal.c \
@@ -121,6 +122,7 @@ noinst_HEADERS = \
 	swfdec_graphic_movie.h \
 	swfdec_image.h \
 	swfdec_js.h \
+	swfdec_listener.h \
 	swfdec_loader_internal.h \
 	swfdec_loadertarget.h \
 	swfdec_marshal.h \
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index e6ce8a5..ee5c7b7 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -30,6 +30,7 @@
 #include "swfdec_player_internal.h"
 #include "swfdec_debug.h"
 #include "swfdec_js.h"
+#include "swfdec_listener.h"
 #include "swfdec_root_movie.h"
 #include "swfdec_swf_decoder.h"
 
@@ -111,6 +112,8 @@ swfdec_js_init_player (SwfdecPlayer *pla
   swfdec_js_add_movieclip_class (player);
   swfdec_js_add_color (player);
   swfdec_js_add_sound (player);
+  player->mouse_listener = swfdec_listener_new (player);
+  player->key_listener = swfdec_listener_new (player);
 }
 
 typedef struct _SwfdecJSInterval SwfdecJSInterval;
@@ -124,6 +127,8 @@ extern void swfdec_js_interval_free (Swf
 void
 swfdec_js_finish_player (SwfdecPlayer *player)
 {
+  swfdec_listener_free (player->mouse_listener);
+  swfdec_listener_free (player->key_listener);
   while (player->intervals)
     swfdec_js_interval_free (player->intervals->data);
   if (player->jscx) {
diff --git a/libswfdec/swfdec_listener.c b/libswfdec/swfdec_listener.c
new file mode 100644
index 0000000..85ea67d
--- /dev/null
+++ b/libswfdec/swfdec_listener.c
@@ -0,0 +1,184 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "swfdec_listener.h"
+#include "js/jsapi.h"
+#include "js/jsfun.h"
+#include "js/jsinterp.h"
+#include "swfdec_debug.h"
+#include "swfdec_player_internal.h"
+
+typedef struct {
+  JSObject *	object;			/* the object we care about or NULL if empty */
+  gboolean	blocked :1;		/* TRUE if may not be removed */
+  gboolean	removed :1;		/* TRUE if was removed but is blocked */
+} SwfdecListenerEntry;
+
+struct _SwfdecListener {
+  SwfdecPlayer *	player;
+  /* we can't use GArray here because it reallocated below us, which JS_AddRoot doesn't like */
+  SwfdecListenerEntry * entries;	/* all allocated entries */
+  guint			n_entries;	/* number of allocated entries */
+};
+
+SwfdecListener *
+swfdec_listener_new (SwfdecPlayer *player)
+{
+  SwfdecListener *listener = g_new0 (SwfdecListener, 1);
+
+  listener->player = player;
+  listener->entries = NULL;
+  listener->n_entries = 0;
+
+  return listener;
+}
+
+void
+swfdec_listener_free (SwfdecListener *listener)
+{
+  guint i;
+  JSContext *cx;
+
+  g_return_if_fail (listener != NULL);
+
+  cx = listener->player->jscx;
+  for (i = 0; i < listener->n_entries; i++) {
+    JS_RemoveRoot (cx, &listener->entries[i].object);
+  }
+  g_free (listener->entries);
+  swfdec_player_remove_all_actions (listener->player, listener);
+  g_free (listener);
+}
+
+gboolean
+swfdec_listener_add (SwfdecListener *listener, JSObject *obj)
+{
+  guint found, i;
+
+  g_return_val_if_fail (listener != NULL, FALSE);
+  g_return_val_if_fail (obj != NULL, FALSE);
+
+  found = listener->n_entries;
+  for (i = 0; i < listener->n_entries; i++) {
+    if (listener->entries[i].object == NULL && found >= listener->n_entries)
+      found = i;
+    else if (listener->entries[i].object == obj)
+      return TRUE;
+  }
+  if (found >= listener->n_entries) {
+    gpointer mem;
+    guint new_len = listener->n_entries + 16;
+    JSContext *cx = listener->player->jscx;
+
+    for (i = 0; i < listener->n_entries; i++) {
+      JS_RemoveRoot (cx, &listener->entries[i].object);
+    }
+    mem = g_try_realloc (listener->entries, sizeof (SwfdecListenerEntry) * new_len);
+    if (mem == NULL)
+      return FALSE;
+    listener->entries = mem;
+    for (i = listener->n_entries; i < new_len; i++) {
+      listener->entries[i].object = NULL;
+      listener->entries[i].blocked = 0;
+      listener->entries[i].removed = 0;
+      if (!JS_AddRoot (cx, &listener->entries[i].object)) {
+	listener->n_entries = i;
+	return FALSE;
+      }
+    }
+    listener->n_entries = new_len;
+  }
+  g_assert (listener->entries[found].object == NULL);
+  listener->entries[found].object = obj;
+  return TRUE;
+}
+
+void
+swfdec_listener_remove (SwfdecListener *listener, JSObject *obj)
+{
+  guint i;
+
+  g_return_if_fail (listener != NULL);
+  g_return_if_fail (obj != NULL);
+
+  for (i = 0; i < listener->n_entries; i++) {
+    if (listener->entries[i].object == obj) {
+      if (listener->entries[i].blocked) {
+	listener->entries[i].removed = TRUE;
+      } else {
+	listener->entries[i].object = NULL;
+      }
+      return;
+    }
+  }
+}
+
+static void
+swfdec_listener_do_execute (gpointer listenerp, gpointer event_name)
+{
+  guint i;
+  SwfdecListener *listener = listenerp;
+  JSContext *cx = listener->player->jscx;
+
+  for (i = 0; i < listener->n_entries; i++) {
+    if (listener->entries[i].blocked) {
+      jsval fun;
+      JSObject *obj = listener->entries[i].object;
+      if (listener->entries[i].removed) {
+	listener->entries[i].object = NULL;
+	listener->entries[i].removed = FALSE;
+      }
+      listener->entries[i].blocked = FALSE;
+      if (!JS_GetProperty (cx, obj, event_name, &fun))
+	continue;
+      if (!JSVAL_IS_OBJECT (fun) || fun == JSVAL_NULL ||
+	  JS_GetClass (JSVAL_TO_OBJECT (fun)) != &js_FunctionClass) {
+	SWFDEC_INFO ("object has no handler for %s event", (char *) event_name);
+	continue;
+      }
+      js_InternalCall (cx, obj, fun, 0, NULL, &fun);
+    }
+  }
+  g_free (event_name);
+}
+
+void
+swfdec_listener_execute	(SwfdecListener *listener, const char *event_name)
+{
+  gboolean found = FALSE;
+  guint i;
+
+  g_return_if_fail (listener != NULL);
+  g_return_if_fail (event_name != NULL);
+
+  for (i = 0; i < listener->n_entries; i++) {
+    g_assert (!listener->entries[i].blocked); /* ensure this happens only once */
+    if (listener->entries[i].object) {
+      listener->entries[i].blocked = TRUE;
+      found = TRUE;
+    }
+  }
+  if (found)
+    swfdec_player_add_action (listener->player, listener, 
+	swfdec_listener_do_execute, g_strdup (event_name));
+}
+
diff --git a/libswfdec/swfdec_listener.h b/libswfdec/swfdec_listener.h
new file mode 100644
index 0000000..de4694d
--- /dev/null
+++ b/libswfdec/swfdec_listener.h
@@ -0,0 +1,42 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#include <libswfdec/swfdec.h>
+#include <libswfdec/swfdec_types.h>
+#include <libswfdec/js/jspubtd.h>
+
+#ifndef _SWFDEC_LISTENER_H_
+#define _SWFDEC_LISTENER_H_
+
+G_BEGIN_DECLS
+
+
+SwfdecListener *	swfdec_listener_new	(SwfdecPlayer *		player);
+void			swfdec_listener_free	(SwfdecListener *	listener);
+gboolean		swfdec_listener_add	(SwfdecListener *	listener,
+						 JSObject *		obj);
+void			swfdec_listener_remove	(SwfdecListener *	listener,
+						 JSObject *		obj);
+void			swfdec_listener_execute	(SwfdecListener *	listener,
+						 const char *		event);
+
+
+G_END_DECLS
+
+#endif
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 0034a65..2f7deef 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -33,6 +33,7 @@
 #include "swfdec_enums.h"
 #include "swfdec_event.h"
 #include "swfdec_js.h"
+#include "swfdec_listener.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_marshal.h"
 #include "swfdec_movie.h"
@@ -493,6 +494,7 @@ swfdec_player_do_mouse_move (SwfdecPlaye
   for (walk = player->movies; walk; walk = walk->next) {
     swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_MOVE);
   }
+  swfdec_listener_execute (player->mouse_listener, "onMouseMove");
   swfdec_player_update_mouse_position (player);
 }
 
@@ -501,15 +503,19 @@ swfdec_player_do_mouse_button (SwfdecPla
 {
   GList *walk;
   guint event;
+  const char *event_name;
 
   if (player->mouse_button) {
     event = SWFDEC_EVENT_MOUSE_DOWN;
+    event_name = "onMouseDown";
   } else {
     event = SWFDEC_EVENT_MOUSE_UP;
+    event_name = "onMouseUp";
   }
   for (walk = player->movies; walk; walk = walk->next) {
     swfdec_movie_queue_script (walk->data, event);
   }
+  swfdec_listener_execute (player->mouse_listener, event_name);
   if (player->mouse_grab)
     swfdec_movie_send_mouse_change (player->mouse_grab, FALSE);
 }
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index fc316b1..2e63b78 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -53,6 +53,10 @@ struct _SwfdecPlayer
   /* javascript */
   JSContext *		jscx;			/* global Javascript context */
   JSObject *		jsobj;			/* the global object */
+  unsigned int		interval_id;		/* id returned from setInterval call */
+  GList *		intervals;		/* all currently running intervals */
+  SwfdecListener *	mouse_listener;		/* emitting mouse events */
+  SwfdecListener *	key_listener;		/* emitting keyboard events */
 
   /* rendering */
   SwfdecRect		invalid;      		/* area that needs a rredraw */
@@ -80,8 +84,6 @@ struct _SwfdecPlayer
   /* iterating */
   GList *		movies;			/* list of all moveis that want to be iterated */
   SwfdecRingBuffer *	actions;		/* all actions we've queued up so far */
-  unsigned int		interval_id;		/* id returned from setInterval call */
-  GList *		intervals;		/* all currently running intervals */
 };
 
 struct _SwfdecPlayerClass
diff --git a/libswfdec/swfdec_types.h b/libswfdec/swfdec_types.h
index f03b60f..f601dff 100644
--- a/libswfdec/swfdec_types.h
+++ b/libswfdec/swfdec_types.h
@@ -43,6 +43,7 @@ typedef struct _SwfdecEventList SwfdecEv
 typedef struct _SwfdecFont SwfdecFont;
 typedef struct _SwfdecGraphic SwfdecGraphic;
 typedef struct _SwfdecImage SwfdecImage;
+typedef struct _SwfdecListener SwfdecListener;
 typedef struct _SwfdecMovie SwfdecMovie;
 typedef struct _SwfdecShape SwfdecShape;
 typedef struct _SwfdecShapeVec SwfdecShapeVec;
diff-tree e5d04657bbb051abe723a80ecd28df4bdc0f4ba4 (from 650e111062975b4911c16dcac67885e2ac32d892)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Feb 20 11:58:34 2007 +0100

    make the actions take any gpointer instead of just SwfdecMovies for actions

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index cbb787c..a1df353 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -334,8 +334,9 @@ swfdec_movie_remove (SwfdecMovie *movie)
 }
 
 static void
-swfdec_movie_execute_script (SwfdecMovie *movie, gpointer data)
+swfdec_movie_execute_script (gpointer moviep, gpointer data)
 {
+  SwfdecMovie *movie = moviep;
   guint condition = GPOINTER_TO_UINT (data);
 
   g_assert (movie->content->events);
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 0717ff5..0034a65 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -178,19 +178,31 @@ swfdec_player_remove_timeout (SwfdecPlay
 /*** Actions ***/
 
 typedef struct {
-  SwfdecMovie *		movie;
+  gpointer		object;
   SwfdecActionFunc	func;
   gpointer		data;
 } SwfdecPlayerAction;
 
+/**
+ * swfdec_player_add_action:
+ * @player: a #SwfdecPlayer
+ * @object: object identifying the action
+ * @action_func: function to execute
+ * @action_data: additional data to pass to @func
+ *
+ * Adds an action to the @player. Actions are used by Flash player to solve
+ * reentrancy issues. Instead of calling back into the Actionscript engine,
+ * an action is queued for later execution. So if you're writing code that
+ * is calling Actionscript code, you want to do this by using actions.
+ **/
 void
-swfdec_player_add_action (SwfdecPlayer *player, SwfdecMovie *movie,
+swfdec_player_add_action (SwfdecPlayer *player, gpointer object,
     SwfdecActionFunc action_func, gpointer action_data)
 {
   SwfdecPlayerAction *action;
 
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
-  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+  g_return_if_fail (object != NULL);
   g_return_if_fail (action_func != NULL);
 
   action = swfdec_ring_buffer_push (player->actions);
@@ -201,25 +213,33 @@ swfdec_player_add_action (SwfdecPlayer *
     action = swfdec_ring_buffer_push (player->actions);
     g_assert (action);
   }
-  action->movie = movie;
+  action->object = object;
   action->func = action_func;
   action->data = action_data;
 }
 
+/**
+ * swfdec_player_remove_all_actions:
+ * @player: a #SwfdecPlayer
+ * @object: object pointer identifying the actions to be removed
+ *
+ * Removes all actions associated with @object. See swfdec_player_add_action()
+ * for details about actions.
+ **/
 void
-swfdec_player_remove_all_actions (SwfdecPlayer *player, SwfdecMovie *movie)
+swfdec_player_remove_all_actions (SwfdecPlayer *player, gpointer object)
 {
   SwfdecPlayerAction *action;
   guint i;
 
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
-  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+  g_return_if_fail (object != NULL);
 
   for (i = 0; i < swfdec_ring_buffer_get_n_elements (player->actions); i++) {
     action = swfdec_ring_buffer_peek_nth (player->actions, i);
 
-    if (action->movie == movie)
-      action->movie = NULL;
+    if (action->object == object)
+      action->object = NULL;
   }
 }
 
@@ -232,9 +252,9 @@ swfdec_player_do_action (SwfdecPlayer *p
     action = swfdec_ring_buffer_pop (player->actions);
     if (action == NULL)
       return FALSE;
-  } while (action->movie == NULL); /* skip removed actions */
+  } while (action->object == NULL); /* skip removed actions */
 
-  action->func (action->movie, action->data);
+  action->func (action->object, action->data);
 
   return TRUE;
 }
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index ebc5fe9..fc316b1 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -28,7 +28,7 @@
 
 G_BEGIN_DECLS
 
-typedef void (* SwfdecActionFunc) (SwfdecMovie *movie, gpointer data);
+typedef void (* SwfdecActionFunc) (gpointer object, gpointer data);
 
 typedef struct _SwfdecTimeout SwfdecTimeout;
 struct _SwfdecTimeout {
@@ -118,11 +118,11 @@ void		swfdec_player_add_timeout	(SwfdecP
 void		swfdec_player_remove_timeout	(SwfdecPlayer *		player,
 						 SwfdecTimeout *	timeout);
 void		swfdec_player_add_action	(SwfdecPlayer *		player,
-						 SwfdecMovie *		movie,
+						 gpointer		object,
 						 SwfdecActionFunc   	action_func,
 						 gpointer		action_data);
 void		swfdec_player_remove_all_actions (SwfdecPlayer *      	player,
-						 SwfdecMovie *		movie);
+						 gpointer		object);
 void		swfdec_player_set_drag_movie	(SwfdecPlayer *		player,
 						 SwfdecMovie *		drag,
 						 gboolean		center,
diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c
index 473b49b..414838e 100644
--- a/libswfdec/swfdec_root_movie.c
+++ b/libswfdec/swfdec_root_movie.c
@@ -169,7 +169,7 @@ swfdec_root_movie_init (SwfdecRootMovie 
 }
 
 void
-swfdec_root_movie_do_parse (SwfdecMovie *movie, gpointer unused)
+swfdec_root_movie_do_parse (gpointer movie, gpointer unused)
 {
   swfdec_loader_parse_internal (SWFDEC_ROOT_MOVIE (movie)->loader);
 }
diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index 1cc2f0b..d5545df 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -62,7 +62,7 @@ swfdec_sprite_movie_remove_child (Swfdec
 }
 
 static void
-swfdec_sprite_movie_run_script (SwfdecMovie *movie, gpointer data)
+swfdec_sprite_movie_run_script (gpointer movie, gpointer data)
 {
   swfdec_script_execute (data, SWFDEC_SCRIPTABLE (movie));
 }
@@ -121,9 +121,10 @@ swfdec_sprite_movie_perform_one_action (
 }
 
 static void
-swfdec_sprite_movie_do_goto_frame (SwfdecMovie *mov, gpointer data)
+swfdec_sprite_movie_do_goto_frame (gpointer moviep, gpointer data)
 {
-  SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov);
+  SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (moviep);
+  SwfdecMovie *mov = moviep;
   unsigned int goto_frame = GPOINTER_TO_UINT (data);
   GList *old, *walk;
   guint i, j, start;
@@ -216,8 +217,10 @@ swfdec_sprite_movie_dispose (GObject *ob
 }
 
 static void
-swfdec_sprite_movie_queue_enter_frame (SwfdecMovie *movie, gpointer unused)
+swfdec_sprite_movie_queue_enter_frame (gpointer moviep, gpointer unused)
 {
+  SwfdecMovie *movie = moviep;
+
   if (movie->will_be_removed)
     return;
   swfdec_movie_queue_script (movie, SWFDEC_EVENT_ENTER);
diff-tree 650e111062975b4911c16dcac67885e2ac32d892 (from ba5327ffe305de547d40a282a1d866a2cf9e992e)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Feb 20 11:29:51 2007 +0100

    andle quitting in breakpoint while feeding data

diff --git a/player/swfdebug.c b/player/swfdebug.c
index e1f0cbd..f5aa12b 100644
--- a/player/swfdebug.c
+++ b/player/swfdebug.c
@@ -170,8 +170,17 @@ select_script_cb (SwfdecPlayerManager *m
 }
 
 static void
+force_continue (SwfdecPlayerManager *manager, GParamSpec *pspec, gpointer unused)
+{
+  g_signal_stop_emission_by_name (manager, "notify::interrupted");
+  if (swfdec_player_manager_get_interrupted (manager))
+    swfdec_player_manager_continue (manager);
+}
+
+static void
 destroyed_cb (GtkWindow *window, SwfdecPlayerManager *manager)
 {
+  g_signal_connect (manager, "notify::interrupted", G_CALLBACK (force_continue), NULL);
   if (swfdec_player_manager_get_interrupted (manager))
     swfdec_player_manager_continue (manager);
   g_object_unref (manager);
@@ -297,6 +306,22 @@ do_break_cb (SwfdecDebugger *debugger, S
   swfdec_debugger_set_breakpoint (debugger, script, 0);
 }
 
+static gboolean
+add_variables (gpointer player)
+{
+  const char *variables = g_object_get_data (player, "variables");
+  SwfdecLoader *loader = g_object_get_data (player, "loader");
+
+  swfdec_player_set_loader_with_variables (player, loader, variables);
+  if (!swfdec_player_is_initialized (player)) {
+    g_printerr ("File \"%s\" is not a file Swfdec can play\n", loader->url);
+    g_object_unref (player);
+    gtk_main_quit ();
+    return FALSE;
+  }
+  return FALSE;
+}
+
 int 
 main (int argc, char *argv[])
 {
@@ -348,13 +373,9 @@ main (int argc, char *argv[])
   if (do_break)
     g_signal_connect (player, "script-added", G_CALLBACK (do_break_cb), NULL);
   view_swf (player, scale, use_image);
-  swfdec_player_set_loader_with_variables (player, loader, variables);
-  if (!swfdec_player_is_initialized (player)) {
-    g_printerr ("File \"%s\" is not a file Swfdec can play\n", argv[1]);
-    g_object_unref (player);
-    player = NULL;
-    return 1;
-  }
+  g_object_set_data (G_OBJECT (player), "loader", loader);
+  g_object_set_data (G_OBJECT (player), "variables", variables);
+  g_idle_add_full (G_PRIORITY_HIGH, add_variables, player, NULL);
 
   gtk_main ();
 


More information about the Swfdec mailing list