[Swfdec] 10 commits - doc/swfdec-sections.txt libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h libswfdec/swfdec_loader.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie_clip_loader.c libswfdec/swfdec_movie.h libswfdec/swfdec_resource.c libswfdec/swfdec_resource_request.c libswfdec/swfdec_resource_request.h libswfdec/swfdec_sprite_movie.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Fri Nov 9 08:23:41 PST 2007


 doc/swfdec-sections.txt                   |    1 
 libswfdec/swfdec_as_interpret.c           |   14 ++++-
 libswfdec/swfdec_as_object.c              |    6 +-
 libswfdec/swfdec_as_object.h              |    3 -
 libswfdec/swfdec_loader.c                 |   18 +++---
 libswfdec/swfdec_movie.c                  |   11 +++-
 libswfdec/swfdec_movie.h                  |    1 
 libswfdec/swfdec_movie_clip_loader.c      |    7 ++
 libswfdec/swfdec_resource.c               |    2 
 libswfdec/swfdec_resource_request.c       |   81 +++++++++++++++++++++++++-----
 libswfdec/swfdec_resource_request.h       |   27 ++++++++--
 libswfdec/swfdec_sprite_movie.c           |    6 +-
 test/trace/Makefile.am                    |    9 +++
 test/trace/unloadmovie-simple-5.swf       |binary
 test/trace/unloadmovie-simple-5.swf.trace |    4 +
 test/trace/unloadmovie-simple-6.swf       |binary
 test/trace/unloadmovie-simple-6.swf.trace |   12 ++++
 test/trace/unloadmovie-simple-7.swf       |binary
 test/trace/unloadmovie-simple-7.swf.trace |   12 ++++
 test/trace/unloadmovie-simple-8.swf       |binary
 test/trace/unloadmovie-simple-8.swf.trace |   12 ++++
 test/trace/unloadmovie-simple.as          |   16 +++++
 22 files changed, 205 insertions(+), 37 deletions(-)

New commits:
commit 1453a43c36678b07a4c585e1173a0d4b78bc8e52
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 17:22:55 2007 +0100

    handle reentrancy correctly
    
    fixes mysterious segfaults on AMD64

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 04c21a0..618b9d7 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -210,9 +210,10 @@ swfdec_loader_init (SwfdecLoader *loader)
 static void
 swfdec_loader_process (gpointer loaderp, gpointer unused)
 {
-  SwfdecLoaderTarget *target;
   SwfdecLoader *loader = loaderp;
 
+  g_assert (loader->target != NULL);
+
   loader->queued = FALSE;
   if (loader->state == loader->processed_state)
     return;
@@ -221,22 +222,23 @@ swfdec_loader_process (gpointer loaderp, gpointer unused)
     swfdec_loader_target_error (loader->target, loader);
     return;
   }
-  target = loader->target;
+  g_object_ref (loader);
   while (loader->state != loader->processed_state) {
-    /* stupid reentrancy */
-    if (loader->target != target)
-      break;
     if (loader->processed_state == SWFDEC_LOADER_STATE_NEW) {
-      swfdec_loader_target_open (target, loader);
       loader->processed_state = SWFDEC_LOADER_STATE_OPEN;
+      swfdec_loader_target_open (loader->target, loader);
     } else if (loader->processed_state == SWFDEC_LOADER_STATE_OPEN) {
-      swfdec_loader_target_parse (target, loader);
       loader->processed_state = SWFDEC_LOADER_STATE_READING;
+      swfdec_loader_target_parse (loader->target, loader);
     } else if (loader->processed_state == SWFDEC_LOADER_STATE_READING) {
-      swfdec_loader_target_eof (target, loader);
       loader->processed_state = SWFDEC_LOADER_STATE_EOF;
+      swfdec_loader_target_eof (loader->target, loader);
     }
+    /* stupid reentrancy */
+    if (loader->processed_state == SWFDEC_LOADER_STATE_NEW)
+      break;
   }
+  g_object_unref (loader);
 }
 
 static void
commit 40abab5ecd2d5bee4341aa659472085199faee43
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 17:02:26 2007 +0100

    simplify rswfdec_player_request_unload()
    
    also implement MovieClipLoader.unloadClip with it

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 81fb2fc..627d0d6 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1144,12 +1144,7 @@ swfdec_action_get_url (SwfdecAsContext *cx, guint action, const guint8 *data, gu
     /* nothing to do here */
   } else if (swfdec_player_get_level (SWFDEC_PLAYER (cx), target) >= 0) {
     if (url[0] == '\0') {
-      SwfdecMovie *movie = swfdec_player_get_movie_from_string (SWFDEC_PLAYER (cx), target);
-      if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
-	char *path = swfdec_movie_get_path (movie, TRUE);
-	swfdec_player_request_unload (SWFDEC_PLAYER (cx), path);
-	g_free (path);
-      }
+      swfdec_player_request_unload (SWFDEC_PLAYER (cx), target);
     } else {
       swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, 
 	  SWFDEC_LOADER_REQUEST_DEFAULT, NULL, NULL);
@@ -1197,12 +1192,7 @@ swfdec_action_get_url2 (SwfdecAsContext *cx, guint action, const guint8 *data, g
     }
   } else if (internal) {
     if (url[0] == '\0') {
-      SwfdecMovie *movie = swfdec_player_get_movie_from_string (SWFDEC_PLAYER (cx), target);
-      if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
-	char *path = swfdec_movie_get_path (movie, TRUE);
-	swfdec_player_request_unload (SWFDEC_PLAYER (cx), path);
-	g_free (path);
-      }
+      swfdec_player_request_unload (SWFDEC_PLAYER (cx), target);
     } else {
       swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, method, NULL, NULL);
     }
diff --git a/libswfdec/swfdec_movie_clip_loader.c b/libswfdec/swfdec_movie_clip_loader.c
index 33ff187..bc70765 100644
--- a/libswfdec/swfdec_movie_clip_loader.c
+++ b/libswfdec/swfdec_movie_clip_loader.c
@@ -29,6 +29,7 @@
 #include "swfdec_decoder.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_resource.h"
+#include "swfdec_resource_request.h"
 
 
 G_DEFINE_TYPE (SwfdecMovieClipLoader, swfdec_movie_clip_loader, SWFDEC_TYPE_AS_OBJECT)
@@ -82,7 +83,11 @@ void
 swfdec_movie_clip_loader_unloadClip (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
 {
-  SWFDEC_FIXME ("implement");
+  SwfdecMovieClipLoader *loader;
+  const char *target;
+
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE_CLIP_LOADER, &loader, "s", &target);
+  swfdec_player_request_unload (SWFDEC_PLAYER (cx), target);
 }
 
 SWFDEC_AS_NATIVE (112, 101, swfdec_movie_clip_loader_getProgress)
diff --git a/libswfdec/swfdec_resource_request.c b/libswfdec/swfdec_resource_request.c
index 44db41a..fb9a791 100644
--- a/libswfdec/swfdec_resource_request.c
+++ b/libswfdec/swfdec_resource_request.c
@@ -222,13 +222,17 @@ void
 swfdec_player_request_unload (SwfdecPlayer *player, const char *target)
 {
   SwfdecResourceRequest *request;
+  SwfdecMovie *movie;
 
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
   g_return_if_fail (target != NULL);
 
+  movie = swfdec_player_get_movie_from_string (player, target);
+  if (!SWFDEC_IS_SPRITE_MOVIE (movie))
+    return;
   request = g_slice_new0 (SwfdecResourceRequest);
   request->type = SWFDEC_RESOURCE_REQUEST_UNLOAD;
-  request->target = g_strdup (target);
+  request->target = swfdec_movie_get_path (movie, TRUE);
 
   player->resource_requests = g_slist_append (player->resource_requests, request);
 }
commit 729590ccd5bddf6fca4685078a8b467ae263d226
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 15:21:55 2007 +0100

    add test case for unloadMovie
    
    also tests that onFoo events in Flash <= 5 aren't executed

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 57c8e79..20678a4 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -2187,6 +2187,15 @@ EXTRA_DIST = \
 	unescape2-6.swf.trace \
 	unescape2-7.swf \
 	unescape2-7.swf.trace \
+	unloadmovie-simple.as \
+	unloadmovie-simple-5.swf \
+	unloadmovie-simple-5.swf.trace \
+	unloadmovie-simple-6.swf \
+	unloadmovie-simple-6.swf.trace \
+	unloadmovie-simple-7.swf \
+	unloadmovie-simple-7.swf.trace \
+	unloadmovie-simple-8.swf \
+	unloadmovie-simple-8.swf.trace \
 	unreproducable-random.as \
 	unreproducable-random-5.swf \
 	unreproducable-random-5.swf.trace \
diff --git a/test/trace/unloadmovie-simple-5.swf b/test/trace/unloadmovie-simple-5.swf
new file mode 100644
index 0000000..f9e2792
Binary files /dev/null and b/test/trace/unloadmovie-simple-5.swf differ
diff --git a/test/trace/unloadmovie-simple-5.swf.trace b/test/trace/unloadmovie-simple-5.swf.trace
new file mode 100644
index 0000000..89965ca
--- /dev/null
+++ b/test/trace/unloadmovie-simple-5.swf.trace
@@ -0,0 +1,4 @@
+undefined
+undefined
+undefined
+true
diff --git a/test/trace/unloadmovie-simple-6.swf b/test/trace/unloadmovie-simple-6.swf
new file mode 100644
index 0000000..f45f203
Binary files /dev/null and b/test/trace/unloadmovie-simple-6.swf differ
diff --git a/test/trace/unloadmovie-simple-6.swf.trace b/test/trace/unloadmovie-simple-6.swf.trace
new file mode 100644
index 0000000..73de115
--- /dev/null
+++ b/test/trace/unloadmovie-simple-6.swf.trace
@@ -0,0 +1,12 @@
+_level0.a
+42
+_level0.a.a
+true
+_level0.a
+42
+_level0.a.a
+true
+_level0.a
+undefined
+undefined
+true
diff --git a/test/trace/unloadmovie-simple-7.swf b/test/trace/unloadmovie-simple-7.swf
new file mode 100644
index 0000000..cbe83c2
Binary files /dev/null and b/test/trace/unloadmovie-simple-7.swf differ
diff --git a/test/trace/unloadmovie-simple-7.swf.trace b/test/trace/unloadmovie-simple-7.swf.trace
new file mode 100644
index 0000000..73de115
--- /dev/null
+++ b/test/trace/unloadmovie-simple-7.swf.trace
@@ -0,0 +1,12 @@
+_level0.a
+42
+_level0.a.a
+true
+_level0.a
+42
+_level0.a.a
+true
+_level0.a
+undefined
+undefined
+true
diff --git a/test/trace/unloadmovie-simple-8.swf b/test/trace/unloadmovie-simple-8.swf
new file mode 100644
index 0000000..b8e5a6d
Binary files /dev/null and b/test/trace/unloadmovie-simple-8.swf differ
diff --git a/test/trace/unloadmovie-simple-8.swf.trace b/test/trace/unloadmovie-simple-8.swf.trace
new file mode 100644
index 0000000..73de115
--- /dev/null
+++ b/test/trace/unloadmovie-simple-8.swf.trace
@@ -0,0 +1,12 @@
+_level0.a
+42
+_level0.a.a
+true
+_level0.a
+42
+_level0.a.a
+true
+_level0.a
+undefined
+undefined
+true
diff --git a/test/trace/unloadmovie-simple.as b/test/trace/unloadmovie-simple.as
new file mode 100644
index 0000000..a1df6bf
--- /dev/null
+++ b/test/trace/unloadmovie-simple.as
@@ -0,0 +1,16 @@
+// makeswf -v 7 -s 200x150 -r 1 -o unloadmovie-simple.swf unloadmovie-simple.as
+
+x = createEmptyMovieClip ("a", 1);
+loadMovie ("", a); 
+a.x = 42;
+a.createEmptyMovieClip ("a", 1);
+
+onEnterFrame = function () {
+  trace (a);
+  trace (a.x);
+  trace (a.a);
+  trace (a == x);
+  if (!a.a)
+    loadMovie ("fscommand:QUIT", "");
+};
+onEnterFrame ();
commit 6af94b966fbd37bb415f0e8a8c7223c92f6dbb5a
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 15:20:39 2007 +0100

    don't call MovieClip.onFoo events in Flash <= 5
    
    also add swfdec_movie_get_version () to get a per-movie version.

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 1859971..fefa930 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -360,6 +360,12 @@ swfdec_movie_set_constructor (SwfdecSpriteMovie *movie)
   swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (movie), constructor);
 }
 
+guint
+swfdec_movie_get_version (SwfdecMovie *movie)
+{
+  return SWFDEC_SWF_DECODER (movie->resource->decoder)->version;
+}
+
 void
 swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
 {
@@ -369,7 +375,7 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
 
   /* special cases */
   if (condition == SWFDEC_EVENT_CONSTRUCT) {
-    if (SWFDEC_AS_OBJECT (movie)->context->version <= 5)
+    if (swfdec_movie_get_version (movie) <= 5)
       return;
     swfdec_movie_set_constructor (SWFDEC_SPRITE_MOVIE (movie));
   } else if (condition == SWFDEC_EVENT_ENTER) {
@@ -381,6 +387,9 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
     swfdec_event_list_execute (movie->events, SWFDEC_AS_OBJECT (movie), 
 	SWFDEC_SECURITY (movie->resource), condition, 0);
   }
+  /* FIXME: how do we compute the version correctly here? */
+  if (swfdec_movie_get_version (movie) <= 5)
+    return;
   name = swfdec_event_type_get_name (condition);
   if (name != NULL) {
     swfdec_as_object_call_with_security (SWFDEC_AS_OBJECT (movie), 
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 1bb161a..62abf12 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -241,6 +241,7 @@ void		swfdec_movie_render		(SwfdecMovie *		movie,
 						 cairo_t *		cr, 
 						 const SwfdecColorTransform *trans,
 						 const SwfdecRect *	inval);
+guint		swfdec_movie_get_version	(SwfdecMovie *		movie);
 void		swfdec_movie_execute		(SwfdecMovie *		movie,
 						 SwfdecEventType	condition);
 gboolean      	swfdec_movie_queue_script	(SwfdecMovie *		movie,
commit 4bf31dd22e5766ca65e45b9be24bb50dbb667cd9
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 15:13:20 2007 +0100

    s/swfdec_as_object_clear_variables/swfdec_as_object_delete_all_variables/

diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt
index 0916f16..4a5e12a 100644
--- a/doc/swfdec-sections.txt
+++ b/doc/swfdec-sections.txt
@@ -345,6 +345,7 @@ swfdec_as_object_add_variable
 swfdec_as_object_set_variable_flags
 swfdec_as_object_unset_variable_flags
 swfdec_as_object_delete_variable
+swfdec_as_object_delete_all_variables
 SwfdecAsVariableForeach
 swfdec_as_object_foreach
 swfdec_as_object_has_function
diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 877f6e4..bb4adcc 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -921,13 +921,13 @@ swfdec_as_object_delete_variable (SwfdecAsObject *object, const char *variable)
 }
 
 /**
- * swfdec_as_object_clear_variables:
+ * swfdec_as_object_delete_all_variables:
  * @object: a #SwfdecAsObject
  *
- * Clears all user-set variables from the given object.
+ * Deletes all user-set variables from the given object.
  **/
 void
-swfdec_as_object_clear_variables (SwfdecAsObject *object)
+swfdec_as_object_delete_all_variables (SwfdecAsObject *object)
 {
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
 
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index 8952b72..5c76b3a 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -146,7 +146,8 @@ gboolean	swfdec_as_object_get_variable_and_flags
 SwfdecAsDeleteReturn
 		swfdec_as_object_delete_variable(SwfdecAsObject *	object,
 						 const char *		variable);
-void		swfdec_as_object_clear_variables(SwfdecAsObject *	object);
+void		swfdec_as_object_delete_all_variables
+						(SwfdecAsObject *	object);
 void		swfdec_as_object_set_variable_flags
 						(SwfdecAsObject *       object,
 						 const char *		variable,
diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index 1ae7480..888c160 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -816,7 +816,7 @@ swfdec_sprite_movie_unload (SwfdecSpriteMovie *movie)
   /* FIXME: destroy or unload? */
   while (mov->list)
     swfdec_movie_remove (mov->list->data);
-  swfdec_as_object_clear_variables (SWFDEC_AS_OBJECT (movie));
+  swfdec_as_object_delete_all_variables (SWFDEC_AS_OBJECT (movie));
   movie->frame = (guint) -1;
   movie->n_frames = 0;
   movie->next_action = 0;
commit 525f27cdaa0c2407c8662fa686a5a49005471dae
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 15:10:11 2007 +0100

    implement unloading of movies

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index a1c456c..81fb2fc 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1143,8 +1143,17 @@ swfdec_action_get_url (SwfdecAsContext *cx, guint action, const guint8 *data, gu
   } else if (swfdec_player_request_fscommand (SWFDEC_PLAYER (cx), url, target)) {
     /* nothing to do here */
   } else if (swfdec_player_get_level (SWFDEC_PLAYER (cx), target) >= 0) {
-    swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, 
-	SWFDEC_LOADER_REQUEST_DEFAULT, NULL, NULL);
+    if (url[0] == '\0') {
+      SwfdecMovie *movie = swfdec_player_get_movie_from_string (SWFDEC_PLAYER (cx), target);
+      if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+	char *path = swfdec_movie_get_path (movie, TRUE);
+	swfdec_player_request_unload (SWFDEC_PLAYER (cx), path);
+	g_free (path);
+      }
+    } else {
+      swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, 
+	  SWFDEC_LOADER_REQUEST_DEFAULT, NULL, NULL);
+    }
   }
   g_free (url);
   g_free (target);
@@ -1187,7 +1196,16 @@ swfdec_action_get_url2 (SwfdecAsContext *cx, guint action, const guint8 *data, g
       swfdec_movie_load_variables (movie, url, method, NULL);
     }
   } else if (internal) {
-    swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, method, NULL, NULL);
+    if (url[0] == '\0') {
+      SwfdecMovie *movie = swfdec_player_get_movie_from_string (SWFDEC_PLAYER (cx), target);
+      if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+	char *path = swfdec_movie_get_path (movie, TRUE);
+	swfdec_player_request_unload (SWFDEC_PLAYER (cx), path);
+	g_free (path);
+      }
+    } else {
+      swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, method, NULL, NULL);
+    }
   } else {
     /* load an external file */
     swfdec_player_launch (SWFDEC_PLAYER (cx), method, url, target, NULL);
commit 60446f56d3a006f44b74e27a711f47f99bc614c8
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 15:09:57 2007 +0100

    fix swfdec_sprite_movie_unload()
    
    - remove, not destroy the contained movieclips
    - queue an update

diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index 89d30b4..1ae7480 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -811,18 +811,18 @@ swfdec_sprite_movie_unload (SwfdecSpriteMovie *movie)
   g_return_if_fail (SWFDEC_IS_SPRITE_MOVIE (movie));
 
   mov = SWFDEC_MOVIE (movie);
-  /* This function does enough invalidating */
   swfdec_sprite_movie_clear (SWFDEC_AS_OBJECT (movie)->context, 
       SWFDEC_AS_OBJECT (movie), 0, NULL, &hack);
   /* FIXME: destroy or unload? */
   while (mov->list)
-    swfdec_movie_destroy (mov->list->data);
+    swfdec_movie_remove (mov->list->data);
   swfdec_as_object_clear_variables (SWFDEC_AS_OBJECT (movie));
   movie->frame = (guint) -1;
   movie->n_frames = 0;
   movie->next_action = 0;
   movie->max_action = 0;
   movie->sprite = NULL;
+  swfdec_movie_queue_update (SWFDEC_MOVIE (movie), SWFDEC_MOVIE_INVALID_EXTENTS);
 }
 
 /**
commit 00706fc9836e93250e1e2471de5616167e427a77
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 14:53:10 2007 +0100

    implement UNLOAD request

diff --git a/libswfdec/swfdec_resource_request.c b/libswfdec/swfdec_resource_request.c
index 2cdb4ed..44db41a 100644
--- a/libswfdec/swfdec_resource_request.c
+++ b/libswfdec/swfdec_resource_request.c
@@ -21,11 +21,14 @@
 #include "config.h"
 #endif
 
+#include <string.h>
 #include "swfdec_resource_request.h"
+#include "swfdec_as_interpret.h"
 #include "swfdec_debug.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_resource.h"
+#include "swfdec_sprite_movie.h"
 
 static void
 swfdec_resource_request_free (SwfdecResourceRequest *request)
@@ -41,6 +44,7 @@ swfdec_resource_request_free (SwfdecResourceRequest *request)
     swfdec_buffer_unref (request->buffer);
   g_free (request->command);
   g_free (request->value);
+  g_free (request->target);
   g_slice_free (SwfdecResourceRequest, request);
 }
 
@@ -80,22 +84,30 @@ swfdec_request_resource_perform_fscommand (SwfdecPlayer *player, SwfdecResourceR
 }
 
 static void
-swfdec_request_resource_perform_load(SwfdecPlayer *player, SwfdecResourceRequest *request)
+swfdec_request_resource_perform_load (SwfdecPlayer *player, SwfdecResourceRequest *request)
 {
   SwfdecLoader *loader;
 
   g_assert (player->resource);
-  if (request->url[0] == '\0') {
-    /* special case for unloadMovie */
-    loader = NULL;
-  } else {
-    loader = swfdec_player_request_resource_now (player, request->security, 
-	request->url, request->request, request->buffer);
-  }
+  loader = swfdec_player_request_resource_now (player, request->security, 
+      request->url, request->request, request->buffer);
   request->func (player, loader, request->data);
 }
 
 static void
+swfdec_request_resource_perform_unload (SwfdecPlayer *player, SwfdecResourceRequest *request)
+{
+  SwfdecSpriteMovie *movie = (SwfdecSpriteMovie *) swfdec_action_lookup_object (
+      SWFDEC_AS_CONTEXT (player), player->roots->data, 
+      request->target, request->target + strlen (request->target));
+  if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
+    SWFDEC_DEBUG ("no movie, not emitting signal");
+    return;
+  }
+  swfdec_sprite_movie_unload (movie);
+}
+
+static void
 swfdec_request_resource_perform_one (gpointer requestp, gpointer player)
 {
   SwfdecResourceRequest *request = requestp;
@@ -108,6 +120,8 @@ swfdec_request_resource_perform_one (gpointer requestp, gpointer player)
       swfdec_request_resource_perform_fscommand (player, request);
       break;
     case SWFDEC_RESOURCE_REQUEST_UNLOAD:
+      swfdec_request_resource_perform_unload (player, request);
+      break;
     default:
       g_assert_not_reached ();
       break;
@@ -205,6 +219,21 @@ swfdec_player_request_fscommand (SwfdecPlayer *player, const char *command,
 }
 
 void
+swfdec_player_request_unload (SwfdecPlayer *player, const char *target)
+{
+  SwfdecResourceRequest *request;
+
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+  g_return_if_fail (target != NULL);
+
+  request = g_slice_new0 (SwfdecResourceRequest);
+  request->type = SWFDEC_RESOURCE_REQUEST_UNLOAD;
+  request->target = g_strdup (target);
+
+  player->resource_requests = g_slist_append (player->resource_requests, request);
+}
+
+void
 swfdec_player_resource_request_init (SwfdecPlayer *player)
 {
   /* empty */
diff --git a/libswfdec/swfdec_resource_request.h b/libswfdec/swfdec_resource_request.h
index 09b349f..7cdcc20 100644
--- a/libswfdec/swfdec_resource_request.h
+++ b/libswfdec/swfdec_resource_request.h
@@ -51,6 +51,9 @@ struct _SwfdecResourceRequest
   /* FSCOMMAND */
   char *		command;	/* fscommand to execute */
   char *		value;		/* value to pass to fscommand */
+
+  /* UNLOAD */
+  char *	      	target;		/* the target to unload */
 };
 
 /* public api for swfdec */
@@ -63,14 +66,16 @@ void		swfdec_player_request_resource		(SwfdecPlayer *		player,
 							 SwfdecResourceFunc	func,
 							 gpointer		data,
 							 GDestroyNotify		destroy);
-gboolean	swfdec_player_request_fscommand		(SwfdecPlayer *		player,
-							 const char *		command,
-							 const char *		value);
 SwfdecLoader *	swfdec_player_request_resource_now	(SwfdecPlayer *		player,
 							 SwfdecSecurity *	security,
 							 const char *		url,
 							 SwfdecLoaderRequest	req,
 							 SwfdecBuffer *		buffer);
+void		swfdec_player_request_unload		(SwfdecPlayer *		player,
+							 const char *		target);
+gboolean	swfdec_player_request_fscommand		(SwfdecPlayer *		player,
+							 const char *		command,
+							 const char *		value);
 
 /* private api for swfdec_player.c */
 void		swfdec_player_resource_request_init	(SwfdecPlayer *		player);
commit 64ddbcea881182bd0596121706b098195afcde98
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 9 11:56:55 2007 +0100

    reorganize resource requests a bit, so we can add unload easier

diff --git a/libswfdec/swfdec_resource_request.c b/libswfdec/swfdec_resource_request.c
index 0b67a66..2cdb4ed 100644
--- a/libswfdec/swfdec_resource_request.c
+++ b/libswfdec/swfdec_resource_request.c
@@ -39,6 +39,8 @@ swfdec_resource_request_free (SwfdecResourceRequest *request)
   g_free (request->url);
   if (request->buffer)
     swfdec_buffer_unref (request->buffer);
+  g_free (request->command);
+  g_free (request->value);
   g_slice_free (SwfdecResourceRequest, request);
 }
 
@@ -72,21 +74,44 @@ swfdec_player_request_resource_now (SwfdecPlayer *player, SwfdecSecurity *securi
 }
 
 static void
-swfdec_request_resource_perform_one (gpointer requestp, gpointer playerp)
+swfdec_request_resource_perform_fscommand (SwfdecPlayer *player, SwfdecResourceRequest *request)
+{
+  g_signal_emit_by_name (player, "fscommand", request->command, request->value);
+}
+
+static void
+swfdec_request_resource_perform_load(SwfdecPlayer *player, SwfdecResourceRequest *request)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (playerp);
-  SwfdecResourceRequest *request = requestp;
   SwfdecLoader *loader;
 
-  if (request->security == NULL) {
-    g_signal_emit_by_name (player, "fscommand", request->url, request->data);
-    swfdec_resource_request_free (request);
-    return;
-  }
   g_assert (player->resource);
-  loader = swfdec_player_request_resource_now (player, request->security, 
-      request->url, request->request, request->buffer);
+  if (request->url[0] == '\0') {
+    /* special case for unloadMovie */
+    loader = NULL;
+  } else {
+    loader = swfdec_player_request_resource_now (player, request->security, 
+	request->url, request->request, request->buffer);
+  }
   request->func (player, loader, request->data);
+}
+
+static void
+swfdec_request_resource_perform_one (gpointer requestp, gpointer player)
+{
+  SwfdecResourceRequest *request = requestp;
+
+  switch (request->type) {
+    case SWFDEC_RESOURCE_REQUEST_LOAD:
+      swfdec_request_resource_perform_load (player, request);
+      break;
+    case SWFDEC_RESOURCE_REQUEST_FSCOMMAND:
+      swfdec_request_resource_perform_fscommand (player, request);
+      break;
+    case SWFDEC_RESOURCE_REQUEST_UNLOAD:
+    default:
+      g_assert_not_reached ();
+      break;
+  }
   swfdec_resource_request_free (request);
 }
 
@@ -116,6 +141,7 @@ swfdec_player_request_resource (SwfdecPlayer *player, SwfdecSecurity *security,
   g_return_if_fail (func != NULL);
 
   request = g_slice_new0 (SwfdecResourceRequest);
+  request->type = SWFDEC_RESOURCE_REQUEST_LOAD;
   request->security = g_object_ref (security);
   request->url = g_strdup (url);
   request->request = req;
@@ -170,9 +196,9 @@ swfdec_player_request_fscommand (SwfdecPlayer *player, const char *command,
     return TRUE;
   }
   request = g_slice_new0 (SwfdecResourceRequest);
-  request->url = g_ascii_strdown (command, -1);
-  request->destroy = g_free;
-  request->data = g_strdup (value);
+  request->type = SWFDEC_RESOURCE_REQUEST_FSCOMMAND;
+  request->command = g_ascii_strdown (command, -1);
+  request->value = g_strdup (value);
 
   player->resource_requests = g_slist_append (player->resource_requests, request);
   return TRUE;
diff --git a/libswfdec/swfdec_resource_request.h b/libswfdec/swfdec_resource_request.h
index bb6669f..09b349f 100644
--- a/libswfdec/swfdec_resource_request.h
+++ b/libswfdec/swfdec_resource_request.h
@@ -28,17 +28,29 @@ G_BEGIN_DECLS
 typedef struct _SwfdecResourceRequest SwfdecResourceRequest;
 typedef void (* SwfdecResourceFunc) (SwfdecPlayer *player, SwfdecLoader *loader, gpointer data);
 
+typedef enum {
+  SWFDEC_RESOURCE_REQUEST_LOAD,
+  SWFDEC_RESOURCE_REQUEST_FSCOMMAND,
+  SWFDEC_RESOURCE_REQUEST_UNLOAD
+} SwfdecResourceRequestType;
+
+/* FIXME: make this a union? */
 struct _SwfdecResourceRequest
 {
-  SwfdecSecurity *	security;     	/* security context when loading or NULL for fscommand */
+  SwfdecResourceRequestType	type;	/* type of request */
 
+  /* LOAD */
+  SwfdecSecurity *	security;     	/* security context when loading or NULL for fscommand */
   char *		url;		/* URL we're gonna load */
   SwfdecLoaderRequest	request;	/* how are we goona load this URL? */
   SwfdecBuffer *	buffer;		/* data to pass to load request or NULL */
-
   SwfdecResourceFunc	func;		/* function to call when we got a loader (or an error) */
   GDestroyNotify	destroy;	/* function to call on player dispose */
   gpointer		data;		/* function to pass to the above functions */
+
+  /* FSCOMMAND */
+  char *		command;	/* fscommand to execute */
+  char *		value;		/* value to pass to fscommand */
 };
 
 /* public api for swfdec */
commit 1ad2ae5c003a52ff357e8fa0e2ae65ca49cc5fae
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 8 22:54:16 2007 +0100

    this is tested, no need for fixme messages

diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index 9983642..9a23d27 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -120,7 +120,7 @@ swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolea
   movie = swfdec_action_lookup_object (cx, SWFDEC_PLAYER (cx)->roots->data, 
       resource->target, resource->target + strlen (resource->target));
   if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
-    SWFDEC_FIXME ("figure out if we emit nonetheless");
+    SWFDEC_DEBUG ("no movie, not emitting signal");
     return NULL;
   }
 


More information about the Swfdec mailing list