Benjamin Otte
2007-Nov-08 09:18 UTC
[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
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,
Apparently Analagous Threads
- 3 commits - libswfdec/Makefile.am libswfdec/swfdec_as_interpret.c libswfdec/swfdec_loader.c libswfdec/swfdec_loader_internal.h libswfdec/swfdec_load_object_as.c libswfdec/swfdec_load_object.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_player.c
- libswfdec-gtk/swfdec_gtk_player.c libswfdec/swfdec_as_date.c libswfdec/swfdec_audio.c libswfdec/swfdec_audio_event.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_interval.c libswfdec/swfdec_key_as.c libswfdec/swfdec_mouse_as.c libswfdec/swfdec_movie.c
- 7 commits - doc/swfdec-sections.txt libswfdec-gtk/swfdec_gtk_widget.c libswfdec/swfdec_as_strings.c libswfdec/swfdec_decoder.c libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_movie_asprops.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_player.c
- 18 commits - doc/swfdec-sections.txt libswfdec/Makefile.am libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_strings.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_event.c libswfdec/swfdec_event.h libswfdec/swfdec_flash_security.c
- 5 commits - libswfdec/swfdec_net_stream.c libswfdec/swfdec_player.c libswfdec/swfdec_resource.c libswfdec/swfdec_resource.h player/swfdec_slow_loader.c test/trace