2 * Copyright (C) 2006-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
27 #include "swfdec_resource.h"
28 #include "swfdec_access.h"
29 #include "swfdec_as_object.h"
30 #include "swfdec_as_internal.h"
31 #include "swfdec_as_interpret.h"
32 #include "swfdec_as_strings.h"
33 #include "swfdec_character.h"
34 #include "swfdec_debug.h"
35 #include "swfdec_decoder.h"
36 #include "swfdec_image_decoder.h"
37 #include "swfdec_loader_internal.h"
38 #include "swfdec_movie_clip_loader.h"
39 #include "swfdec_player_internal.h"
40 #include "swfdec_sandbox.h"
41 #include "swfdec_script.h"
42 #include "swfdec_sprite.h"
43 #include "swfdec_stream_target.h"
44 #include "swfdec_swf_decoder.h"
45 #include "swfdec_utils.h"
48 static void swfdec_resource_stream_target_init (SwfdecStreamTargetInterface
*iface
);
49 G_DEFINE_TYPE_WITH_CODE (SwfdecResource
, swfdec_resource
, SWFDEC_TYPE_GC_OBJECT
,
50 G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_STREAM_TARGET
, swfdec_resource_stream_target_init
))
52 /*** SWFDEC_STREAM_TARGET interface ***/
55 swfdec_resource_is_root (SwfdecResource
*resource
)
57 g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource
), FALSE
);
60 resource
== SWFDEC_MOVIE (SWFDEC_PLAYER (swfdec_gc_object_get_context (resource
))->priv
->roots
->data
)->resource
;
64 swfdec_resource_stream_target_get_player (SwfdecStreamTarget
*target
)
66 return SWFDEC_PLAYER (swfdec_gc_object_get_context (target
));
70 swfdec_resource_stream_target_image (SwfdecResource
*instance
)
72 SwfdecPlayer
*player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (instance
));
73 SwfdecSpriteMovie
*movie
= (SwfdecSpriteMovie
*) SWFDEC_AS_VALUE_GET_MOVIE (&instance
->movie
);
75 if (!SWFDEC_IS_SPRITE_MOVIE (movie
) || movie
->sprite
!= NULL
)
78 if (SWFDEC_IS_SWF_DECODER (instance
->decoder
)) {
79 SwfdecSwfDecoder
*dec
= SWFDEC_SWF_DECODER (instance
->decoder
);
80 SwfdecSandbox
*old_sandbox
;
82 old_sandbox
= instance
->sandbox
;
83 instance
->sandbox
= swfdec_sandbox_get_for_url (player
,
84 swfdec_loader_get_url (instance
->loader
), instance
->version
,
85 SWFDEC_SWF_DECODER (instance
->decoder
)->use_network
);
86 if (instance
->sandbox
) {
87 movie
->sprite
= dec
->main_sprite
;
88 g_assert (movie
->sprite
->parse_frame
> 0);
89 movie
->n_frames
= movie
->sprite
->n_frames
;
90 swfdec_movie_invalidate_last (SWFDEC_MOVIE (movie
));
91 swfdec_sandbox_use (instance
->sandbox
);
92 swfdec_as_object_set_constructor_by_name (swfdec_as_relay_get_as_object (
93 SWFDEC_AS_RELAY (movie
)), SWFDEC_AS_STR_MovieClip
, NULL
);
94 swfdec_sandbox_unuse (instance
->sandbox
);
95 if (swfdec_resource_is_root (instance
)) {
96 swfdec_player_start_ticking (player
);
97 swfdec_movie_initialize (SWFDEC_MOVIE (movie
));
98 swfdec_player_perform_actions (player
);
101 SWFDEC_FIXME ("cannot continue loading %s, invalid rights",
102 swfdec_url_get_url (swfdec_loader_get_url (instance
->loader
)));
103 swfdec_stream_set_target (SWFDEC_STREAM (instance
->loader
), NULL
);
104 instance
->sandbox
= old_sandbox
;
105 /* FIXME: anyting else on the movie we need to clear? */
108 g_assert_not_reached ();
112 /* NB: name must be GC'ed */
114 swfdec_resource_emit_signal (SwfdecResource
*resource
, const char *name
, gboolean progress
,
115 SwfdecAsValue
*args
, guint n_args
)
119 guint skip
= progress
? 4 : 2;
120 SwfdecAsValue vals
[n_args
+ skip
];
122 if (resource
->clip_loader
== NULL
)
124 cx
= swfdec_gc_object_get_context (resource
->clip_loader
);
126 SWFDEC_AS_VALUE_SET_STRING (&vals
[0], name
);
127 if (SWFDEC_AS_VALUE_IS_MOVIE (&resource
->movie
)) {
128 movie
= SWFDEC_AS_VALUE_GET_MOVIE (&resource
->movie
);
130 SWFDEC_DEBUG ("no movie, not emitting signal");
133 if (name
== SWFDEC_AS_STR_onLoadInit
&&
134 movie
->as_value
!= SWFDEC_AS_VALUE_GET_VALUE (&resource
->movie
)) {
135 SWFDEC_INFO ("not emitting onLoadInit - the movie is different");
138 SWFDEC_AS_VALUE_SET_MOVIE (&vals
[1], movie
);
140 SWFDEC_AS_VALUE_SET_UNDEFINED (&vals
[1]);
146 if (SWFDEC_IS_MOVIE (movie
))
147 res
= swfdec_movie_get_own_resource (SWFDEC_MOVIE (movie
));
150 if (res
&& res
->decoder
) {
151 SwfdecDecoder
*dec
= res
->decoder
;
152 swfdec_as_value_set_integer (cx
, &vals
[2], dec
->bytes_loaded
);
153 swfdec_as_value_set_integer (cx
, &vals
[3], dec
->bytes_total
);
155 swfdec_as_value_set_integer (cx
, &vals
[2], 0);
156 swfdec_as_value_set_integer (cx
, &vals
[3], 0);
160 memcpy (&vals
[skip
], args
, sizeof (SwfdecAsValue
) * n_args
);
161 /* FIXME: what's the correct sandbox here? */
162 swfdec_sandbox_use (resource
->clip_loader_sandbox
);
163 swfdec_as_relay_call (SWFDEC_AS_RELAY (resource
->clip_loader
), SWFDEC_AS_STR_broadcastMessage
,
164 n_args
+ skip
, vals
, NULL
);
165 swfdec_sandbox_unuse (resource
->clip_loader_sandbox
);
169 swfdec_resource_emit_error (SwfdecResource
*resource
, const char *message
)
171 SwfdecAsValue vals
[2];
173 SWFDEC_AS_VALUE_SET_STRING (&vals
[0], message
);
174 swfdec_as_value_set_integer (swfdec_gc_object_get_context (resource
), &vals
[1], 0);
176 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadError
, FALSE
, vals
, 2);
179 static SwfdecSpriteMovie
*
180 swfdec_resource_replace_movie (SwfdecSpriteMovie
*movie
, SwfdecResource
*resource
)
182 /* can't use swfdec_movie_duplicate() here, we copy to same depth */
183 SwfdecMovie
*mov
= SWFDEC_MOVIE (movie
);
186 copy
= swfdec_movie_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie
)),
187 mov
->depth
, mov
->parent
, resource
, NULL
, mov
->name
);
190 swfdec_movie_begin_update_matrix (copy
);
191 copy
->matrix
= mov
->matrix
;
192 copy
->modified
= mov
->modified
;
193 copy
->xscale
= mov
->xscale
;
194 copy
->yscale
= mov
->yscale
;
195 copy
->rotation
= mov
->rotation
;
196 copy
->lockroot
= mov
->lockroot
;
197 swfdec_movie_end_update_matrix (copy
);
198 /* FIXME: are events copied? If so, wouldn't that be a security issue? */
199 swfdec_movie_set_static_properties (copy
, &mov
->original_transform
,
200 &mov
->color_transform
, mov
->original_ratio
, mov
->clip_depth
,
201 mov
->blend_mode
, NULL
);
202 swfdec_movie_remove (mov
);
203 return SWFDEC_SPRITE_MOVIE (copy
);
207 swfdec_resource_stream_target_open (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
209 SwfdecLoader
*loader
= SWFDEC_LOADER (stream
);
210 SwfdecResource
*instance
= SWFDEC_RESOURCE (target
);
211 SwfdecAsObject
*object
;
215 g_assert (SWFDEC_AS_VALUE_IS_MOVIE (&instance
->movie
));
216 movie
= SWFDEC_AS_VALUE_GET_MOVIE (&instance
->movie
);
218 object
= swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (movie
));
219 query
= swfdec_url_get_query (swfdec_loader_get_url (loader
));
221 SWFDEC_INFO ("set url query movie variables: %s", query
);
222 swfdec_as_object_decode (object
, query
);
224 if (instance
->variables
) {
225 SWFDEC_INFO ("set manual movie variables: %s", instance
->variables
);
226 swfdec_as_object_decode (object
, instance
->variables
);
228 swfdec_resource_emit_signal (instance
, SWFDEC_AS_STR_onLoadStart
, FALSE
, NULL
, 0);
229 instance
->state
= SWFDEC_RESOURCE_OPENED
;
233 swfdec_resource_stream_target_parse (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
235 SwfdecLoader
*loader
= SWFDEC_LOADER (stream
);
236 SwfdecResource
*resource
= SWFDEC_RESOURCE (target
);
237 SwfdecBufferQueue
*queue
;
238 SwfdecBuffer
*buffer
;
239 SwfdecDecoder
*dec
= resource
->decoder
;
243 queue
= swfdec_stream_get_queue (stream
);
244 if (dec
== NULL
&& swfdec_buffer_queue_get_offset (queue
) == 0) {
245 if (swfdec_buffer_queue_get_depth (queue
) < SWFDEC_DECODER_DETECT_LENGTH
)
247 buffer
= swfdec_buffer_queue_peek (queue
, 4);
248 dec
= swfdec_decoder_new (buffer
);
249 swfdec_buffer_unref (buffer
);
251 SWFDEC_ERROR ("no decoder found for format");
254 resource
->decoder
= dec
;
255 g_signal_connect_swapped (dec
, "missing-plugin",
256 G_CALLBACK (swfdec_player_add_missing_plugin
), swfdec_gc_object_get_context (resource
));
257 total
= swfdec_loader_get_size (loader
);
259 dec
->bytes_total
= total
;
262 while (swfdec_buffer_queue_get_depth (queue
)) {
266 buffer
= swfdec_buffer_queue_peek_buffer (queue
);
269 if (parsed
+ buffer
->length
<= 65536) {
270 swfdec_buffer_unref (buffer
);
271 buffer
= swfdec_buffer_queue_pull_buffer (queue
);
273 swfdec_buffer_unref (buffer
);
274 buffer
= swfdec_buffer_queue_pull (queue
, 65536 - parsed
);
276 parsed
+= buffer
->length
;
278 status
|= swfdec_decoder_parse (dec
, buffer
);
280 swfdec_buffer_unref (buffer
);
282 } while (parsed
< 65536 && (status
& (SWFDEC_STATUS_ERROR
| SWFDEC_STATUS_EOF
)) == 0);
283 if (status
& SWFDEC_STATUS_ERROR
) {
284 SWFDEC_ERROR ("parsing error");
285 swfdec_stream_set_target (SWFDEC_STREAM (loader
), NULL
);
288 if ((status
& SWFDEC_STATUS_INIT
)) {
289 if (SWFDEC_IS_SWF_DECODER (dec
))
290 resource
->version
= SWFDEC_SWF_DECODER (dec
)->version
;
291 if (swfdec_resource_is_root (resource
)) {
292 swfdec_player_initialize (SWFDEC_PLAYER (swfdec_gc_object_get_context (resource
)),
293 dec
->rate
, dec
->width
, dec
->height
);
296 if (status
& SWFDEC_STATUS_IMAGE
)
297 swfdec_resource_stream_target_image (resource
);
298 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadProgress
, TRUE
, NULL
, 0);
299 if (status
& SWFDEC_STATUS_EOF
)
306 swfdec_resource_abort_if_not_initialized (SwfdecResource
*resource
)
308 if (resource
->sandbox
)
311 swfdec_as_context_abort (swfdec_gc_object_get_context (resource
),
312 "This is not a Flash file");
317 swfdec_resource_stream_target_close (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
319 SwfdecResource
*resource
= SWFDEC_RESOURCE (target
);
322 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadProgress
, TRUE
, NULL
, 0);
323 if (resource
->decoder
) {
324 SwfdecDecoder
*dec
= resource
->decoder
;
325 swfdec_decoder_eof (dec
);
326 if (dec
->data_type
!= SWFDEC_LOADER_DATA_UNKNOWN
)
327 swfdec_loader_set_data_type (SWFDEC_LOADER (stream
), dec
->data_type
);
330 swfdec_as_value_set_integer (swfdec_gc_object_get_context (resource
), &val
, 0); /* FIXME */
331 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadComplete
, FALSE
, &val
, 1);
332 resource
->state
= SWFDEC_RESOURCE_COMPLETE
;
333 if (swfdec_resource_abort_if_not_initialized (resource
))
336 if (SWFDEC_AS_VALUE_IS_MOVIE (&resource
->movie
)) {
337 SwfdecMovie
*movie
= SWFDEC_AS_VALUE_GET_MOVIE (&resource
->movie
);
339 swfdec_actor_queue_script (SWFDEC_ACTOR (movie
), SWFDEC_EVENT_LOAD
);
344 swfdec_resource_stream_target_error (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
346 SwfdecResource
*resource
= SWFDEC_RESOURCE (target
);
349 switch (resource
->state
) {
350 case SWFDEC_RESOURCE_REQUESTED
:
351 message
= SWFDEC_AS_STR_URLNotFound
;
353 case SWFDEC_RESOURCE_OPENED
:
354 message
= SWFDEC_AS_STR_LoadNeverCompleted
;
356 case SWFDEC_RESOURCE_NEW
:
357 case SWFDEC_RESOURCE_COMPLETE
:
358 case SWFDEC_RESOURCE_DONE
:
360 g_assert_not_reached ();
361 message
= SWFDEC_AS_STR_EMPTY
;
364 swfdec_resource_emit_error (resource
, message
);
365 swfdec_resource_abort_if_not_initialized (resource
);
369 swfdec_resource_stream_target_init (SwfdecStreamTargetInterface
*iface
)
371 iface
->get_player
= swfdec_resource_stream_target_get_player
;
372 iface
->open
= swfdec_resource_stream_target_open
;
373 iface
->parse
= swfdec_resource_stream_target_parse
;
374 iface
->error
= swfdec_resource_stream_target_error
;
375 iface
->close
= swfdec_resource_stream_target_close
;
379 swfdec_resource_mark (SwfdecGcObject
*object
)
381 SwfdecResource
*resource
= SWFDEC_RESOURCE (object
);
383 if (resource
->clip_loader
) {
384 swfdec_gc_object_mark (resource
->clip_loader
);
385 swfdec_gc_object_mark (resource
->clip_loader_sandbox
);
387 if (resource
->sandbox
)
388 swfdec_gc_object_mark (resource
->sandbox
);
389 if (resource
->target
)
390 swfdec_gc_object_mark (resource
->target
);
391 swfdec_as_value_mark (&resource
->movie
);
393 SWFDEC_GC_OBJECT_CLASS (swfdec_resource_parent_class
)->mark (object
);
397 swfdec_resource_dispose (GObject
*object
)
399 SwfdecResource
*resource
= SWFDEC_RESOURCE (object
);
401 if (resource
->loader
) {
402 swfdec_stream_set_target (SWFDEC_STREAM (resource
->loader
), NULL
);
403 g_object_unref (resource
->loader
);
404 resource
->loader
= NULL
;
406 if (resource
->decoder
) {
407 g_signal_handlers_disconnect_by_func (resource
->decoder
,
408 swfdec_player_add_missing_plugin
, swfdec_gc_object_get_context (resource
));
409 g_object_unref (resource
->decoder
);
410 resource
->decoder
= NULL
;
412 g_free (resource
->variables
);
413 g_hash_table_destroy (resource
->exports
);
414 g_hash_table_destroy (resource
->export_names
);
416 G_OBJECT_CLASS (swfdec_resource_parent_class
)->dispose (object
);
420 swfdec_resource_class_init (SwfdecResourceClass
*klass
)
422 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
423 SwfdecGcObjectClass
*gc_class
= SWFDEC_GC_OBJECT_CLASS (klass
);
425 object_class
->dispose
= swfdec_resource_dispose
;
427 gc_class
->mark
= swfdec_resource_mark
;
431 swfdec_resource_init (SwfdecResource
*instance
)
433 instance
->exports
= g_hash_table_new_full (swfdec_str_case_hash
,
434 swfdec_str_case_equal
, g_free
, g_object_unref
);
435 instance
->export_names
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
436 g_object_unref
, g_free
);
440 swfdec_resource_set_loader (SwfdecResource
*resource
, SwfdecLoader
*loader
)
442 g_return_if_fail (SWFDEC_IS_RESOURCE (resource
));
443 g_return_if_fail (SWFDEC_IS_LOADER (loader
));
444 g_return_if_fail (resource
->loader
== NULL
);
446 resource
->loader
= g_object_ref (loader
);
447 swfdec_stream_set_target (SWFDEC_STREAM (resource
->loader
), SWFDEC_STREAM_TARGET (resource
));
448 resource
->state
= SWFDEC_RESOURCE_REQUESTED
;
452 swfdec_resource_new (SwfdecPlayer
*player
, SwfdecLoader
*loader
, const char *variables
)
454 SwfdecResource
*resource
;
456 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
457 g_return_val_if_fail (SWFDEC_IS_LOADER (loader
), NULL
);
459 resource
= g_object_new (SWFDEC_TYPE_RESOURCE
, "context", player
, NULL
);
460 resource
->version
= 8;
461 resource
->variables
= g_strdup (variables
);
462 swfdec_resource_set_loader (resource
, loader
);
468 swfdec_resource_get_export (SwfdecResource
*instance
, const char *name
)
470 g_return_val_if_fail (SWFDEC_IS_RESOURCE (instance
), NULL
);
471 g_return_val_if_fail (name
!= NULL
, NULL
);
473 return g_hash_table_lookup (instance
->exports
, name
);
477 swfdec_resource_get_export_name (SwfdecResource
*instance
, SwfdecCharacter
*character
)
479 g_return_val_if_fail (SWFDEC_IS_RESOURCE (instance
), NULL
);
480 g_return_val_if_fail (SWFDEC_IS_CHARACTER (character
), NULL
);
482 return g_hash_table_lookup (instance
->export_names
, character
);
486 swfdec_resource_add_export (SwfdecResource
*instance
, SwfdecCharacter
*character
, const char *name
)
488 g_return_if_fail (SWFDEC_IS_RESOURCE (instance
));
489 g_return_if_fail (SWFDEC_IS_CHARACTER (character
));
490 g_return_if_fail (name
!= NULL
);
492 g_hash_table_insert (instance
->exports
, g_strdup (name
), g_object_ref (character
));
493 g_hash_table_insert (instance
->export_names
, g_object_ref (character
), g_strdup (name
));
496 /*** RESOURC LOAD ***/
498 typedef struct _SwfdecResourceLoad SwfdecResourceLoad
;
499 struct _SwfdecResourceLoad
{
500 SwfdecSandbox
* sandbox
;
501 SwfdecAsValue target
;
503 SwfdecBuffer
* buffer
;
504 SwfdecMovieClipLoader
* loader
;
508 swfdec_resource_load_free (gpointer loadp
)
510 SwfdecResourceLoad
*load
= loadp
;
514 swfdec_buffer_unref (load
->buffer
);
515 g_slice_free (SwfdecResourceLoad
, load
);
519 swfdec_resource_load_mark (gpointer loadp
, gpointer playerp
)
521 SwfdecResourceLoad
*load
= loadp
;
523 swfdec_gc_object_mark (load
->sandbox
);
525 swfdec_gc_object_mark (load
->loader
);
526 swfdec_as_value_mark (&load
->target
);
530 swfdec_resource_create_movie (SwfdecResource
*resource
, SwfdecResourceLoad
*load
)
532 SwfdecPlayer
*player
;
533 SwfdecSpriteMovie
*movie
;
535 if (SWFDEC_AS_VALUE_IS_MOVIE (&resource
->movie
))
537 player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (resource
));
538 if (SWFDEC_AS_VALUE_IS_MOVIE (&load
->target
)) {
539 movie
= (SwfdecSpriteMovie
*) SWFDEC_AS_VALUE_GET_MOVIE (&load
->target
);
540 if (SWFDEC_IS_SPRITE_MOVIE (movie
))
541 movie
= swfdec_resource_replace_movie (movie
, resource
);
544 } else if (SWFDEC_AS_VALUE_IS_STRING (&load
->target
)) {
545 int level
= swfdec_player_get_level (player
, SWFDEC_AS_VALUE_GET_STRING (&load
->target
), 7);
547 movie
= swfdec_player_get_movie_at_level (player
, level
);
549 swfdec_movie_remove (SWFDEC_MOVIE (movie
));
550 movie
= swfdec_player_create_movie_at_level (player
, resource
, level
);
555 /* we only set target to string or movie values */
556 g_assert_not_reached ();
559 SWFDEC_WARNING ("target does not reference a movie, not loading %s", load
->url
);
562 /* FIXME: does this belong here? */
563 SWFDEC_ACTOR (movie
)->focusrect
= SWFDEC_FLASH_YES
;
568 swfdec_resource_do_load (SwfdecPlayer
*player
, gboolean allowed
, gpointer loadp
)
570 SwfdecResourceLoad
*load
= loadp
;
571 SwfdecResource
*resource
;
572 SwfdecLoader
*loader
;
574 resource
= g_object_new (SWFDEC_TYPE_RESOURCE
, "context", player
, NULL
);
575 resource
->version
= 8;
577 resource
->clip_loader
= load
->loader
;
578 resource
->clip_loader_sandbox
= load
->sandbox
;
580 resource
->sandbox
= load
->sandbox
;
582 SWFDEC_WARNING ("SECURITY: no access to %s from %s",
583 load
->url
, swfdec_url_get_url (load
->sandbox
->url
));
584 /* FIXME: is replacing correct? */
585 if (SWFDEC_AS_VALUE_IS_MOVIE (&load
->target
)) {
586 if (SWFDEC_AS_VALUE_IS_MOVIE (&load
->target
) &&
587 SWFDEC_IS_SPRITE_MOVIE (SWFDEC_AS_VALUE_GET_MOVIE (&load
->target
)))
588 resource
->movie
= load
->target
;
589 swfdec_resource_emit_error (resource
, SWFDEC_AS_STR_IllegalRequest
);
591 swfdec_player_unroot (player
, load
);
595 /* FIXME: load nonetheless, even if there's no movie? */
596 if (swfdec_resource_create_movie (resource
, load
)) {
597 loader
= swfdec_player_load (player
, load
->url
, load
->buffer
);
598 swfdec_resource_set_loader (resource
, loader
);
599 g_object_unref (loader
);
601 swfdec_player_unroot (player
, load
);
604 static const SwfdecAccessMatrix swfdec_resource_matrix
= {
605 { SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_NO
},
606 { SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_YES
},
607 { SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_NO
},
608 { SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_YES
},
609 { SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_YES
}
613 swfdec_resource_load_request (gpointer loadp
, gpointer playerp
)
615 SwfdecResourceLoad
*load
= loadp
;
616 SwfdecPlayer
*player
= playerp
;
618 /* empty URL means unload (yay!) */
619 if (load
->url
[0] == '\0') {
620 SwfdecSpriteMovie
*movie
;
622 if (SWFDEC_AS_VALUE_IS_MOVIE (&load
->target
)) {
623 movie
= (SwfdecSpriteMovie
*) SWFDEC_AS_VALUE_GET_MOVIE (&load
->target
);
627 if (SWFDEC_IS_SPRITE_MOVIE (movie
)) {
628 swfdec_resource_replace_movie (movie
, SWFDEC_MOVIE (movie
)->resource
);
630 SWFDEC_DEBUG ("no movie, not unloading");
632 swfdec_player_unroot (player
, load
);
637 if (g_ascii_strncasecmp (load
->url
, "FSCommand:", 10) == 0) {
638 char *command
= load
->url
+ 10;
639 const char *target
= swfdec_as_value_to_string (SWFDEC_AS_CONTEXT (player
), &load
->target
);
640 if (SWFDEC_AS_VALUE_IS_MOVIE (&load
->target
)) {
641 SWFDEC_FIXME ("Adobe 9.0.124.0 and later don't emit fscommands here. "
642 "We just do for compatibility reasons with the testsuite.");
644 g_signal_emit_by_name (player
, "fscommand", command
, target
);
645 swfdec_player_unroot (player
, load
);
649 /* LAUNCH command (aka getURL) */
650 if (SWFDEC_AS_VALUE_IS_STRING (&load
->target
) && swfdec_player_get_level (player
,
651 SWFDEC_AS_VALUE_GET_STRING (&load
->target
), 7) < 0) {
652 swfdec_player_launch (player
, load
->url
, SWFDEC_AS_VALUE_GET_STRING (&load
->target
), load
->buffer
);
653 swfdec_player_unroot (player
, load
);
657 swfdec_player_allow_by_matrix (player
, load
->sandbox
, load
->url
,
658 swfdec_resource_matrix
, swfdec_resource_do_load
, load
);
661 /* NB: must be called from a script */
662 /* FIXME: 5 arguments?! */
664 swfdec_resource_load_internal (SwfdecPlayer
*player
, const SwfdecAsValue
*val
,
665 const char *url
, SwfdecBuffer
*buffer
, SwfdecMovieClipLoader
*loader
)
667 SwfdecResourceLoad
*load
;
669 g_assert (SWFDEC_AS_CONTEXT (player
)->frame
!= NULL
);
670 load
= g_slice_new (SwfdecResourceLoad
);
672 load
->sandbox
= swfdec_sandbox_get (player
);
673 load
->url
= g_strdup (url
);
675 load
->buffer
= buffer
;
676 load
->loader
= loader
;
678 swfdec_player_root_full (player
, load
, swfdec_resource_load_mark
, swfdec_resource_load_free
);
679 swfdec_player_request_resource (player
, swfdec_resource_load_request
, load
, NULL
);
683 swfdec_resource_load_movie (SwfdecPlayer
*player
, const SwfdecAsValue
*target
,
684 const char *url
, SwfdecBuffer
*buffer
, SwfdecMovieClipLoader
*loader
)
690 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
691 g_return_val_if_fail (target
!= NULL
, FALSE
);
692 g_return_val_if_fail (url
!= NULL
, FALSE
);
693 g_return_val_if_fail (loader
== NULL
|| SWFDEC_IS_MOVIE_CLIP_LOADER (loader
), FALSE
);
695 if (SWFDEC_AS_VALUE_IS_MOVIE (target
)) {
696 movie
= SWFDEC_AS_VALUE_GET_MOVIE (target
);
697 if (SWFDEC_IS_SPRITE_MOVIE (movie
)) {
698 swfdec_resource_load_internal (player
, target
, url
, buffer
, loader
);
704 if (SWFDEC_AS_VALUE_IS_NUMBER (target
)) {
705 int i
= swfdec_as_double_to_integer (SWFDEC_AS_VALUE_GET_NUMBER (target
));
708 SWFDEC_AS_VALUE_SET_STRING (&val
, swfdec_as_context_give_string (
709 SWFDEC_AS_CONTEXT (player
), g_strdup_printf ("_level%d", i
)));
710 swfdec_resource_load_internal (player
, &val
, url
, buffer
, loader
);
712 } else if (SWFDEC_AS_VALUE_IS_STRING (target
) || SWFDEC_AS_VALUE_IS_MOVIE(target
)) {
713 s
= swfdec_as_value_to_string (SWFDEC_AS_CONTEXT (player
), target
);
715 SWFDEC_WARNING ("target does not reference a movie, not loading %s", url
);
719 s
= swfdec_as_value_to_string (SWFDEC_AS_CONTEXT (player
), target
);
721 if (swfdec_player_get_level (player
, s
, SWFDEC_AS_CONTEXT (player
)->version
) >= 0) {
722 /* lowercase the string, so we can do case insensitive level lookups later on */
723 char *tmp
= g_ascii_strdown (s
, -1);
724 SWFDEC_AS_VALUE_SET_STRING (&val
, swfdec_as_context_give_string (
725 SWFDEC_AS_CONTEXT (player
), tmp
));
726 swfdec_resource_load_internal (player
, &val
, url
, buffer
, NULL
);
729 movie
= swfdec_player_get_movie_from_string (player
, s
);
730 if (SWFDEC_IS_SPRITE_MOVIE (movie
)) {
731 SWFDEC_AS_VALUE_SET_MOVIE (&val
, movie
);
732 swfdec_resource_load_internal (player
, &val
, url
, buffer
, loader
);
735 SWFDEC_WARNING ("%s does not reference a movie, not loading %s", s
, url
);
740 swfdec_resource_load (SwfdecPlayer
*player
, const char *target
,
741 const char *url
, SwfdecBuffer
*buffer
)
745 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
746 g_return_if_fail (target
!= NULL
);
747 g_return_if_fail (url
!= NULL
);
749 SWFDEC_AS_VALUE_SET_STRING (&val
, target
);
750 swfdec_resource_load_internal (player
, &val
, url
, buffer
, NULL
);
754 swfdec_resource_emit_on_load_init (SwfdecResource
*resource
)
756 g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource
), FALSE
);
758 if (resource
->state
!= SWFDEC_RESOURCE_COMPLETE
)
761 if (SWFDEC_AS_VALUE_IS_MOVIE (&resource
->movie
) && SWFDEC_IS_IMAGE_DECODER (resource
->decoder
)) {
762 SwfdecImage
*image
= SWFDEC_IMAGE_DECODER (resource
->decoder
)->image
;
763 SwfdecMovie
*movie
= SWFDEC_AS_VALUE_GET_MOVIE (&resource
->movie
);
764 if (image
&& movie
) {
765 swfdec_movie_invalidate_next (movie
);
766 swfdec_movie_queue_update (movie
, SWFDEC_MOVIE_INVALID_EXTENTS
);
767 movie
->image
= g_object_ref (image
);
770 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadInit
, FALSE
, NULL
, 0);
771 resource
->state
= SWFDEC_RESOURCE_DONE
;
772 /* free now unneeded resources */
773 resource
->clip_loader
= NULL
;
774 resource
->clip_loader_sandbox
= NULL
;