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_AS_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
->movie
== SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource
)->context
)->priv
->roots
->data
;
64 swfdec_resource_stream_target_get_player (SwfdecStreamTarget
*target
)
66 return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (target
)->context
);
70 swfdec_resource_stream_target_image (SwfdecResource
*instance
)
72 SwfdecPlayer
*player
= SWFDEC_PLAYER (SWFDEC_AS_OBJECT (instance
)->context
);
73 SwfdecSpriteMovie
*movie
= instance
->movie
;
75 if (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_as_object_set_constructor (SWFDEC_AS_OBJECT (movie
), instance
->sandbox
->MovieClip
);
92 if (swfdec_resource_is_root (instance
)) {
93 swfdec_player_start_ticking (player
);
94 swfdec_movie_initialize (SWFDEC_MOVIE (movie
));
95 swfdec_player_perform_actions (player
);
98 SWFDEC_FIXME ("cannot continue loading %s, invalid rights",
99 swfdec_url_get_url (swfdec_loader_get_url (instance
->loader
)));
100 swfdec_stream_set_target (SWFDEC_STREAM (instance
->loader
), NULL
);
101 instance
->sandbox
= old_sandbox
;
102 /* FIXME: anyting else on the movie we need to clear? */
105 g_assert_not_reached ();
109 /* NB: name must be GC'ed */
111 swfdec_resource_emit_signal (SwfdecResource
*resource
, const char *name
, gboolean progress
,
112 SwfdecAsValue
*args
, guint n_args
)
116 guint skip
= progress
? 4 : 2;
117 SwfdecAsValue vals
[n_args
+ skip
];
119 if (resource
->clip_loader
== NULL
)
121 cx
= SWFDEC_AS_OBJECT (resource
->clip_loader
)->context
;
123 SWFDEC_AS_VALUE_SET_STRING (&vals
[0], name
);
124 if (resource
->movie
) {
125 movie
= swfdec_movie_resolve (SWFDEC_MOVIE (resource
->movie
));
127 SWFDEC_DEBUG ("no movie, not emitting signal");
130 if (name
== SWFDEC_AS_STR_onLoadInit
&&
131 movie
!= SWFDEC_MOVIE (resource
->movie
)) {
132 SWFDEC_INFO ("not emitting onLoadInit - the movie is different");
135 SWFDEC_AS_VALUE_SET_OBJECT (&vals
[1], SWFDEC_AS_OBJECT (movie
));
137 SWFDEC_AS_VALUE_SET_UNDEFINED (&vals
[1]);
142 if (SWFDEC_IS_MOVIE (movie
))
143 res
= swfdec_movie_get_own_resource (SWFDEC_MOVIE (movie
));
146 if (res
&& res
->decoder
) {
147 SwfdecDecoder
*dec
= res
->decoder
;
148 SWFDEC_AS_VALUE_SET_INT (&vals
[2], dec
->bytes_loaded
);
149 SWFDEC_AS_VALUE_SET_INT (&vals
[3], dec
->bytes_total
);
151 SWFDEC_AS_VALUE_SET_INT (&vals
[2], 0);
152 SWFDEC_AS_VALUE_SET_INT (&vals
[3], 0);
156 memcpy (&vals
[skip
], args
, sizeof (SwfdecAsValue
) * n_args
);
157 /* FIXME: what's the correct sandbox here? */
158 swfdec_sandbox_use (resource
->clip_loader_sandbox
);
159 swfdec_as_object_call (SWFDEC_AS_OBJECT (resource
->clip_loader
), SWFDEC_AS_STR_broadcastMessage
,
160 n_args
+ skip
, vals
, NULL
);
161 swfdec_sandbox_unuse (resource
->clip_loader_sandbox
);
165 swfdec_resource_emit_error (SwfdecResource
*resource
, const char *message
)
167 SwfdecAsValue vals
[2];
169 SWFDEC_AS_VALUE_SET_STRING (&vals
[0], message
);
170 SWFDEC_AS_VALUE_SET_INT (&vals
[1], 0);
172 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadError
, FALSE
, vals
, 2);
175 static SwfdecSpriteMovie
*
176 swfdec_resource_replace_movie (SwfdecSpriteMovie
*movie
, SwfdecResource
*resource
)
178 /* can't use swfdec_movie_duplicate() here, we copy to same depth */
179 SwfdecMovie
*mov
= SWFDEC_MOVIE (movie
);
182 copy
= swfdec_movie_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie
)->context
),
183 mov
->depth
, mov
->parent
, resource
, NULL
, mov
->name
);
186 swfdec_movie_begin_update_matrix (copy
);
187 copy
->matrix
= mov
->matrix
;
188 copy
->original_name
= mov
->original_name
;
189 copy
->modified
= mov
->modified
;
190 copy
->xscale
= mov
->xscale
;
191 copy
->yscale
= mov
->yscale
;
192 copy
->rotation
= mov
->rotation
;
193 copy
->lockroot
= mov
->lockroot
;
194 swfdec_movie_end_update_matrix (copy
);
195 /* FIXME: are events copied? If so, wouldn't that be a security issue? */
196 swfdec_movie_set_static_properties (copy
, &mov
->original_transform
,
197 &mov
->color_transform
, mov
->original_ratio
, mov
->clip_depth
,
198 mov
->blend_mode
, NULL
);
199 swfdec_movie_remove (mov
);
200 return SWFDEC_SPRITE_MOVIE (copy
);
204 swfdec_resource_stream_target_open (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
206 SwfdecLoader
*loader
= SWFDEC_LOADER (stream
);
207 SwfdecResource
*instance
= SWFDEC_RESOURCE (target
);
210 g_assert (instance
->movie
);
211 query
= swfdec_url_get_query (swfdec_loader_get_url (loader
));
213 SWFDEC_INFO ("set url query movie variables: %s", query
);
214 swfdec_as_object_decode (SWFDEC_AS_OBJECT (instance
->movie
), query
);
216 if (instance
->variables
) {
217 SWFDEC_INFO ("set manual movie variables: %s", instance
->variables
);
218 swfdec_as_object_decode (SWFDEC_AS_OBJECT (instance
->movie
), instance
->variables
);
220 swfdec_resource_emit_signal (instance
, SWFDEC_AS_STR_onLoadStart
, FALSE
, NULL
, 0);
221 instance
->state
= SWFDEC_RESOURCE_OPENED
;
225 swfdec_resource_stream_target_parse (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
227 SwfdecLoader
*loader
= SWFDEC_LOADER (stream
);
228 SwfdecResource
*resource
= SWFDEC_RESOURCE (target
);
229 SwfdecBufferQueue
*queue
;
230 SwfdecBuffer
*buffer
;
231 SwfdecDecoder
*dec
= resource
->decoder
;
235 queue
= swfdec_stream_get_queue (stream
);
236 if (dec
== NULL
&& swfdec_buffer_queue_get_offset (queue
) == 0) {
237 if (swfdec_buffer_queue_get_depth (queue
) < SWFDEC_DECODER_DETECT_LENGTH
)
239 buffer
= swfdec_buffer_queue_peek (queue
, 4);
240 dec
= swfdec_decoder_new (buffer
);
241 swfdec_buffer_unref (buffer
);
243 SWFDEC_ERROR ("no decoder found for format");
246 resource
->decoder
= dec
;
247 g_signal_connect_swapped (dec
, "missing-plugin",
248 G_CALLBACK (swfdec_player_add_missing_plugin
), SWFDEC_AS_OBJECT (resource
)->context
);
249 total
= swfdec_loader_get_size (loader
);
251 dec
->bytes_total
= total
;
254 while (swfdec_buffer_queue_get_depth (queue
)) {
258 buffer
= swfdec_buffer_queue_peek_buffer (queue
);
261 if (parsed
+ buffer
->length
<= 65536) {
262 swfdec_buffer_unref (buffer
);
263 buffer
= swfdec_buffer_queue_pull_buffer (queue
);
265 swfdec_buffer_unref (buffer
);
266 buffer
= swfdec_buffer_queue_pull (queue
, 65536 - parsed
);
268 parsed
+= buffer
->length
;
270 status
|= swfdec_decoder_parse (dec
, buffer
);
272 swfdec_buffer_unref (buffer
);
274 } while (parsed
< 65536 && (status
& (SWFDEC_STATUS_ERROR
| SWFDEC_STATUS_EOF
)) == 0);
275 if (status
& SWFDEC_STATUS_ERROR
) {
276 SWFDEC_ERROR ("parsing error");
277 swfdec_stream_set_target (SWFDEC_STREAM (loader
), NULL
);
280 if ((status
& SWFDEC_STATUS_INIT
)) {
281 if (SWFDEC_IS_SWF_DECODER (dec
))
282 resource
->version
= SWFDEC_SWF_DECODER (dec
)->version
;
283 if (swfdec_resource_is_root (resource
)) {
284 swfdec_player_initialize (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource
)->context
),
285 dec
->rate
, dec
->width
, dec
->height
);
288 if (status
& SWFDEC_STATUS_IMAGE
)
289 swfdec_resource_stream_target_image (resource
);
290 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadProgress
, TRUE
, NULL
, 0);
291 if (status
& SWFDEC_STATUS_EOF
)
298 swfdec_resource_abort_if_not_initialized (SwfdecResource
*resource
)
300 if (resource
->sandbox
)
303 swfdec_as_context_abort (SWFDEC_AS_OBJECT (resource
)->context
,
304 "This is not a Flash file");
309 swfdec_resource_stream_target_close (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
311 SwfdecResource
*resource
= SWFDEC_RESOURCE (target
);
314 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadProgress
, TRUE
, NULL
, 0);
315 if (resource
->decoder
) {
316 SwfdecDecoder
*dec
= resource
->decoder
;
317 swfdec_decoder_eof (dec
);
318 if (dec
->data_type
!= SWFDEC_LOADER_DATA_UNKNOWN
)
319 swfdec_loader_set_data_type (SWFDEC_LOADER (stream
), dec
->data_type
);
322 SWFDEC_AS_VALUE_SET_INT (&val
, 0); /* FIXME */
323 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadComplete
, FALSE
, &val
, 1);
324 resource
->state
= SWFDEC_RESOURCE_COMPLETE
;
325 if (swfdec_resource_abort_if_not_initialized (resource
))
328 if (resource
->movie
!= NULL
)
329 swfdec_actor_queue_script (SWFDEC_ACTOR (resource
->movie
), SWFDEC_EVENT_LOAD
);
333 swfdec_resource_stream_target_error (SwfdecStreamTarget
*target
, SwfdecStream
*stream
)
335 SwfdecResource
*resource
= SWFDEC_RESOURCE (target
);
338 switch (resource
->state
) {
339 case SWFDEC_RESOURCE_REQUESTED
:
340 message
= SWFDEC_AS_STR_URLNotFound
;
342 case SWFDEC_RESOURCE_OPENED
:
343 message
= SWFDEC_AS_STR_LoadNeverCompleted
;
345 case SWFDEC_RESOURCE_NEW
:
346 case SWFDEC_RESOURCE_COMPLETE
:
347 case SWFDEC_RESOURCE_DONE
:
349 g_assert_not_reached ();
350 message
= SWFDEC_AS_STR_EMPTY
;
353 swfdec_resource_emit_error (resource
, message
);
354 swfdec_resource_abort_if_not_initialized (resource
);
358 swfdec_resource_stream_target_init (SwfdecStreamTargetInterface
*iface
)
360 iface
->get_player
= swfdec_resource_stream_target_get_player
;
361 iface
->open
= swfdec_resource_stream_target_open
;
362 iface
->parse
= swfdec_resource_stream_target_parse
;
363 iface
->error
= swfdec_resource_stream_target_error
;
364 iface
->close
= swfdec_resource_stream_target_close
;
368 swfdec_resource_mark (SwfdecAsObject
*object
)
370 SwfdecResource
*resource
= SWFDEC_RESOURCE (object
);
372 if (resource
->clip_loader
) {
373 swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource
->clip_loader
));
374 swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource
->clip_loader_sandbox
));
376 if (resource
->sandbox
)
377 swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource
->sandbox
));
378 if (resource
->target
)
379 swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource
->target
));
381 SWFDEC_AS_OBJECT_CLASS (swfdec_resource_parent_class
)->mark (object
);
385 swfdec_resource_dispose (GObject
*object
)
387 SwfdecResource
*resource
= SWFDEC_RESOURCE (object
);
389 if (resource
->loader
) {
390 swfdec_stream_set_target (SWFDEC_STREAM (resource
->loader
), NULL
);
391 g_object_unref (resource
->loader
);
392 resource
->loader
= NULL
;
394 if (resource
->decoder
) {
395 g_signal_handlers_disconnect_by_func (resource
->decoder
,
396 swfdec_player_add_missing_plugin
, SWFDEC_AS_OBJECT (resource
)->context
);
397 g_object_unref (resource
->decoder
);
398 resource
->decoder
= NULL
;
400 g_free (resource
->variables
);
401 g_hash_table_destroy (resource
->exports
);
402 g_hash_table_destroy (resource
->export_names
);
404 G_OBJECT_CLASS (swfdec_resource_parent_class
)->dispose (object
);
408 swfdec_resource_class_init (SwfdecResourceClass
*klass
)
410 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
411 SwfdecAsObjectClass
*asobject_class
= SWFDEC_AS_OBJECT_CLASS (klass
);
413 object_class
->dispose
= swfdec_resource_dispose
;
415 asobject_class
->mark
= swfdec_resource_mark
;
419 swfdec_resource_init (SwfdecResource
*instance
)
421 instance
->exports
= g_hash_table_new_full (swfdec_str_case_hash
,
422 swfdec_str_case_equal
, g_free
, g_object_unref
);
423 instance
->export_names
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
424 g_object_unref
, g_free
);
428 swfdec_resource_set_loader (SwfdecResource
*resource
, SwfdecLoader
*loader
)
430 g_return_if_fail (SWFDEC_IS_RESOURCE (resource
));
431 g_return_if_fail (SWFDEC_IS_LOADER (loader
));
432 g_return_if_fail (resource
->loader
== NULL
);
434 resource
->loader
= g_object_ref (loader
);
435 swfdec_stream_set_target (SWFDEC_STREAM (resource
->loader
), SWFDEC_STREAM_TARGET (resource
));
436 resource
->state
= SWFDEC_RESOURCE_REQUESTED
;
440 swfdec_resource_new (SwfdecPlayer
*player
, SwfdecLoader
*loader
, const char *variables
)
442 SwfdecResource
*resource
;
445 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
446 g_return_val_if_fail (SWFDEC_IS_LOADER (loader
), NULL
);
448 size
= sizeof (SwfdecResource
);
449 if (!swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player
), size
))
451 resource
= g_object_new (SWFDEC_TYPE_RESOURCE
, NULL
);
452 swfdec_as_object_add (SWFDEC_AS_OBJECT (resource
), SWFDEC_AS_CONTEXT (player
), size
);
453 resource
->version
= 8;
454 resource
->variables
= g_strdup (variables
);
455 swfdec_resource_set_loader (resource
, loader
);
461 swfdec_resource_get_export (SwfdecResource
*instance
, const char *name
)
463 g_return_val_if_fail (SWFDEC_IS_RESOURCE (instance
), NULL
);
464 g_return_val_if_fail (name
!= NULL
, NULL
);
466 return g_hash_table_lookup (instance
->exports
, name
);
470 swfdec_resource_get_export_name (SwfdecResource
*instance
, SwfdecCharacter
*character
)
472 g_return_val_if_fail (SWFDEC_IS_RESOURCE (instance
), NULL
);
473 g_return_val_if_fail (SWFDEC_IS_CHARACTER (character
), NULL
);
475 return g_hash_table_lookup (instance
->export_names
, character
);
479 swfdec_resource_add_export (SwfdecResource
*instance
, SwfdecCharacter
*character
, const char *name
)
481 g_return_if_fail (SWFDEC_IS_RESOURCE (instance
));
482 g_return_if_fail (SWFDEC_IS_CHARACTER (character
));
483 g_return_if_fail (name
!= NULL
);
485 g_hash_table_insert (instance
->exports
, g_strdup (name
), g_object_ref (character
));
486 g_hash_table_insert (instance
->export_names
, g_object_ref (character
), g_strdup (name
));
489 /*** RESOURC LOAD ***/
491 typedef struct _SwfdecResourceLoad SwfdecResourceLoad
;
492 struct _SwfdecResourceLoad
{
493 SwfdecSandbox
* sandbox
;
494 char * target_string
;
495 SwfdecSpriteMovie
* target_movie
;
497 SwfdecBuffer
* buffer
;
498 SwfdecMovieClipLoader
* loader
;
502 swfdec_resource_load_free (gpointer loadp
)
504 SwfdecResourceLoad
*load
= loadp
;
507 g_free (load
->target_string
);
509 swfdec_buffer_unref (load
->buffer
);
510 g_slice_free (SwfdecResourceLoad
, load
);
514 swfdec_resource_load_mark (gpointer loadp
, gpointer playerp
)
516 SwfdecResourceLoad
*load
= loadp
;
518 swfdec_as_object_mark (SWFDEC_AS_OBJECT (load
->sandbox
));
520 swfdec_as_object_mark (SWFDEC_AS_OBJECT (load
->loader
));
521 if (load
->target_movie
)
522 swfdec_as_object_mark (SWFDEC_AS_OBJECT (load
->target_movie
));
526 swfdec_resource_create_movie (SwfdecResource
*resource
, SwfdecResourceLoad
*load
)
528 SwfdecPlayer
*player
;
529 SwfdecSpriteMovie
*movie
;
533 player
= SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource
)->context
);
534 if (load
->target_movie
) {
535 movie
= (SwfdecSpriteMovie
*) swfdec_movie_resolve (SWFDEC_MOVIE (load
->target_movie
));
536 if (SWFDEC_IS_SPRITE_MOVIE (movie
))
537 movie
= swfdec_resource_replace_movie (movie
, resource
);
541 int level
= swfdec_player_get_level (player
, load
->target_string
, 7);
543 movie
= swfdec_player_get_movie_at_level (player
, level
);
545 swfdec_movie_remove (SWFDEC_MOVIE (movie
));
546 movie
= swfdec_player_create_movie_at_level (player
, resource
, level
);
552 SWFDEC_WARNING ("target does not reference a movie, not loading %s", load
->url
);
555 /* FIXME: does this belong here? */
556 SWFDEC_ACTOR (movie
)->focusrect
= SWFDEC_FLASH_YES
;
561 swfdec_resource_do_load (SwfdecPlayer
*player
, gboolean allowed
, gpointer loadp
)
563 SwfdecResourceLoad
*load
= loadp
;
564 SwfdecResource
*resource
;
565 SwfdecLoader
*loader
;
567 if (!swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player
), sizeof (SwfdecResource
))) {
568 swfdec_player_unroot (player
, load
);
571 resource
= g_object_new (SWFDEC_TYPE_RESOURCE
, NULL
);
572 swfdec_as_object_add (SWFDEC_AS_OBJECT (resource
), SWFDEC_AS_CONTEXT (player
), sizeof (SwfdecResource
));
573 resource
->version
= 8;
575 resource
->clip_loader
= load
->loader
;
576 resource
->clip_loader_sandbox
= load
->sandbox
;
578 resource
->sandbox
= load
->sandbox
;
580 SWFDEC_WARNING ("SECURITY: no access to %s from %s",
581 load
->url
, swfdec_url_get_url (load
->sandbox
->url
));
582 /* FIXME: is replacing correct? */
583 if (load
->target_movie
) {
584 resource
->movie
= SWFDEC_SPRITE_MOVIE (swfdec_movie_resolve (SWFDEC_MOVIE (load
->target_movie
)));
585 swfdec_resource_emit_error (resource
, SWFDEC_AS_STR_IllegalRequest
);
587 swfdec_player_unroot (player
, load
);
591 /* FIXME: load nonetheless, even if there's no movie? */
592 if (swfdec_resource_create_movie (resource
, load
)) {
593 loader
= swfdec_player_load (player
, load
->url
, load
->buffer
);
594 swfdec_resource_set_loader (resource
, loader
);
595 g_object_unref (loader
);
597 swfdec_player_unroot (player
, load
);
600 static const SwfdecAccessMatrix swfdec_resource_matrix
= {
601 { SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_NO
},
602 { SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_YES
},
603 { SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_NO
},
604 { SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_POLICY
},
605 { SWFDEC_ACCESS_YES
, SWFDEC_ACCESS_NO
, SWFDEC_ACCESS_POLICY
}
609 swfdec_resource_load_request (gpointer loadp
, gpointer playerp
)
611 SwfdecResourceLoad
*load
= loadp
;
612 SwfdecPlayer
*player
= playerp
;
614 /* empty URL means unload (yay!) */
615 if (load
->url
[0] == '\0') {
616 SwfdecSpriteMovie
*movie
;
618 movie
= load
->target_movie
? (SwfdecSpriteMovie
*) swfdec_movie_resolve (SWFDEC_MOVIE (load
->target_movie
)) : NULL
;
619 if (SWFDEC_IS_SPRITE_MOVIE (movie
)) {
620 swfdec_resource_replace_movie (movie
, SWFDEC_MOVIE (movie
)->resource
);
622 SWFDEC_DEBUG ("no movie, not unloading");
624 swfdec_player_unroot (player
, load
);
629 if (g_ascii_strncasecmp (load
->url
, "FSCommand:", 10) == 0) {
630 char *command
= load
->url
+ 10;
631 if (load
->target_movie
) {
632 char *target
= swfdec_movie_get_path (SWFDEC_MOVIE (load
->target_movie
), TRUE
);
633 SWFDEC_FIXME ("Adobe 9.0.124.0 and later don't emit fscommands here. "
634 "We just do for compatibility reasons with the testsuite.");
635 g_signal_emit_by_name (player
, "fscommand", command
, target
);
638 g_signal_emit_by_name (player
, "fscommand", command
, load
->target_string
);
640 swfdec_player_unroot (player
, load
);
644 /* LAUNCH command (aka getURL) */
645 if (load
->target_string
&& swfdec_player_get_level (player
, load
->target_string
, 7) < 0) {
646 swfdec_player_launch (player
, load
->url
, load
->target_string
, load
->buffer
);
647 swfdec_player_unroot (player
, load
);
651 swfdec_player_allow_by_matrix (player
, load
->sandbox
, load
->url
,
652 swfdec_resource_matrix
, swfdec_resource_do_load
, load
);
655 /* NB: must be called from a script */
656 /* FIXME: 6 arguments?! */
658 swfdec_resource_load_internal (SwfdecPlayer
*player
,
659 SwfdecSpriteMovie
*target_movie
, const char *target_string
,
660 const char *url
, SwfdecBuffer
*buffer
, SwfdecMovieClipLoader
*loader
)
662 SwfdecResourceLoad
*load
;
664 g_assert (SWFDEC_AS_CONTEXT (player
)->frame
!= NULL
);
665 load
= g_slice_new (SwfdecResourceLoad
);
667 load
->sandbox
= SWFDEC_SANDBOX (SWFDEC_AS_CONTEXT (player
)->global
);
668 load
->url
= g_strdup (url
);
669 load
->target_movie
= target_movie
;
670 load
->target_string
= g_strdup (target_string
);
671 load
->buffer
= buffer
;
672 load
->loader
= loader
;
674 swfdec_player_root_full (player
, load
, swfdec_resource_load_mark
, swfdec_resource_load_free
);
675 swfdec_player_request_resource (player
, swfdec_resource_load_request
, load
, NULL
);
679 swfdec_resource_load_movie (SwfdecPlayer
*player
, const SwfdecAsValue
*target
,
680 const char *url
, SwfdecBuffer
*buffer
, SwfdecMovieClipLoader
*loader
)
685 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
686 g_return_val_if_fail (target
!= NULL
, FALSE
);
687 g_return_val_if_fail (url
!= NULL
, FALSE
);
688 g_return_val_if_fail (loader
== NULL
|| SWFDEC_IS_MOVIE_CLIP_LOADER (loader
), FALSE
);
690 if (SWFDEC_AS_VALUE_IS_OBJECT (target
)) {
691 SwfdecAsObject
*object
= SWFDEC_AS_VALUE_GET_OBJECT (target
);
692 if (SWFDEC_IS_SPRITE_MOVIE (object
)) {
693 swfdec_resource_load_internal (player
, SWFDEC_SPRITE_MOVIE (object
),
694 NULL
, url
, buffer
, loader
);
700 if (SWFDEC_AS_VALUE_IS_NUMBER (target
)) {
701 int i
= swfdec_as_double_to_integer (SWFDEC_AS_VALUE_GET_NUMBER (target
));
704 s
= swfdec_as_context_give_string (SWFDEC_AS_OBJECT (loader
)->context
,
705 g_strdup_printf ("_level%d", i
));
706 swfdec_resource_load_internal (player
, NULL
, s
, url
, buffer
, loader
);
708 } else if (SWFDEC_AS_VALUE_IS_STRING (target
) ||
709 (SWFDEC_AS_VALUE_IS_OBJECT (target
) && SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (target
)))) {
710 s
= swfdec_as_value_to_string (SWFDEC_AS_CONTEXT (player
), target
);
712 SWFDEC_WARNING ("target does not reference a movie, not loading %s", url
);
716 s
= swfdec_as_value_to_string (SWFDEC_AS_CONTEXT (player
), target
);
718 if (swfdec_player_get_level (player
, s
, SWFDEC_AS_CONTEXT (player
)->version
) >= 0) {
719 /* lowercase the string, so we can do case insensitive level lookups later on */
720 char *tmp
= g_ascii_strdown (s
, -1);
721 swfdec_resource_load_internal (player
, NULL
, tmp
, url
, buffer
, NULL
);
725 movie
= swfdec_player_get_movie_from_string (player
, s
);
726 if (SWFDEC_IS_SPRITE_MOVIE (movie
)) {
727 swfdec_resource_load_internal (player
, SWFDEC_SPRITE_MOVIE (movie
),
728 NULL
, url
, buffer
, loader
);
731 SWFDEC_WARNING ("%s does not reference a movie, not loading %s", s
, url
);
736 swfdec_resource_load (SwfdecPlayer
*player
, const char *target
,
737 const char *url
, SwfdecBuffer
*buffer
)
739 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
740 g_return_if_fail (target
!= NULL
);
741 g_return_if_fail (url
!= NULL
);
743 swfdec_resource_load_internal (player
, NULL
, target
, url
, buffer
, NULL
);
747 swfdec_resource_emit_on_load_init (SwfdecResource
*resource
)
749 g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource
), FALSE
);
751 if (resource
->state
!= SWFDEC_RESOURCE_COMPLETE
)
754 if (resource
->movie
&& SWFDEC_IS_IMAGE_DECODER (resource
->decoder
)) {
755 SwfdecImage
*image
= SWFDEC_IMAGE_DECODER (resource
->decoder
)->image
;
757 swfdec_movie_invalidate_next (SWFDEC_MOVIE (resource
->movie
));
758 swfdec_movie_queue_update (SWFDEC_MOVIE (resource
->movie
), SWFDEC_MOVIE_INVALID_EXTENTS
);
759 SWFDEC_MOVIE (resource
->movie
)->image
= g_object_ref (image
);
762 swfdec_resource_emit_signal (resource
, SWFDEC_AS_STR_onLoadInit
, FALSE
, NULL
, 0);
763 resource
->state
= SWFDEC_RESOURCE_DONE
;
764 /* free now unneeded resources */
765 resource
->clip_loader
= NULL
;
766 resource
->clip_loader_sandbox
= NULL
;