[Swfdec] libswfdec/swfdec_load_object.c libswfdec/swfdec_movie.c libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_resource.c libswfdec/swfdec_resource.h

Benjamin Otte company at kemper.freedesktop.org
Thu Nov 8 01:18:42 PST 2007


 libswfdec/swfdec_load_object.c     |    5 -
 libswfdec/swfdec_movie.c           |    2 
 libswfdec/swfdec_player.c          |  126 +++++++++++++++++++++++++------------
 libswfdec/swfdec_player_internal.h |    6 +
 libswfdec/swfdec_resource.c        |  117 +++++++++++++++++-----------------
 libswfdec/swfdec_resource.h        |    6 -
 6 files changed, 158 insertions(+), 104 deletions(-)

New commits:
commit 6388c7fda57910e62bd1aa307f82842a2f13af27
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 8 10:14:55 2007 +0100

    lots of reorg to make resources load correctly
    
    sorry, big patch again :(

diff --git a/libswfdec/swfdec_load_object.c b/libswfdec/swfdec_load_object.c
index 838b756..56333b3 100644
--- a/libswfdec/swfdec_load_object.c
+++ b/libswfdec/swfdec_load_object.c
@@ -74,6 +74,8 @@ swfdec_load_object_ondata (SwfdecLoadObject *load_object)
   }
   swfdec_as_object_call (load_object->target, SWFDEC_AS_STR_onData, 1, &val,
       NULL);
+  swfdec_player_unroot_object (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (load_object)->context), 
+      G_OBJECT (load_object));
 }
 
 static void
@@ -256,8 +258,7 @@ swfdec_load_object_new (SwfdecAsObject *target, const char *url,
   if (!swfdec_load_object_load (SWFDEC_LOAD_OBJECT (load_object), url, request, data))
     return NULL;
 
-  SWFDEC_PLAYER (target->context)->load_objects =
-    g_list_append (SWFDEC_PLAYER (target->context)->load_objects, load_object);
+  swfdec_player_root_object (SWFDEC_PLAYER (target->context), G_OBJECT (load_object));
 
   return load_object;
 }
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index a223e97..9c028a1 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -1303,7 +1303,7 @@ swfdec_movie_new (SwfdecPlayer *player, int depth, SwfdecMovie *parent, SwfdecRe
   /* only setup here, the resource assumes it can access the player via the movie */
   if (resource->movie == NULL) {
     g_assert (SWFDEC_IS_SPRITE_MOVIE (movie));
-    swfdec_resource_set_movie (resource, SWFDEC_SPRITE_MOVIE (movie));
+    resource->movie = SWFDEC_SPRITE_MOVIE (movie);
   }
   return movie;
 }
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 3d36451..4d7e723 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -887,7 +887,8 @@ swfdec_player_dispose (GObject *object)
   }
   g_assert (player->timeouts == NULL);
   g_list_free (player->intervals);
-  g_list_free (player->load_objects);
+  while (player->rooted_objects)
+    swfdec_player_unroot_object (player, player->rooted_objects->data);
   player->intervals = NULL;
   swfdec_cache_unref (player->cache);
   if (player->system) {
@@ -1374,6 +1375,16 @@ swfdec_player_mark_string_object (gpointer key, gpointer value, gpointer data)
 }
 
 static void
+swfdec_player_mark_rooted_object (gpointer object, gpointer unused)
+{
+  if (SWFDEC_IS_RESOURCE (object)) {
+    swfdec_resource_mark (object);
+  } else if (SWFDEC_IS_AS_OBJECT (object)) {
+    swfdec_as_object_mark (object);
+  }
+}
+
+static void
 swfdec_player_mark (SwfdecAsContext *context)
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (context);
@@ -1383,7 +1394,7 @@ swfdec_player_mark (SwfdecAsContext *context)
   swfdec_as_object_mark (player->Video);
   g_list_foreach (player->roots, (GFunc) swfdec_as_object_mark, NULL);
   g_list_foreach (player->intervals, (GFunc) swfdec_as_object_mark, NULL);
-  g_list_foreach (player->load_objects, (GFunc) swfdec_as_object_mark, NULL);
+  g_list_foreach (player->rooted_objects, swfdec_player_mark_rooted_object, NULL);
 
   SWFDEC_AS_CONTEXT_CLASS (swfdec_player_parent_class)->mark (context);
 }
@@ -1870,50 +1881,56 @@ void
 swfdec_player_initialize (SwfdecPlayer *player, guint version, 
     guint rate, guint width, guint height)
 {
-  SwfdecAsContext *context;
-
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
-
-  if (swfdec_player_is_initialized (player))
-    return;
-  
-  context = SWFDEC_AS_CONTEXT (player);
-  swfdec_as_context_startup (context, version);
-  /* reset state for initialization */
-  /* FIXME: have a better way to do this */
-  if (context->state == SWFDEC_AS_CONTEXT_RUNNING) {
-    context->state = SWFDEC_AS_CONTEXT_NEW;
-    swfdec_sprite_movie_init_context (player, version);
-    swfdec_video_movie_init_context (player, version);
-    swfdec_net_connection_init_context (player, version);
-    swfdec_net_stream_init_context (player, version);
-
-    swfdec_as_context_run_init_script (context, swfdec_initialize, 
-	sizeof (swfdec_initialize), 8);
-
-    if (context->state == SWFDEC_AS_CONTEXT_NEW) {
-      context->state = SWFDEC_AS_CONTEXT_RUNNING;
-      swfdec_as_object_set_constructor (player->roots->data, player->MovieClip);
+  g_return_if_fail (rate > 0);
+
+  if (!player->initialized) {
+    SwfdecAsContext *context = SWFDEC_AS_CONTEXT (player);
+    swfdec_as_context_startup (context, version);
+    /* reset state for initialization */
+    /* FIXME: have a better way to do this */
+    if (context->state == SWFDEC_AS_CONTEXT_RUNNING) {
+      context->state = SWFDEC_AS_CONTEXT_NEW;
+      swfdec_sprite_movie_init_context (player, version);
+      swfdec_video_movie_init_context (player, version);
+      swfdec_net_connection_init_context (player, version);
+      swfdec_net_stream_init_context (player, version);
+
+      swfdec_as_context_run_init_script (context, swfdec_initialize, 
+	  sizeof (swfdec_initialize), 8);
+
+      if (context->state == SWFDEC_AS_CONTEXT_NEW) {
+	context->state = SWFDEC_AS_CONTEXT_RUNNING;
+	swfdec_as_object_set_constructor (player->roots->data, player->MovieClip);
+      }
     }
+    player->initialized = TRUE;
+    g_object_notify (G_OBJECT (player), "initialized");
+  } else {
+    swfdec_player_remove_timeout (player, &player->iterate_timeout);
   }
+
   SWFDEC_INFO ("initializing player to size %ux%u and rate %u/256", width, height, rate);
-  player->rate = rate;
-  player->width = width;
-  player->height = height;
+  if (rate != player->rate) {
+    player->rate = rate;
+    g_object_notify (G_OBJECT (player), "rate");
+  }
+  if (player->width != width) {
+    player->width = width;
+    g_object_notify (G_OBJECT (player), "default-width");
+  }
+  if (player->height != height) {
+    player->height = height;
+    g_object_notify (G_OBJECT (player), "default-height");
+  }
   player->internal_width = player->stage_width >= 0 ? (guint) player->stage_width : player->width;
   player->internal_height = player->stage_height >= 0 ? (guint) player->stage_height : player->height;
-  player->initialized = TRUE;
-  if (rate) {
-    player->iterate_timeout.timestamp = player->time;
-    swfdec_player_add_timeout (player, &player->iterate_timeout);
-    SWFDEC_LOG ("initialized iterate timeout %p to %"G_GUINT64_FORMAT" (now %"G_GUINT64_FORMAT")",
-	&player->iterate_timeout, player->iterate_timeout.timestamp, player->time);
-  }
-  g_object_notify (G_OBJECT (player), "initialized");
-  g_object_notify (G_OBJECT (player), "default-width");
-  g_object_notify (G_OBJECT (player), "default-height");
-  g_object_notify (G_OBJECT (player), "rate");
   swfdec_player_update_scale (player);
+
+  player->iterate_timeout.timestamp = player->time;
+  swfdec_player_add_timeout (player, &player->iterate_timeout);
+  SWFDEC_LOG ("initialized iterate timeout %p to %"G_GUINT64_FORMAT" (now %"G_GUINT64_FORMAT")",
+      &player->iterate_timeout, player->iterate_timeout.timestamp, player->time);
 }
 
 /**
@@ -1962,6 +1979,34 @@ swfdec_player_set_export_class (SwfdecPlayer *player, const char *name, SwfdecAs
   }
 }
 
+/* FIXME:
+ * I don't like the idea of rooting arbitrary objects very much. And so far, 
+ * this API is only necessary for the objects used for loading data. So it seems
+ * like a good idea to revisit the refcounting and GCing of resources.
+ */
+void
+swfdec_player_root_object (SwfdecPlayer *player, GObject *object)
+{
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+  g_return_if_fail (G_IS_OBJECT (object));
+
+  g_object_ref (object);
+  player->rooted_objects = g_list_prepend (player->rooted_objects, object);
+}
+
+void
+swfdec_player_unroot_object (SwfdecPlayer *player, GObject *object)
+{
+  GList *entry;
+
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+  g_return_if_fail (G_IS_OBJECT (object));
+  entry = g_list_find (player->rooted_objects, object);
+  g_return_if_fail (entry != NULL);
+  g_object_unref (object);
+  player->rooted_objects = g_list_delete_link (player->rooted_objects, entry);
+}
+
 /** PUBLIC API ***/
 
 /**
@@ -2026,7 +2071,7 @@ swfdec_player_set_loader_with_variables (SwfdecPlayer *player, SwfdecLoader *loa
   g_return_if_fail (player->resource == NULL);
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
 
-  player->resource = swfdec_resource_new (loader, variables);
+  player->resource = swfdec_resource_new (player, loader, variables);
   movie = swfdec_movie_new (player, -16384, NULL, player->resource, NULL, SWFDEC_AS_STR__level0);
   movie->name = SWFDEC_AS_STR_EMPTY;
   g_object_unref (loader);
@@ -2597,3 +2642,4 @@ swfdec_player_set_maximum_runtime (SwfdecPlayer *player, gulong msecs)
   player->max_runtime = msecs;
   g_object_notify (G_OBJECT (player), "max-runtime");
 }
+
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index 91f48f9..a30433a 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -61,7 +61,7 @@ struct _SwfdecPlayer
   guint			width;			/* width of movie */
   guint			height;			/* height of movie */
   GList *		roots;			/* all the root movies */
-  GList *		load_objects;		/* all the load objects */
+  GList *		rooted_objects;		/* all the objects we keep track of */
   GSList *		resource_requests;	/* all external requested URIs - see swfdec_resource_request.[ch] */
   SwfdecCache *		cache;			/* player cache */
   gboolean		bgcolor_set;		/* TRUE if the background color has been set */
@@ -161,6 +161,10 @@ void		swfdec_player_unlock		(SwfdecPlayer *		player);
 void		swfdec_player_unlock_soft	(SwfdecPlayer *		player);
 void		swfdec_player_perform_actions	(SwfdecPlayer *		player);
 
+void		swfdec_player_root_object	(SwfdecPlayer *		player,
+						 GObject *		object);
+void		swfdec_player_unroot_object	(SwfdecPlayer *		player,
+						 GObject *		object);
 SwfdecAsObject *swfdec_player_get_export_class	(SwfdecPlayer *		player,
 						 const char *		name);
 void		swfdec_player_set_export_class	(SwfdecPlayer *		player,
diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index 18abce4..ddb170e 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -53,18 +53,15 @@ G_DEFINE_TYPE_WITH_CODE (SwfdecResource, swfdec_resource, SWFDEC_TYPE_FLASH_SECU
 static gboolean 
 swfdec_resource_is_root (SwfdecResource *resource)
 {
-  SwfdecPlayer *player;
-
   g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource), FALSE);
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource->movie)->context);
-  return resource->movie == player->roots->data;
+  return resource->movie == resource->player->roots->data;
 }
 
 static SwfdecPlayer *
 swfdec_resource_loader_target_get_player (SwfdecLoaderTarget *target)
 {
-  return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (SWFDEC_RESOURCE (target)->movie)->context);
+  return SWFDEC_RESOURCE (target)->player;
 }
 
 static void
@@ -158,12 +155,60 @@ swfdec_resource_emit_error (SwfdecResource *resource, const char *message)
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadError, FALSE, vals, 2);
 }
 
+static gboolean
+swfdec_resource_create_movie (SwfdecResource *resource)
+{
+  SwfdecPlayer *player;
+  SwfdecSpriteMovie *movie;
+  int level = -1;
+
+  if (resource->movie)
+    return TRUE;
+  player = resource->player;
+  movie = (SwfdecSpriteMovie *) swfdec_action_lookup_object (SWFDEC_AS_CONTEXT (player),
+      player->roots->data, resource->target, resource->target + strlen (resource->target));
+  if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
+    level = swfdec_player_get_level (player, resource->target);
+    if (level < 0) {
+      SWFDEC_WARNING ("%s does not reference a movie, not loading %s", resource->target,
+	  swfdec_url_get_url (swfdec_loader_get_url (resource->loader)));
+      swfdec_loader_close (resource->loader);
+      swfdec_player_unroot_object (player, G_OBJECT (resource));
+      return FALSE;
+    }
+    movie = swfdec_player_get_movie_at_level (player, level);
+  }
+  if (movie == NULL) {
+    movie = swfdec_player_create_movie_at_level (player, resource, level);
+  } else {
+    /* can't use swfdec_movie_duplicate() here, we copy to same depth */
+    SwfdecMovie *mov = SWFDEC_MOVIE (movie);
+    SwfdecMovie *copy;
+    
+    copy = swfdec_movie_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), 
+	mov->depth, mov->parent, resource, NULL, mov->name);
+    if (copy == NULL)
+      return FALSE;
+    copy->original_name = mov->original_name;
+    /* FIXME: are events copied? If so, wouldn't that be a security issue? */
+    swfdec_movie_set_static_properties (copy, &mov->original_transform,
+	&mov->original_ctrans, mov->original_ratio, mov->clip_depth, 
+	mov->blend_mode, NULL);
+    swfdec_movie_remove (mov);
+    movie = SWFDEC_SPRITE_MOVIE (copy);
+  }
+  swfdec_player_unroot_object (player, G_OBJECT (resource));
+  return TRUE;
+}
+
 static void
 swfdec_resource_loader_target_open (SwfdecLoaderTarget *target, SwfdecLoader *loader)
 {
   SwfdecResource *instance = SWFDEC_RESOURCE (target);
   const char *query;
 
+  if (!swfdec_resource_create_movie (instance))
+    return;
   query = swfdec_url_get_query (swfdec_loader_get_url (loader));
   if (query) {
     SWFDEC_INFO ("set url query movie variables: %s", query);
@@ -181,7 +226,6 @@ static void
 swfdec_resource_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *loader)
 {
   SwfdecResource *instance = SWFDEC_RESOURCE (target);
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (instance->movie)->context);
   SwfdecBuffer *buffer;
   SwfdecDecoder *dec = instance->decoder;
   SwfdecDecoderClass *klass;
@@ -192,7 +236,7 @@ swfdec_resource_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *l
     if (swfdec_buffer_queue_get_depth (loader->queue) < SWFDEC_DECODER_DETECT_LENGTH)
       return;
     buffer = swfdec_buffer_queue_peek (loader->queue, 4);
-    dec = swfdec_decoder_new (player, buffer);
+    dec = swfdec_decoder_new (instance->player, buffer);
     swfdec_buffer_unref (buffer);
     if (dec == NULL) {
       SWFDEC_ERROR ("no decoder found");
@@ -234,8 +278,9 @@ swfdec_resource_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *l
       swfdec_loader_set_target (loader, NULL);
       return;
     }
-    if (status & SWFDEC_STATUS_INIT) {
-      swfdec_player_initialize (player, 
+    if ((status & SWFDEC_STATUS_INIT) &&
+	swfdec_resource_is_root (instance)) {
+      swfdec_player_initialize (instance->player, 
 	  SWFDEC_IS_SWF_DECODER (dec) ? SWFDEC_SWF_DECODER (dec)->version : 7, /* <-- HACK */
 	  dec->rate, dec->width, dec->height);
     }
@@ -344,39 +389,29 @@ swfdec_resource_set_loader (SwfdecResource *resource, SwfdecLoader *loader)
   g_return_if_fail (resource->loader == NULL);
 
   resource->loader = g_object_ref (loader);
+  swfdec_loader_set_target (resource->loader, SWFDEC_LOADER_TARGET (resource));
   swfdec_flash_security_set_url (SWFDEC_FLASH_SECURITY (resource),
       swfdec_loader_get_url (loader));
   resource->state = SWFDEC_RESOURCE_REQUESTED;
 }
 
 SwfdecResource *
-swfdec_resource_new (SwfdecLoader *loader, const char *variables)
+swfdec_resource_new (SwfdecPlayer *player, SwfdecLoader *loader, const char *variables)
 {
   SwfdecResource *resource;
 
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
   g_return_val_if_fail (SWFDEC_IS_LOADER (loader), NULL);
 
   resource = g_object_new (SWFDEC_TYPE_RESOURCE, NULL);
-  /* set important variables */
+  resource->player = player;
   resource->variables = g_strdup (variables);
-  /* set loader (that depends on those vars) */
   swfdec_resource_set_loader (resource, loader);
 
   return resource;
 }
 
 void
-swfdec_resource_set_movie (SwfdecResource *resource, SwfdecSpriteMovie *movie)
-{
-  g_return_if_fail (SWFDEC_IS_RESOURCE (resource));
-  g_return_if_fail (resource->movie == NULL);
-  g_return_if_fail (SWFDEC_IS_SPRITE_MOVIE (movie));
-
-  resource->movie = movie;
-  swfdec_loader_set_target (resource->loader, SWFDEC_LOADER_TARGET (resource));
-}
-
-void
 swfdec_resource_mark (SwfdecResource *resource)
 {
   g_return_if_fail (SWFDEC_IS_RESOURCE (resource));
@@ -418,48 +453,14 @@ static void
 swfdec_resource_do_load (SwfdecPlayer *player, SwfdecLoader *loader, gpointer resourcep)
 {
   SwfdecResource *resource = SWFDEC_RESOURCE (resourcep);
-  SwfdecSpriteMovie *movie;
-  int level = -1;
 
   if (loader == NULL) {
     /* *** Security Sandbox Violation *** */
     swfdec_resource_emit_error (resource, SWFDEC_AS_STR_IllegalRequest);
     return;
   }
-
-  movie = (SwfdecSpriteMovie *) swfdec_action_lookup_object (SWFDEC_AS_CONTEXT (player),
-      player->roots->data, resource->target, resource->target + strlen (resource->target));
   swfdec_resource_set_loader (resource, loader);
-  if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
-    level = swfdec_player_get_level (player, resource->target);
-    if (level < 0) {
-      SWFDEC_WARNING ("%s does not reference a movie, not loading %s", resource->target,
-	  swfdec_url_get_url (swfdec_loader_get_url (loader)));
-      swfdec_loader_close (loader);
-    }
-    movie = swfdec_player_get_movie_at_level (player, level);
-  }
-  if (movie == NULL) {
-    movie = swfdec_player_create_movie_at_level (player, resource, level);
-  } else {
-    /* can't use swfdec_movie_duplicate() here, we copy to same depth */
-    SwfdecMovie *mov = SWFDEC_MOVIE (movie);
-    SwfdecMovie *copy;
-    
-    copy = swfdec_movie_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), 
-	mov->depth, mov->parent, resource, NULL, mov->name);
-    if (copy == NULL)
-      return;
-    copy->original_name = mov->original_name;
-    /* FIXME: are events copied? If so, wouldn't that be a security issue? */
-    swfdec_movie_set_static_properties (copy, &mov->original_transform,
-	&mov->original_ctrans, mov->original_ratio, mov->clip_depth, 
-	mov->blend_mode, NULL);
-    swfdec_movie_remove (mov);
-    movie = SWFDEC_SPRITE_MOVIE (copy);
-  }
   g_object_unref (loader);
-  return;
 }
 
 /* NB: must be called from a script */
@@ -487,9 +488,11 @@ swfdec_resource_load (SwfdecPlayer *player, const char *target, const char *url,
     return;
   }
   resource = g_object_new (SWFDEC_TYPE_RESOURCE, NULL);
+  resource->player = player;
   resource->target = path;
   if (loader)
     resource->clip_loader = g_object_ref (loader);
+  swfdec_player_root_object (player, G_OBJECT (resource));
   swfdec_player_request_resource (player, SWFDEC_AS_CONTEXT (player)->frame->security, 
       url, request, buffer, swfdec_resource_do_load, resource, g_object_unref);
 }
diff --git a/libswfdec/swfdec_resource.h b/libswfdec/swfdec_resource.h
index b75d77d..ecc80ab 100644
--- a/libswfdec/swfdec_resource.h
+++ b/libswfdec/swfdec_resource.h
@@ -47,6 +47,7 @@ struct _SwfdecResource
 {
   SwfdecFlashSecurity	flash_security;
 
+  SwfdecPlayer *	player;		/* player we belong to */
   SwfdecSpriteMovie * 	movie;		/* the movie responsible for creating this instance */
   guint			parse_frame;	/* next frame to parse */
 
@@ -70,10 +71,9 @@ struct _SwfdecResourceClass
 
 GType		swfdec_resource_get_type	  	(void);
 
-SwfdecResource *swfdec_resource_new			(SwfdecLoader *		loader,
+SwfdecResource *swfdec_resource_new			(SwfdecPlayer *		player,
+							 SwfdecLoader *		loader,
 							 const char *		variables);
-void		swfdec_resource_set_movie		(SwfdecResource *	resource,
-							 SwfdecSpriteMovie *	movie);
 void		swfdec_resource_mark			(SwfdecResource *	resource);
 
 void		swfdec_resource_add_export		(SwfdecResource *	instance,


More information about the Swfdec mailing list