[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