Benjamin Otte
2007-Jan-16 15:13 UTC
[Swfdec] 9 commits - libswfdec/js libswfdec/Makefile.am libswfdec/swfdec_audio_stream.c libswfdec/swfdec_audio_stream.h libswfdec/swfdec_cache.c libswfdec/swfdec_cached.c libswfdec/swfdec_cached.h libswfdec/swfdec_edittext_movie.c libswfdec/swfdec_image.c libswfdec/swfdec_image.h libswfdec/swfdec_js.c libswfdec/swfdec_js_color.c libswfdec/swfdec_js.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_net_stream.c libswfdec/swfdec_net_stream.h libswfdec/swfdec_scriptable.c libswfdec/swfdec_scriptable.h libswfdec/swfdec_sound.c libswfdec/swfdec_sound.h libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_types.h
libswfdec/Makefile.am | 4 libswfdec/js/jsapi.c | 6 - libswfdec/js/jsapi.h | 6 - libswfdec/js/jsfun.h | 2 libswfdec/js/jsinterp.c | 2 libswfdec/js/jsobj.c | 8 - libswfdec/js/jsobj.h | 6 - libswfdec/js/jspubtd.h | 4 libswfdec/js/jsscope.c | 2 libswfdec/js/jsscope.h | 2 libswfdec/swfdec_audio_stream.c | 13 +- libswfdec/swfdec_audio_stream.h | 2 libswfdec/swfdec_cache.c | 11 + libswfdec/swfdec_cached.c | 123 ++++++++++++++++++++++ libswfdec/swfdec_cached.h | 65 +++++++++++ libswfdec/swfdec_edittext_movie.c | 44 +++---- libswfdec/swfdec_image.c | 65 ++++------- libswfdec/swfdec_image.h | 32 ++--- libswfdec/swfdec_js.c | 41 +------ libswfdec/swfdec_js.h | 7 - libswfdec/swfdec_js_color.c | 2 libswfdec/swfdec_js_movie.c | 159 ++++++---------------------- libswfdec/swfdec_movie.c | 33 +++++ libswfdec/swfdec_movie.h | 9 - libswfdec/swfdec_net_stream.c | 2 libswfdec/swfdec_net_stream.h | 5 libswfdec/swfdec_scriptable.c | 154 +++++++++++++++++++++++++++ libswfdec/swfdec_scriptable.h | 66 +++++++++++ libswfdec/swfdec_sound.c | 210 ++++++++++++++++++-------------------- libswfdec/swfdec_sound.h | 20 +-- libswfdec/swfdec_swf_decoder.c | 7 - libswfdec/swfdec_types.h | 1 32 files changed, 698 insertions(+), 415 deletions(-) New commits: diff-tree 7005f0c65edf0177ea22cbb4514c7df1cbb099c1 (from 327ff632511845290eac307252b9e0441cb7fb43) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 22:38:58 2007 +0100 get the codec out of SwfdecSound and into the audio objects rationale: I want to be able to use different codecs if that becomes interesting and as such keep the codec selection as close as possible to the decoding process diff --git a/libswfdec/swfdec_audio_stream.c b/libswfdec/swfdec_audio_stream.c index b1dd5e1..58e2175 100644 --- a/libswfdec/swfdec_audio_stream.c +++ b/libswfdec/swfdec_audio_stream.c @@ -38,7 +38,7 @@ swfdec_audio_stream_dispose (GObject *ob SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (object); if (stream->decoder != NULL) { - SwfdecBuffer *buffer = swfdec_sound_finish_decoder (stream->sound, stream->decoder); + SwfdecBuffer *buffer = swfdec_audio_codec_finish (stream->codec, stream->decoder); stream->decoder = NULL; if (buffer) swfdec_buffer_unref (buffer); @@ -68,7 +68,7 @@ swfdec_audio_stream_decode_one (SwfdecAu /* FIXME: with this method and mad not giving out full samples, we end up * putting silence too early */ if (frame->sound_block) { - buffer = swfdec_sound_decode_buffer (stream->sound, stream->decoder, frame->sound_block); + buffer = swfdec_audio_codec_decode (stream->codec, stream->decoder, frame->sound_block); if (buffer == NULL) continue; } else { @@ -79,7 +79,7 @@ swfdec_audio_stream_decode_one (SwfdecAu g_queue_push_tail (stream->playback_queue, buffer); return buffer; } - buffer = swfdec_sound_finish_decoder (stream->sound, stream->decoder); + buffer = swfdec_audio_codec_finish (stream->codec, stream->decoder); stream->decoder = NULL; stream->done = TRUE; if (buffer) @@ -199,9 +199,12 @@ swfdec_audio_stream_new (SwfdecPlayer *p stream->sound = frame->sound_head; stream->playback_skip = frame->sound_skip; stream->current_frame = start_frame; - stream->decoder = swfdec_sound_init_decoder (stream->sound); + stream->codec = swfdec_codec_get_audio (stream->sound->format); + if (stream->codec) + stream->decoder = swfdec_audio_codec_init (stream->codec, + stream->sound->width, stream->sound->original_format); if (stream->decoder) - stream->format = swfdec_sound_get_decoder_format (stream->sound, stream->decoder); + stream->format = swfdec_audio_codec_get_format (stream->codec, stream->decoder); swfdec_audio_add (SWFDEC_AUDIO (stream), player); return SWFDEC_AUDIO (stream); diff --git a/libswfdec/swfdec_audio_stream.h b/libswfdec/swfdec_audio_stream.h index af2a0ba..8758462 100644 --- a/libswfdec/swfdec_audio_stream.h +++ b/libswfdec/swfdec_audio_stream.h @@ -23,6 +23,7 @@ #define _SWFDEC_AUDIO_STREAM_H_ #include <libswfdec/swfdec_audio_internal.h> +#include <libswfdec/swfdec_codec.h> G_BEGIN_DECLS @@ -42,6 +43,7 @@ struct _SwfdecAudioStream SwfdecSprite * sprite; /* sprite we're playing back */ SwfdecSound * sound; /* sound we're playing */ + const SwfdecAudioCodec *codec; /* codec used by this stream */ gpointer decoder; /* decoder used for this frame */ SwfdecAudioOut format; /* format used by decoder */ unsigned int playback_skip; /* number of samples to skip at the beginning of queue */ diff --git a/libswfdec/swfdec_sound.c b/libswfdec/swfdec_sound.c index 6e68f38..1620f5d 100644 --- a/libswfdec/swfdec_sound.c +++ b/libswfdec/swfdec_sound.c @@ -179,6 +179,7 @@ tag_func_define_sound (SwfdecSwfDecoder SwfdecBuffer * swfdec_sound_get_decoded (SwfdecSound *sound, SwfdecAudioOut *format) { + const SwfdecAudioCodec *codec; gpointer decoder; SwfdecBuffer *tmp, *tmp2; guint sample_bytes; @@ -193,19 +194,19 @@ swfdec_sound_get_decoded (SwfdecSound *s } if (sound->encoded == NULL) return NULL; - sound->codec = swfdec_codec_get_audio (sound->format); - if (sound->codec == NULL) + codec = swfdec_codec_get_audio (sound->format); + if (codec == NULL) return NULL; - decoder = swfdec_sound_init_decoder (sound); + decoder = swfdec_audio_codec_init (codec, sound->width, sound->original_format); if (decoder == NULL) return NULL; - sound->decoded_format = swfdec_sound_get_decoder_format (sound, decoder); + sound->decoded_format = swfdec_audio_codec_get_format (codec, decoder); sample_bytes = 2 * SWFDEC_AUDIO_OUT_N_CHANNELS (sound->decoded_format); /* FIXME: The size is only a guess */ swfdec_cached_load (SWFDEC_CACHED (sound), sound->n_samples * sample_bytes); - tmp = swfdec_sound_decode_buffer (sound, decoder, sound->encoded); - tmp2 = swfdec_sound_finish_decoder (sound, decoder); + tmp = swfdec_audio_codec_decode (codec, decoder, sound->encoded); + tmp2 = swfdec_audio_codec_finish (codec, decoder); if (tmp == NULL) { if (tmp2) { tmp = tmp2; @@ -307,10 +308,6 @@ tag_func_sound_stream_head (SwfdecSwfDec SWFDEC_WARNING ("unknown format %d", format); sound->format = format; } - sound->codec = swfdec_codec_get_audio (sound->format); - if (sound->codec == NULL) { - SWFDEC_WARNING ("No codec found for format %u", sound->format); - } return SWFDEC_STATUS_OK; } @@ -460,49 +457,6 @@ tag_func_define_button_sound (SwfdecSwfD return SWFDEC_STATUS_OK; } -gpointer -swfdec_sound_init_decoder (SwfdecSound * sound) -{ - g_assert (sound->decoded == NULL); - - if (sound->codec) - return swfdec_audio_codec_init (sound->codec, sound->width, sound->original_format); - else - return NULL; -} - -SwfdecBuffer * -swfdec_sound_finish_decoder (SwfdecSound * sound, gpointer data) -{ - g_assert (sound->decoded == NULL); - - if (sound->codec) - return swfdec_audio_codec_finish (sound->codec, data); - return NULL; -} - -SwfdecBuffer * -swfdec_sound_decode_buffer (SwfdecSound *sound, gpointer data, SwfdecBuffer *buffer) -{ - g_assert (sound->decoded == NULL); - - if (sound->codec) - return swfdec_audio_codec_decode (sound->codec, data, buffer); - else - return NULL; -} - -SwfdecAudioFormat -swfdec_sound_get_decoder_format (SwfdecSound *sound, gpointer data) -{ - g_assert (sound->decoded == NULL); - - if (sound->codec) - return swfdec_audio_codec_get_format (sound->codec, data); - else - return sound->original_format; -} - /** * swfdec_sound_buffer_get_n_samples: * @buffer: data to examine diff --git a/libswfdec/swfdec_sound.h b/libswfdec/swfdec_sound.h index 7101675..7bf26ec 100644 --- a/libswfdec/swfdec_sound.h +++ b/libswfdec/swfdec_sound.h @@ -64,7 +64,6 @@ struct _SwfdecSound SwfdecCached cached; SwfdecAudioFormat format; /* format in use */ - const SwfdecAudioCodec *codec; /* codec for this sound */ gboolean width; /* TRUE for 16bit, FALSE for 8bit */ SwfdecAudioOut original_format; /* channel/rate information */ unsigned int n_samples; /* total number of samples */ @@ -88,15 +87,6 @@ int tag_func_sound_stream_head (SwfdecSw int tag_func_start_sound (SwfdecSwfDecoder * s); int tag_func_define_button_sound (SwfdecSwfDecoder * s); -gpointer swfdec_sound_init_decoder (SwfdecSound * sound); -SwfdecBuffer * swfdec_sound_finish_decoder (SwfdecSound * sound, - gpointer data); -SwfdecBuffer * swfdec_sound_decode_buffer (SwfdecSound * sound, - gpointer data, - SwfdecBuffer * buffer); -SwfdecAudioFormat swfdec_sound_get_decoder_format (SwfdecSound * sound, - gpointer data); - void swfdec_sound_render (SwfdecSound * sound, gint16 * dest, unsigned int offset, diff-tree 327ff632511845290eac307252b9e0441cb7fb43 (from 3fe8fea8d9594e3a6bc52152a2fe77629fa59063) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 21:56:23 2007 +0100 use the cache makes SwfdecSound a SwfdecCached and decode sounds on demand. Has the nice side effect of keeping around the encoded sound should we later decide to extract it. (FIXME: make swfdec-extract do just that) diff --git a/libswfdec/swfdec_sound.c b/libswfdec/swfdec_sound.c index 061ba65..6e68f38 100644 --- a/libswfdec/swfdec_sound.c +++ b/libswfdec/swfdec_sound.c @@ -1,7 +1,7 @@ /* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> * 2005-2006 Eric Anholt <eric@anholt.net> - * 2006 Benjamin Otte <otte@gnome.org> + * 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,15 +32,26 @@ #include "swfdec_sprite.h" #include "swfdec_swf_decoder.h" -G_DEFINE_TYPE (SwfdecSound, swfdec_sound, SWFDEC_TYPE_CHARACTER) +G_DEFINE_TYPE (SwfdecSound, swfdec_sound, SWFDEC_TYPE_CACHED) + +static void +swfdec_sound_unload (SwfdecCached *cached) +{ + SwfdecSound * sound = SWFDEC_SOUND (cached); + + if (sound->decoded) { + swfdec_buffer_unref (sound->decoded); + sound->decoded = NULL; + } +} static void swfdec_sound_dispose (GObject *object) { SwfdecSound * sound = SWFDEC_SOUND (object); - if (sound->decoded) - swfdec_buffer_unref (sound->decoded); + if (sound->encoded) + swfdec_buffer_unref (sound->encoded); G_OBJECT_CLASS (swfdec_sound_parent_class)->dispose (object); } @@ -49,8 +60,11 @@ static void swfdec_sound_class_init (SwfdecSoundClass * g_class) { GObjectClass *object_class = G_OBJECT_CLASS (g_class); + SwfdecCachedClass *cached_class = SWFDEC_CACHED_CLASS (g_class); object_class->dispose = swfdec_sound_dispose; + + cached_class->unload = swfdec_sound_unload; } static void @@ -67,8 +81,6 @@ tag_func_sound_stream_block (SwfdecSwfDe int n_samples; int skip; - /* for MPEG, data starts after 4 byte header */ - sound = SWFDEC_SOUND (s->parse_sprite->frames[s->parse_sprite->parse_frame].sound_head); if (!sound) { @@ -114,8 +126,6 @@ tag_func_define_sound (SwfdecSwfDecoder int type; int n_samples; SwfdecSound *sound; - unsigned int skip = 0; - SwfdecBuffer *orig_buffer = NULL; id = swfdec_bits_get_u16 (b); format = swfdec_bits_getbits (b, 4); @@ -144,33 +154,68 @@ tag_func_define_sound (SwfdecSwfDecoder /* fall through */ case 3: sound->format = SWFDEC_AUDIO_FORMAT_UNCOMPRESSED; - orig_buffer = swfdec_bits_get_buffer (&s->b, -1); + sound->encoded = swfdec_bits_get_buffer (&s->b, -1); break; case 2: sound->format = SWFDEC_AUDIO_FORMAT_MP3; - /* FIXME: skip these samples */ - skip = swfdec_bits_get_u16 (b); - orig_buffer = swfdec_bits_get_buffer (&s->b, -1); + sound->skip = swfdec_bits_get_u16 (b); + sound->encoded = swfdec_bits_get_buffer (&s->b, -1); break; case 1: - sound->format = SWFDEC_AUDIO_FORMAT_ADPCM; - orig_buffer = swfdec_bits_get_buffer (&s->b, -1); - break; + case 5: case 6: - sound->format = SWFDEC_AUDIO_FORMAT_NELLYMOSER; - SWFDEC_WARNING ("Nellymoser compression not implemented"); + sound->format = format; + sound->encoded = swfdec_bits_get_buffer (&s->b, -1); break; default: SWFDEC_WARNING ("unknown format %d", format); sound->format = format; } + sound->n_samples *= rate; + + return SWFDEC_STATUS_OK; +} + +SwfdecBuffer * +swfdec_sound_get_decoded (SwfdecSound *sound, SwfdecAudioOut *format) +{ + gpointer decoder; + SwfdecBuffer *tmp, *tmp2; + guint sample_bytes; + + g_return_val_if_fail (SWFDEC_IS_SOUND (sound), NULL); + g_return_val_if_fail (format != NULL, NULL); + + if (sound->decoded) { + swfdec_cached_use (SWFDEC_CACHED (sound)); + *format = sound->decoded_format; + return sound->decoded; + } + if (sound->encoded == NULL) + return NULL; sound->codec = swfdec_codec_get_audio (sound->format); - if (sound->codec && orig_buffer) { - SwfdecBuffer *tmp, *tmp2; - gpointer data = swfdec_sound_init_decoder (sound); - sound->decoded_format = swfdec_sound_get_decoder_format (sound, data); - tmp = swfdec_sound_decode_buffer (sound, data, orig_buffer); - tmp2 = swfdec_sound_finish_decoder (sound, data); + if (sound->codec == NULL) + return NULL; + + decoder = swfdec_sound_init_decoder (sound); + if (decoder == NULL) + return NULL; + sound->decoded_format = swfdec_sound_get_decoder_format (sound, decoder); + sample_bytes = 2 * SWFDEC_AUDIO_OUT_N_CHANNELS (sound->decoded_format); + /* FIXME: The size is only a guess */ + swfdec_cached_load (SWFDEC_CACHED (sound), sound->n_samples * sample_bytes); + tmp = swfdec_sound_decode_buffer (sound, decoder, sound->encoded); + tmp2 = swfdec_sound_finish_decoder (sound, decoder); + if (tmp == NULL) { + if (tmp2) { + tmp = tmp2; + } else { + SWFDEC_ERROR ("got no data when decoding sound %u", + SWFDEC_CHARACTER (sound)->id); + swfdec_cached_unload (SWFDEC_CACHED (sound)); + return NULL; + } + } else { if (tmp2) { /* and all this code just because mad sucks... */ SwfdecBufferQueue *queue = swfdec_buffer_queue_new (); @@ -179,45 +224,33 @@ tag_func_define_sound (SwfdecSwfDecoder tmp = swfdec_buffer_queue_pull (queue, swfdec_buffer_queue_get_depth (queue)); swfdec_buffer_queue_free (queue); } - swfdec_buffer_unref (orig_buffer); - if (tmp) { - guint sample_bytes = 2 * SWFDEC_AUDIO_OUT_N_CHANNELS (sound->decoded_format); - SWFDEC_LOG ("after decoding, got %u samples, should get %u and skip %u", - tmp->length / sample_bytes, - sound->n_samples, skip); - if (skip) { - SwfdecBuffer *tmp2 = swfdec_buffer_new_subbuffer (tmp, skip * sample_bytes, - tmp->length - skip * sample_bytes); - swfdec_buffer_unref (tmp); - tmp = tmp2; - } - /* sound buffer may be bigger due to mp3 not having sample boundaries */ - if (tmp->length > sound->n_samples * sample_bytes) { - SwfdecBuffer *tmp2 = swfdec_buffer_new_subbuffer (tmp, 0, sound->n_samples * sample_bytes); - swfdec_buffer_unref (tmp); - tmp = tmp2; - } - /* only assign here, the decoding code checks this variable */ - sound->decoded = tmp; - if (tmp->length < sound->n_samples * sample_bytes) { - /* we handle this case in swfdec_sound_render */ - /* FIXME: this message is important when writing new codecs, so I made it a warning. - * It's probably not worth more than INFO for the usual case though */ - SWFDEC_WARNING ("%u samples in %u bytes should be available, but only %u bytes are", - sound->n_samples, sound->n_samples * sample_bytes, tmp->length); - } - } else { - SWFDEC_ERROR ("failed decoding given data in format %u", format); - } } - sound->n_samples *= rate; - if (sound->decoded == NULL) { - SWFDEC_ERROR ("defective sound object (id %d)", SWFDEC_CHARACTER (sound)->id); - s->characters = g_list_remove (s->characters, sound); - g_object_unref (sound); + SWFDEC_LOG ("after decoding, got %u samples, should get %u and skip %u", + tmp->length / sample_bytes, sound->n_samples, sound->skip); + if (sound->skip) { + SwfdecBuffer *tmp2 = swfdec_buffer_new_subbuffer (tmp, sound->skip * sample_bytes, + tmp->length - sound->skip * sample_bytes); + swfdec_buffer_unref (tmp); + tmp = tmp2; + } + /* sound buffer may be bigger due to mp3 not having sample boundaries */ + if (tmp->length > sound->n_samples * sample_bytes) { + SwfdecBuffer *tmp2 = swfdec_buffer_new_subbuffer (tmp, 0, sound->n_samples * sample_bytes); + swfdec_buffer_unref (tmp); + tmp = tmp2; + } + if (tmp->length < sound->n_samples * sample_bytes) { + /* we handle this case in swfdec_sound_render */ + /* FIXME: this message is important when writing new codecs, so I made it a warning. + * It's probably not worth more than INFO for the usual case though */ + SWFDEC_WARNING ("%u samples in %u bytes should be available, but only %u bytes are", + sound->n_samples, sound->n_samples * sample_bytes, tmp->length); } + /* only assign here, the decoding code checks this variable */ + sound->decoded = tmp; - return SWFDEC_STATUS_OK; + *format = sound->decoded_format; + return sound->decoded; } int @@ -621,9 +654,14 @@ void swfdec_sound_render (SwfdecSound *sound, gint16 *dest, unsigned int offset, unsigned int n_samples) { + SwfdecBuffer *buffer; + SwfdecAudioOut format; g_return_if_fail (SWFDEC_IS_SOUND (sound)); - g_return_if_fail (sound->decoded != NULL); + /* FIXME: I need a return_if_fail for !created_by_define_sound */ - swfdec_sound_buffer_render (dest, sound->decoded, sound->decoded_format, + buffer = swfdec_sound_get_decoded (sound, &format); + if (buffer == NULL) + return; + swfdec_sound_buffer_render (dest, buffer, format, NULL, offset, n_samples); } diff --git a/libswfdec/swfdec_sound.h b/libswfdec/swfdec_sound.h index 1032b6b..7101675 100644 --- a/libswfdec/swfdec_sound.h +++ b/libswfdec/swfdec_sound.h @@ -1,7 +1,7 @@ /* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> * 2005-2006 Eric Anholt <eric@anholt.net> - * 2006 Benjamin Otte <otte@gnome.org> + * 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ #ifndef _SWFDEC_SOUND_H_ #define _SWFDEC_SOUND_H_ -#include <libswfdec/swfdec_character.h> +#include <libswfdec/swfdec_cached.h> #include <libswfdec/swfdec_codec.h> #include <libswfdec/swfdec_swf_decoder.h> #include <libswfdec/swfdec_types.h> @@ -61,13 +61,15 @@ struct _SwfdecSoundChunk struct _SwfdecSound { - SwfdecCharacter character; + SwfdecCached cached; SwfdecAudioFormat format; /* format in use */ const SwfdecAudioCodec *codec; /* codec for this sound */ gboolean width; /* TRUE for 16bit, FALSE for 8bit */ SwfdecAudioOut original_format; /* channel/rate information */ unsigned int n_samples; /* total number of samples */ + unsigned int skip; /* samples to skip at start */ + SwfdecBuffer * encoded; /* encoded data */ SwfdecAudioOut decoded_format; /* format of decoded data */ SwfdecBuffer * decoded; /* decoded data */ @@ -75,7 +77,7 @@ struct _SwfdecSound struct _SwfdecSoundClass { - SwfdecCharacterClass character_class; + SwfdecCachedClass cached_class; }; GType swfdec_sound_get_type (void); diff-tree 3fe8fea8d9594e3a6bc52152a2fe77629fa59063 (from 5f2def54b59ff4937c94f6366206aaf29933f682) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 21:52:08 2007 +0100 rename swfdec_cached_reload to swfdec_cached_use diff --git a/libswfdec/swfdec_cached.c b/libswfdec/swfdec_cached.c index ef5ea24..aa6a694 100644 --- a/libswfdec/swfdec_cached.c +++ b/libswfdec/swfdec_cached.c @@ -92,7 +92,7 @@ swfdec_cached_load (SwfdecCached *cached } void -swfdec_cached_reload (SwfdecCached *cached) +swfdec_cached_use (SwfdecCached *cached) { g_return_if_fail (SWFDEC_IS_CACHED (cached)); g_return_if_fail (cached->handle.unload != NULL); diff --git a/libswfdec/swfdec_cached.h b/libswfdec/swfdec_cached.h index 5f40877..bc9a1f7 100644 --- a/libswfdec/swfdec_cached.h +++ b/libswfdec/swfdec_cached.h @@ -55,7 +55,7 @@ GType swfdec_cached_get_type (void); void swfdec_cached_load (SwfdecCached * cached, guint size); -void swfdec_cached_reload (SwfdecCached * cached); +void swfdec_cached_use (SwfdecCached * cached); void swfdec_cached_unload (SwfdecCached * cached); void swfdec_cached_set_cache (SwfdecCached * cached, SwfdecCache * cache); diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c index 64daf19..6c2dcae 100644 --- a/libswfdec/swfdec_image.c +++ b/libswfdec/swfdec_image.c @@ -597,7 +597,7 @@ swfdec_image_get_surface (SwfdecImage *i g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL); if (image->surface) { - swfdec_cached_reload (SWFDEC_CACHED (image)); + swfdec_cached_use (SWFDEC_CACHED (image)); return image->surface; } diff-tree 5f2def54b59ff4937c94f6366206aaf29933f682 (from 89329b9198530b63a11129990780439dd2cf99f8) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 14:46:10 2007 +0100 add new class SwfdecCached SwfdecCached is used by characters that can have their contents dynamically decoded and use a SwfdecCache. Make SwfdecImage use it. SwfdecSound will follow diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am index 8ab165c..485f97f 100644 --- a/libswfdec/Makefile.am +++ b/libswfdec/Makefile.am @@ -25,6 +25,7 @@ libswfdec_@SWFDEC_MAJORMINOR@_la_SOURCES swfdec_button.c \ swfdec_button_movie.c \ swfdec_cache.c \ + swfdec_cached.c \ swfdec_character.c \ swfdec_codec.c \ swfdec_codec_adpcm.c \ @@ -104,6 +105,7 @@ noinst_HEADERS = \ swfdec_button.h \ swfdec_button_movie.h \ swfdec_cache.h \ + swfdec_cached.h \ swfdec_character.h \ swfdec_codec.h \ swfdec_color.h \ diff --git a/libswfdec/swfdec_cached.c b/libswfdec/swfdec_cached.c new file mode 100644 index 0000000..ef5ea24 --- /dev/null +++ b/libswfdec/swfdec_cached.c @@ -0,0 +1,123 @@ +/* Swfdec + * Copyright (C) 2007 Benjamin Otte <otte@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "swfdec_cached.h" +#include "swfdec_debug.h" + + +G_DEFINE_ABSTRACT_TYPE (SwfdecCached, swfdec_cached, SWFDEC_TYPE_CHARACTER) + +static void +swfdec_cached_dispose (GObject *object) +{ + SwfdecCached * cached = SWFDEC_CACHED (object); + + swfdec_cached_unload (cached); + + G_OBJECT_CLASS (swfdec_cached_parent_class)->dispose (object); +} + +static void +swfdec_cached_class_init (SwfdecCachedClass * g_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (g_class); + + object_class->dispose = swfdec_cached_dispose; +} + +static void +swfdec_cached_init (SwfdecCached * cached) +{ +} + +void +swfdec_cached_set_cache (SwfdecCached *cached, SwfdecCache *cache) +{ + g_return_if_fail (SWFDEC_IS_CACHED (cached)); + g_return_if_fail (cache != NULL); + + if (cached->cache) { + if (cached->handle.unload) + swfdec_cache_remove_handle (cached->cache, &cached->handle); + swfdec_cache_unref (cached->cache); + } + cached->cache = cache; + if (cache) { + swfdec_cache_ref (cache); + if (cached->handle.unload) + swfdec_cache_add_handle (cached->cache, &cached->handle); + } +} + +static void +swfdec_cached_unload_func (gpointer data) +{ + SwfdecCached *cached = SWFDEC_CACHED (data - G_STRUCT_OFFSET (SwfdecCached, handle)); + + cached->handle.unload = NULL; + swfdec_cached_unload (cached); +} + +void +swfdec_cached_load (SwfdecCached *cached, guint size) +{ + g_return_if_fail (SWFDEC_IS_CACHED (cached)); + g_return_if_fail (cached->handle.unload == NULL); + g_return_if_fail (size > 0); + + cached->handle.unload = swfdec_cached_unload_func; + cached->handle.size = size; + if (cached->cache) + swfdec_cache_add_handle (cached->cache, &cached->handle); +} + +void +swfdec_cached_reload (SwfdecCached *cached) +{ + g_return_if_fail (SWFDEC_IS_CACHED (cached)); + g_return_if_fail (cached->handle.unload != NULL); + + if (cached->cache) + swfdec_cache_add_handle (cached->cache, &cached->handle); +} + +void +swfdec_cached_unload (SwfdecCached *cached) +{ + g_return_if_fail (SWFDEC_IS_CACHED (cached)); + + if (cached->handle.unload) { + if (cached->cache) + swfdec_cache_remove_handle (cached->cache, &cached->handle); + cached->handle.unload = NULL; + } + if (cached->handle.size) { + SwfdecCachedClass *klass; + + klass = SWFDEC_CACHED_GET_CLASS (cached); + cached->handle.size = 0; + g_return_if_fail (klass->unload != NULL); + klass->unload (cached); + } +} + diff --git a/libswfdec/swfdec_cached.h b/libswfdec/swfdec_cached.h new file mode 100644 index 0000000..5f40877 --- /dev/null +++ b/libswfdec/swfdec_cached.h @@ -0,0 +1,65 @@ +/* Swfdec + * Copyright (c) 2007 Benjamin Otte <otte@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef _SWFDEC_CACHED_H_ +#define _SWFDEC_CACHED_H_ + +#include <cairo.h> +#include <libswfdec/swfdec_cache.h> +#include <libswfdec/swfdec_character.h> + +G_BEGIN_DECLS + +typedef struct _SwfdecCached SwfdecCached; +typedef struct _SwfdecCachedClass SwfdecCachedClass; + +#define SWFDEC_TYPE_CACHED (swfdec_cached_get_type()) +#define SWFDEC_IS_CACHED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_CACHED)) +#define SWFDEC_IS_CACHED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_CACHED)) +#define SWFDEC_CACHED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_CACHED, SwfdecCached)) +#define SWFDEC_CACHED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_CACHED, SwfdecCachedClass)) +#define SWFDEC_CACHED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_CACHED, SwfdecCachedClass)) + + +struct _SwfdecCached { + SwfdecCharacter character; + + SwfdecCache * cache; /* cache to use for cached */ + SwfdecCacheHandle handle; /* handle to unload surface */ +}; + +struct _SwfdecCachedClass +{ + SwfdecCharacterClass character_class; + + void (* unload) (SwfdecCached * cached); +}; + +GType swfdec_cached_get_type (void); + +void swfdec_cached_load (SwfdecCached * cached, + guint size); +void swfdec_cached_reload (SwfdecCached * cached); +void swfdec_cached_unload (SwfdecCached * cached); +void swfdec_cached_set_cache (SwfdecCached * cached, + SwfdecCache * cache); + + +G_END_DECLS +#endif diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c index a08d2d4..64daf19 100644 --- a/libswfdec/swfdec_image.c +++ b/libswfdec/swfdec_image.c @@ -40,12 +40,12 @@ static void swfdec_image_colormap_decode unsigned char *dest, unsigned char *src, unsigned char *colormap, int colormap_len); -G_DEFINE_TYPE (SwfdecImage, swfdec_image, SWFDEC_TYPE_CHARACTER) +G_DEFINE_TYPE (SwfdecImage, swfdec_image, SWFDEC_TYPE_CACHED) static void -swfdec_image_unload (gpointer data) +swfdec_image_unload (SwfdecCached *cached) { - SwfdecImage *image = SWFDEC_IMAGE (data - G_STRUCT_OFFSET (SwfdecImage, handle)); + SwfdecImage *image = SWFDEC_IMAGE (cached); if (image->surface) { cairo_surface_destroy (image->surface); @@ -58,7 +58,6 @@ swfdec_image_dispose (GObject *object) { SwfdecImage * image = SWFDEC_IMAGE (object); - swfdec_image_unload (&image->handle); if (image->jpegtables) { swfdec_buffer_unref (image->jpegtables); image->jpegtables = NULL; @@ -75,14 +74,16 @@ static void swfdec_image_class_init (SwfdecImageClass * g_class) { GObjectClass *object_class = G_OBJECT_CLASS (g_class); + SwfdecCachedClass *cached_class = SWFDEC_CACHED_CLASS (g_class); object_class->dispose = swfdec_image_dispose; + + cached_class->unload = swfdec_image_unload; } static void swfdec_image_init (SwfdecImage * image) { - image->handle.unload = swfdec_image_unload; } @@ -211,9 +212,11 @@ swfdec_image_jpeg_load (SwfdecImage *ima image->raw_data->length - 2); jpeg_rgb_decoder_parse (dec); jpeg_rgb_decoder_get_image_size (dec, &image->width, &image->height); - image->handle.size = 4 * image->width * image->height; - if (image->cache) - swfdec_cache_add_handle (image->cache, &image->handle); + if (image->width == 0 || image->height == 0) { + jpeg_rgb_decoder_free (dec); + return; + } + swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); jpeg_rgb_decoder_get_image (dec, &image_data, &image->rowstride, NULL, NULL); jpeg_rgb_decoder_free (dec); @@ -257,9 +260,11 @@ swfdec_image_jpeg2_load (SwfdecImage *im image->raw_data->length - 2); jpeg_rgb_decoder_parse (dec); jpeg_rgb_decoder_get_image_size (dec, &image->width, &image->height); - image->handle.size = 4 * image->width * image->height; - if (image->cache) - swfdec_cache_add_handle (image->cache, &image->handle); + if (image->width == 0 || image->height == 0) { + jpeg_rgb_decoder_free (dec); + return; + } + swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); jpeg_rgb_decoder_get_image (dec, &image_data, &image->rowstride, &image->width, &image->height); jpeg_rgb_decoder_free (dec); @@ -318,9 +323,11 @@ swfdec_image_jpeg3_load (SwfdecImage *im jpeg_rgb_decoder_addbits (dec, bits.ptr, jpeg_length); jpeg_rgb_decoder_parse (dec); jpeg_rgb_decoder_get_image_size (dec, &image->width, &image->height); - image->handle.size = 4 * image->width * image->height; - if (image->cache) - swfdec_cache_add_handle (image->cache, &image->handle); + if (image->width == 0 || image->height == 0) { + jpeg_rgb_decoder_free (dec); + return; + } + swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); jpeg_rgb_decoder_get_image (dec, &image_data, &image->rowstride, &image->width, &image->height); jpeg_rgb_decoder_free (dec); @@ -385,9 +392,6 @@ swfdec_image_lossless_load (SwfdecImage SWFDEC_LOG (" width = %d", image->width); image->height = swfdec_bits_get_u16 (&bits); SWFDEC_LOG (" height = %d", image->height); - image->handle.size = 4 * image->width * image->height; - if (image->cache) - swfdec_cache_add_handle (image->cache, &image->handle); if (format == 3) { color_table_size = swfdec_bits_get_u8 (&bits) + 1; } else { @@ -399,6 +403,9 @@ swfdec_image_lossless_load (SwfdecImage SWFDEC_LOG ("height = %d", image->height); SWFDEC_LOG ("color_table_size = %d", color_table_size); + if (image->width == 0 || image->height == 0) + return; + swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); ptr = lossless (bits.ptr, endptr - bits.ptr, &len); bits.ptr = endptr; @@ -590,8 +597,7 @@ swfdec_image_get_surface (SwfdecImage *i g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL); if (image->surface) { - if (image->cache) - swfdec_cache_add_handle (image->cache, &image->handle); + swfdec_cached_reload (SWFDEC_CACHED (image)); return image->surface; } @@ -617,27 +623,6 @@ swfdec_image_get_surface (SwfdecImage *i break; } - g_assert (image->handle.size); - g_assert (image->surface); return image->surface; } -void -swfdec_image_set_cache (SwfdecImage *image, SwfdecCache *cache) -{ - g_return_if_fail (SWFDEC_IS_IMAGE (image)); - g_return_if_fail (cache != NULL); - - if (image->cache) { - if (image->surface) - swfdec_cache_remove_handle (image->cache, &image->handle); - swfdec_cache_unref (image->cache); - } - image->cache = cache; - if (cache) { - swfdec_cache_ref (cache); - if (image->surface) - swfdec_cache_add_handle (image->cache, &image->handle); - } -} - diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h index 2fa7a68..af230f2 100644 --- a/libswfdec/swfdec_image.h +++ b/libswfdec/swfdec_image.h @@ -23,8 +23,7 @@ #define _SWFDEC_IMAGE_H_ #include <cairo.h> -#include <libswfdec/swfdec_cache.h> -#include <libswfdec/swfdec_character.h> +#include <libswfdec/swfdec_cached.h> #include <libswfdec/swfdec_decoder.h> G_BEGIN_DECLS @@ -46,34 +45,27 @@ typedef enum { SWFDEC_IMAGE_TYPE_LOSSLESS2, } SwfdecImageType; -struct _SwfdecImage -{ - SwfdecCharacter character; +struct _SwfdecImage { + SwfdecCached cached; cairo_surface_t * surface; /* surface that is on-demand loaded */ - SwfdecCache * cache; /* cache to use for image */ - SwfdecCacheHandle handle; /* handle to unload surface */ - - int width, height; - int rowstride; - - SwfdecBuffer *jpegtables; - SwfdecBuffer *raw_data; - - SwfdecImageType type; + int width; + int height; + int rowstride; + + SwfdecImageType type; + SwfdecBuffer * jpegtables; + SwfdecBuffer * raw_data; }; -struct _SwfdecImageClass -{ - SwfdecCharacterClass character_class; +struct _SwfdecImageClass { + SwfdecCachedClass cached_class; }; GType swfdec_image_get_type (void); cairo_surface_t * swfdec_image_get_surface (SwfdecImage * image); -void swfdec_image_set_cache (SwfdecImage * image, - SwfdecCache * cache); int swfdec_image_jpegtables (SwfdecSwfDecoder * s); int tag_func_define_bits_jpeg (SwfdecSwfDecoder * s); diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c index 60bc99e..e7be205 100644 --- a/libswfdec/swfdec_swf_decoder.c +++ b/libswfdec/swfdec_swf_decoder.c @@ -32,8 +32,8 @@ #include "swfdec_swf_decoder.h" #include "swfdec.h" #include "swfdec_bits.h" +#include "swfdec_cached.h" #include "swfdec_debug.h" -#include "swfdec_image.h" #include "swfdec_js.h" #include "swfdec_player_internal.h" #include "swfdec_sprite.h" @@ -457,9 +457,8 @@ swfdec_swf_decoder_create_character (Swf g_assert (SWFDEC_DECODER (s)->player); SWFDEC_SPRITE (result)->player = SWFDEC_DECODER (s)->player; } - /* FIXME: generalize this for cache-using classes */ - if (SWFDEC_IS_IMAGE (result)) { - swfdec_image_set_cache (SWFDEC_IMAGE (result), SWFDEC_DECODER (s)->player->cache); + if (SWFDEC_IS_CACHED (result)) { + swfdec_cached_set_cache (SWFDEC_CACHED (result), SWFDEC_DECODER (s)->player->cache); } return result; diff-tree 89329b9198530b63a11129990780439dd2cf99f8 (from 56c277e18cee8bf64152e1ad3e5f7e2af5b1ec5f) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 14:44:02 2007 +0100 call unload function after adjusting size This way the unload function can do with the handle what it likes (including freeing it) Also add some debugging diff --git a/libswfdec/swfdec_cache.c b/libswfdec/swfdec_cache.c index 6881337..0620b51 100644 --- a/libswfdec/swfdec_cache.c +++ b/libswfdec/swfdec_cache.c @@ -22,7 +22,8 @@ #include "config.h" #endif -#include <swfdec_cache.h> +#include "swfdec_cache.h" +#include "swfdec_debug.h" SwfdecCache * swfdec_cache_new (unsigned int max_size) @@ -77,8 +78,10 @@ swfdec_cache_shrink (SwfdecCache *cache, while (cache->usage > max_usage) { SwfdecCacheHandle *handle = g_queue_pop_tail (cache->queue); g_assert (handle); - handle->unload (handle); cache->usage -= handle->size; + SWFDEC_LOG ("%p removing %p (%u => %u)", cache, handle, + cache->usage + handle->size, cache->usage); + handle->unload (handle); } } @@ -111,6 +114,8 @@ swfdec_cache_add_handle (SwfdecCache *ca swfdec_cache_shrink (cache, cache->max_size - handle->size); g_queue_push_head (cache->queue, (gpointer) handle); cache->usage += handle->size; + SWFDEC_LOG ("%p adding %p (%u => %u)", cache, handle, + cache->usage - handle->size, cache->usage); } } @@ -136,5 +141,7 @@ swfdec_cache_remove_handle (SwfdecCache if (list) { g_queue_delete_link (cache->queue, list); cache->usage -= handle->size; + SWFDEC_LOG ("%p removing %p (%u => %u)", cache, handle, + cache->usage + handle->size, cache->usage); } } diff-tree 56c277e18cee8bf64152e1ad3e5f7e2af5b1ec5f (from 097b676f528d2d0e5c0a972823cdffdf4e9b0134) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 11:57:12 2007 +0100 make SwfdecNetStream a SwfdecScriptable (nothing else changed) diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c index 21458d5..eee3f72 100644 --- a/libswfdec/swfdec_net_stream.c +++ b/libswfdec/swfdec_net_stream.c @@ -200,7 +200,7 @@ swfdec_net_stream_input_finalize (Swfdec /*** SWFDEC_NET_STREAM ***/ -G_DEFINE_TYPE_WITH_CODE (SwfdecNetStream, swfdec_net_stream, G_TYPE_OBJECT, +G_DEFINE_TYPE_WITH_CODE (SwfdecNetStream, swfdec_net_stream, SWFDEC_TYPE_SCRIPTABLE, G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_LOADER_TARGET, swfdec_net_stream_loader_target_init)) static void diff --git a/libswfdec/swfdec_net_stream.h b/libswfdec/swfdec_net_stream.h index 97de110..cf5fd5a 100644 --- a/libswfdec/swfdec_net_stream.h +++ b/libswfdec/swfdec_net_stream.h @@ -23,6 +23,7 @@ #include <libswfdec/swfdec.h> #include <libswfdec/swfdec_flv_decoder.h> #include <libswfdec/swfdec_player_internal.h> +#include <libswfdec/swfdec_scriptable.h> #include <libswfdec/swfdec_video_movie.h> G_BEGIN_DECLS @@ -39,7 +40,7 @@ typedef struct _SwfdecNetStreamClass Swf struct _SwfdecNetStream { - GObject object; + SwfdecScriptable scriptable; SwfdecPlayer * player; /* the player we play in */ SwfdecLoader * loader; /* input connection */ @@ -63,7 +64,7 @@ struct _SwfdecNetStream struct _SwfdecNetStreamClass { - GObjectClass object_class; + SwfdecScriptableClass scriptable_class; }; GType swfdec_net_stream_get_type (void); diff-tree 097b676f528d2d0e5c0a972823cdffdf4e9b0134 (from a98207b6015a3cfbbd3fc287ad6aaa6e7dc39938) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 11:54:24 2007 +0100 Add a SwfdecScriptable class that functions as the frontend for objects accessible from AS Make SwfdecMovie a SwfdecScriptable diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am index 08e39de..8ab165c 100644 --- a/libswfdec/Makefile.am +++ b/libswfdec/Makefile.am @@ -63,6 +63,7 @@ libswfdec_@SWFDEC_MAJORMINOR@_la_SOURCES swfdec_rect.c \ swfdec_ringbuffer.c \ swfdec_root_movie.c \ + swfdec_scriptable.c \ swfdec_shape.c \ swfdec_sound.c \ swfdec_sprite.c \ @@ -131,6 +132,7 @@ noinst_HEADERS = \ swfdec_rect.h \ swfdec_ringbuffer.h \ swfdec_root_movie.h \ + swfdec_scriptable.h \ swfdec_shape.h \ swfdec_sound.h \ swfdec_sprite.h \ diff --git a/libswfdec/swfdec_edittext_movie.c b/libswfdec/swfdec_edittext_movie.c index 872f7f9..421f6bc 100644 --- a/libswfdec/swfdec_edittext_movie.c +++ b/libswfdec/swfdec_edittext_movie.c @@ -68,24 +68,23 @@ static void swfdec_edit_text_movie_iterate (SwfdecMovie *movie) { SwfdecEditTextMovie *text = SWFDEC_EDIT_TEXT_MOVIE (movie); - SwfdecPlayer *player; + SwfdecScriptable *parent; + JSObject *jsobj; jsval val; const char *s; if (text->text->variable == NULL) return; - player = SWFDEC_ROOT_MOVIE (movie->root)->player; - if (movie->parent->jsobj == NULL) { - swfdec_js_add_movie (movie->parent); - if (movie->parent->jsobj == NULL) - return; - } - val = swfdec_js_eval (player->jscx, movie->parent->jsobj, text->text->variable); + parent = SWFDEC_SCRIPTABLE (movie->parent); + jsobj = swfdec_scriptable_get_object (parent); + if (jsobj == NULL) + return; + val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable); if (JSVAL_IS_VOID (val)) return; - s = swfdec_js_to_string (player->jscx, val); + s = swfdec_js_to_string (parent->jscx, val); if (!s && !text->str) return; if (s && text->str && g_str_equal (s, text->str)) @@ -98,31 +97,28 @@ static void swfdec_edit_text_movie_init_movie (SwfdecMovie *movie) { SwfdecEditTextMovie *text = SWFDEC_EDIT_TEXT_MOVIE (movie); - SwfdecPlayer *player; - JSObject *object; + SwfdecScriptable *parent; + JSObject *jsobj; JSString *string; jsval val; if (text->text->variable == NULL) return; - player = SWFDEC_ROOT_MOVIE (movie->root)->player; - if (movie->parent->jsobj == NULL) { - swfdec_js_add_movie (movie->parent); - if (movie->parent->jsobj == NULL) - return; - } - object = movie->parent->jsobj; + parent = SWFDEC_SCRIPTABLE (movie->parent); + jsobj = swfdec_scriptable_get_object (parent); + if (jsobj == NULL) + return; if (text->text->variable_prefix) { - val = swfdec_js_eval (player->jscx, object, text->text->variable_prefix); + val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix); if (!JSVAL_IS_OBJECT (val)) return; - object = JSVAL_TO_OBJECT (val); + jsobj = JSVAL_TO_OBJECT (val); } - if (!JS_GetProperty (player->jscx, object, text->text->variable_name, &val)) + if (!JS_GetProperty (parent->jscx, jsobj, text->text->variable_name, &val)) return; if (!JSVAL_IS_VOID (val)) { - const char *s = swfdec_js_to_string (player->jscx, val); + const char *s = swfdec_js_to_string (parent->jscx, val); if (!s && !text->str) return; if (s && text->str && g_str_equal (s, text->str)) @@ -134,11 +130,11 @@ swfdec_edit_text_movie_init_movie (Swfde SWFDEC_LOG ("setting variable %s (%s) to \"%s\"", text->text->variable_name, text->text->variable, text->str ? text->str : ""); - string = JS_NewStringCopyZ (player->jscx, text->str ? text->str : ""); + string = JS_NewStringCopyZ (parent->jscx, text->str ? text->str : ""); if (string == NULL) return; val = STRING_TO_JSVAL (string); - JS_SetProperty (player->jscx, object, text->text->variable_name, &val); + JS_SetProperty (parent->jscx, jsobj, text->text->variable_name, &val); } static void diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 3824fb6..4ce01a5 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -130,29 +130,6 @@ swfdec_js_finish_player (SwfdecPlayer *p } } -JSBool -swfdec_js_push_state (SwfdecMovie *movie) -{ - SwfdecPlayer *player = SWFDEC_ROOT_MOVIE (movie->root)->player; - JSBool old_case, new_case; - - old_case = JS_GetContextCaseSensitive (player->jscx); - if (SWFDEC_IS_SWF_DECODER (SWFDEC_ROOT_MOVIE (movie->root)->decoder)) - new_case = SWFDEC_SWF_DECODER (SWFDEC_ROOT_MOVIE (movie->root)->decoder)->version >= 7 ? - JS_TRUE : JS_FALSE; - else - new_case = JS_TRUE; - JS_SetContextCaseSensitive (player->jscx, new_case); - return old_case; -} - -void -swfdec_js_pop_state (SwfdecMovie *movie, JSBool state) -{ - SwfdecPlayer *player = SWFDEC_ROOT_MOVIE (movie->root)->player; - JS_SetContextCaseSensitive (player->jscx, state); -} - /** * swfdec_js_execute_script: * @s: a @SwfdecPlayer @@ -171,7 +148,8 @@ swfdec_js_execute_script (SwfdecPlayer * JSScript *script, jsval *rval) { jsval returnval = JSVAL_VOID; - JSBool ret, old_state; + JSObject *jsobj; + JSBool ret; g_return_val_if_fail (s != NULL, FALSE); g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), FALSE); @@ -183,20 +161,13 @@ swfdec_js_execute_script (SwfdecPlayer * } if (rval == NULL) rval = &returnval; - if (movie->jsobj == NULL) { - swfdec_js_add_movie (movie); - if (movie->jsobj == NULL) - return FALSE; - } - /* setup execution state */ - old_state = swfdec_js_push_state (movie); - ret = JS_ExecuteScript (s->jscx, movie->jsobj, script, rval); - - /* restore execution state */ - swfdec_js_pop_state (movie, old_state); + if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) + return FALSE; + ret = JS_ExecuteScript (s->jscx, jsobj, script, rval); if (!ret) { SWFDEC_WARNING ("executing script %p for movie %s failed", script, movie->name); } + if (ret && returnval != JSVAL_VOID) { JSString * str = JS_ValueToString (s->jscx, returnval); if (str) diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h index acf9392..ced8046 100644 --- a/libswfdec/swfdec_js.h +++ b/libswfdec/swfdec_js.h @@ -36,10 +36,6 @@ gboolean swfdec_js_execute_script (Swfde gboolean swfdec_js_run (SwfdecPlayer * player, const char * s, jsval * rval); -/* FIXME: someone figure out if case sensitivity is global or per-movie */ -JSBool swfdec_js_push_state (SwfdecMovie * movie); -void swfdec_js_pop_state (SwfdecMovie * movie, - JSBool state); void swfdec_js_add_color (SwfdecPlayer * player); void swfdec_js_add_globals (SwfdecPlayer * player); @@ -47,9 +43,6 @@ void swfdec_js_add_mouse (SwfdecPlayer void swfdec_js_add_movieclip_class (SwfdecPlayer * player); void swfdec_js_add_sound (SwfdecPlayer * player); -SwfdecMovie * swfdec_js_val_to_movie (JSContext * cx, - jsval val); -gboolean swfdec_js_add_movie (SwfdecMovie * movie); void swfdec_js_movie_add_property (SwfdecMovie * movie); void swfdec_js_movie_remove_property (SwfdecMovie * movie); diff --git a/libswfdec/swfdec_js_color.c b/libswfdec/swfdec_js_color.c index b72d3c3..a117118 100644 --- a/libswfdec/swfdec_js_color.c +++ b/libswfdec/swfdec_js_color.c @@ -180,7 +180,7 @@ swfdec_js_color_new (JSContext *cx, JSOb SwfdecMovie *movie; JSObject *new; - movie = swfdec_js_val_to_movie (cx, argv[0]); + movie = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_INFO ("attempted to construct a color without a movie"); return JS_TRUE; diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c index 8b85bb8..30eb161 100644 --- a/libswfdec/swfdec_js_movie.c +++ b/libswfdec/swfdec_js_movie.c @@ -1,7 +1,7 @@ /* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> * 2005-2006 Eric Anholt <eric@anholt.net> - * 2006 Benjamin Otte <otte@gnome.org> + * 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,30 +39,12 @@ JSBool swfdec_js_global_eval (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); -static void -movie_finalize (JSContext *cx, JSObject *obj) -{ - SwfdecMovie *movie; - - movie = JS_GetPrivate (cx, obj); - /* since we also finalize the class, not everyone has a private object */ - if (movie) { - g_assert (movie->jsobj != NULL); - - SWFDEC_LOG ("destroying JSObject %p for movie %p", obj, movie); - movie->jsobj = NULL; - g_object_unref (movie); - } else { - SWFDEC_LOG ("destroying JSObject %p", obj); - } -} - -static JSClass movieclip_class = { +const JSClass movieclip_class = { "MovieClip", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, - JS_ConvertStub, movie_finalize, + JS_ConvertStub, swfdec_scriptable_finalize, JSCLASS_NO_OPTIONAL_MEMBERS }; @@ -213,9 +195,9 @@ mc_hitTest (JSContext *cx, JSObject *obj if (argc == 1) { SwfdecMovie *other; - other = swfdec_js_val_to_movie (cx, argv[0]); + other = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE); if (other == NULL) { - g_assert_not_reached (); + SWFDEC_ERROR ("FIXME: what happens now?"); return JS_TRUE; } other = SWFDEC_MOVIE (JS_GetPrivate(cx, JSVAL_TO_OBJECT (argv[0]))); @@ -251,10 +233,11 @@ swfdec_js_getProperty (JSContext *cx, JS { uint32 id; SwfdecMovie *movie; + JSObject *jsobj; jsval tmp; swfdec_js_global_eval (cx, obj, 1, argv, &tmp); - movie = swfdec_js_val_to_movie (cx, tmp); + movie = swfdec_scriptable_from_jsval (cx, tmp, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("specified target does not reference a movie clip"); return JS_TRUE; @@ -265,10 +248,9 @@ swfdec_js_getProperty (JSContext *cx, JS if (id > 19) return JS_FALSE; - if (movie->jsobj == NULL && - !swfdec_js_add_movie (movie)) + if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) return JS_FALSE; - return movieclip_props[id].getter (cx, movie->jsobj, INT_TO_JSVAL (id) /* FIXME */, rval); + return movieclip_props[id].getter (cx, jsobj, INT_TO_JSVAL (id) /* FIXME */, rval); } static JSBool @@ -277,9 +259,10 @@ swfdec_js_setProperty (JSContext *cx, JS uint32 id; SwfdecMovie *movie; jsval tmp; + JSObject *jsobj; swfdec_js_global_eval (cx, obj, 1, argv, &tmp); - movie = swfdec_js_val_to_movie (cx, tmp); + movie = swfdec_scriptable_from_jsval (cx, tmp, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("specified target does not reference a movie clip"); return JS_TRUE; @@ -290,11 +273,10 @@ swfdec_js_setProperty (JSContext *cx, JS if (id > 19) return JS_FALSE; - if (movie->jsobj == NULL && - !swfdec_js_add_movie (movie)) + if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) return JS_FALSE; *rval = argv[2]; - return movieclip_props[id].setter (cx, movie->jsobj, INT_TO_JSVAL (id) /* FIXME */, rval); + return movieclip_props[id].setter (cx, jsobj, INT_TO_JSVAL (id) /* FIXME */, rval); } static JSBool @@ -351,7 +333,7 @@ swfdec_js_movie_swapDepths (JSContext *c g_assert (movie); if (JSVAL_IS_OBJECT (argv[0])) { - other = swfdec_js_val_to_movie (cx, argv[0]); + other = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE); if (other == NULL) return JS_TRUE; if (other->parent != movie->parent) @@ -433,11 +415,11 @@ swfdec_js_movie_duplicateMovieClip (JSCo ret = swfdec_movie_new (movie->parent, content); g_object_weak_ref (G_OBJECT (ret), (GWeakNotify) swfdec_content_free, content); /* must be set by now, the movie has a name */ - if (ret->jsobj == NULL) + if (SWFDEC_SCRIPTABLE (ret)->jsobj == NULL) return JS_FALSE; swfdec_js_copy_props (ret, movie); SWFDEC_LOG ("duplicated %s as %s to depth %u", movie->name, ret->name, ret->depth); - *rval = OBJECT_TO_JSVAL (ret->jsobj); + *rval = OBJECT_TO_JSVAL (SWFDEC_SCRIPTABLE (ret)->jsobj); return JS_TRUE; } @@ -980,6 +962,7 @@ static JSBool mc_parent (JSContext *cx, JSObject *obj, jsval id, jsval *vp) { SwfdecMovie *movie; + JSObject *jsobj; movie = JS_GetPrivate (cx, obj); g_assert (movie); @@ -988,12 +971,11 @@ mc_parent (JSContext *cx, JSObject *obj, if (movie->parent) movie = movie->parent; - if (movie->jsobj == NULL) - swfdec_js_add_movie (movie); - if (movie->jsobj == NULL) + jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)); + if (jsobj == NULL) return JS_FALSE; - - *vp = OBJECT_TO_JSVAL (movie->jsobj); + + *vp = OBJECT_TO_JSVAL (jsobj); return JS_TRUE; } @@ -1002,21 +984,17 @@ static JSBool mc_root (JSContext *cx, JSObject *obj, jsval id, jsval *vp) { SwfdecMovie *movie; + JSObject *jsobj; movie = JS_GetPrivate (cx, obj); g_assert (movie); movie = movie->root; - if (movie->jsobj == NULL) { - /* the root movie only holds this as long as there's no parent */ - movie = movie->list->data; - if (movie->jsobj == NULL) - swfdec_js_add_movie (movie); - } - if (movie->jsobj == NULL) + jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)); + if (jsobj == NULL) return JS_FALSE; - *vp = OBJECT_TO_JSVAL (movie->jsobj); + *vp = OBJECT_TO_JSVAL (jsobj); return JS_TRUE; } @@ -1185,112 +1163,47 @@ swfdec_js_add_movieclip_class (SwfdecPla void swfdec_js_movie_add_property (SwfdecMovie *movie) { - JSBool state; + SwfdecScriptable *script = SWFDEC_SCRIPTABLE (movie); jsval val; JSObject *jsobj; JSContext *cx; - if (movie->jsobj == NULL) { - if (!swfdec_js_add_movie (movie)) - return; - } - val = OBJECT_TO_JSVAL (movie->jsobj); - cx = SWFDEC_ROOT_MOVIE (movie->root)->player->jscx; + jsobj = swfdec_scriptable_get_object (script); + val = OBJECT_TO_JSVAL (jsobj); + cx = script->jscx; if (movie->parent) { - jsobj = movie->parent->jsobj; + jsobj = SWFDEC_SCRIPTABLE (movie->parent)->jsobj; if (jsobj == NULL) return; SWFDEC_LOG ("setting %s as property for %s", movie->name, movie->parent->name); } else { - jsobj = SWFDEC_ROOT_MOVIE (movie->root)->player->jsobj; + jsobj = SWFDEC_ROOT_MOVIE (movie)->player->jsobj; SWFDEC_LOG ("setting %s as property for _global", movie->name); } - state = swfdec_js_push_state (movie); JS_SetProperty (cx, jsobj, movie->name, &val); - swfdec_js_pop_state (movie, state); } void swfdec_js_movie_remove_property (SwfdecMovie *movie) { - JSBool state; + SwfdecScriptable *script = SWFDEC_SCRIPTABLE (movie); JSObject *jsobj; JSContext *cx; - if (movie->jsobj == NULL) + if (script->jsobj == NULL) return; - cx = SWFDEC_ROOT_MOVIE (movie->root)->player->jscx; + cx = script->jscx; if (movie->parent) { - jsobj = movie->parent->jsobj; + jsobj = SWFDEC_SCRIPTABLE (movie->parent)->jsobj; if (jsobj == NULL) return; } else { - jsobj = SWFDEC_ROOT_MOVIE (movie->root)->player->jsobj; + jsobj = SWFDEC_ROOT_MOVIE (movie)->player->jsobj; } SWFDEC_LOG ("removing %s as property", movie->name); - state = swfdec_js_push_state (movie); JS_DeleteProperty (cx, jsobj, movie->name); - swfdec_js_pop_state (movie, state); -} - -/** - * swfdec_js_add_movie: - * @movie: a #SwfdecMovie - * - * Ensures that a JSObject for the given @movie exists. - **/ -gboolean -swfdec_js_add_movie (SwfdecMovie *movie) -{ - JSContext *cx; - GList *walk; - - g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), FALSE); - g_return_val_if_fail (movie->jsobj == NULL, FALSE); - - cx = SWFDEC_ROOT_MOVIE (movie->root)->player->jscx; - - movie->jsobj = JS_NewObject (cx, &movieclip_class, NULL, NULL); - if (movie->jsobj == NULL) { - SWFDEC_ERROR ("failed to create JS object for movie %p", movie); - return FALSE; - } - SWFDEC_LOG ("created JSObject %p for movie %p", movie->jsobj, movie); - g_object_ref (movie); - JS_SetPrivate (cx, movie->jsobj, movie); - /* add all children */ - for (walk = movie->list; walk; walk = walk->next) { - SwfdecMovie *child = walk->data; - if (child->has_name) - swfdec_js_movie_add_property (child); - } - return TRUE; -} - -/** - * swfdec_js_val_to_movie: - * @cx: the relevant #JSContext - * @val: value hat might reference a #SwfdecMovie - * - * Extracts the #SwfdecMovie referenced by @val and returns it. This function - * performs all the necessary error checking to ensure that @val really - * references a movie. - * - * Returns: the movie referenced or NULL if no movie was referenced. - **/ -SwfdecMovie * -swfdec_js_val_to_movie (JSContext *cx, jsval val) -{ - JSObject *object; - - if (!JSVAL_IS_OBJECT (val)) - return NULL; - object = JSVAL_TO_OBJECT (val); - if (JS_GetClass (object) != &movieclip_class) - return NULL; - return JS_GetPrivate (cx, object); } diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c index 2d52336..16ff859 100644 --- a/libswfdec/swfdec_movie.c +++ b/libswfdec/swfdec_movie.c @@ -1,5 +1,5 @@ /* Swfdec - * Copyright (C) 2006 Benjamin Otte <otte@gnome.org> + * Copyright (C) 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,7 +38,7 @@ static const SwfdecContent default_content = SWFDEC_CONTENT_DEFAULT; -G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, G_TYPE_OBJECT) +G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_SCRIPTABLE) static void swfdec_movie_init (SwfdecMovie * movie) @@ -308,7 +308,7 @@ swfdec_movie_destroy (SwfdecMovie *movie if (movie->parent) { movie->parent->list = g_list_remove (movie->parent->list, movie); } - if (movie->jsobj) + if (SWFDEC_SCRIPTABLE (movie)->jsobj) swfdec_js_movie_remove_property (movie); player->movies = g_list_remove (player->movies, movie); g_object_unref (movie); @@ -607,7 +607,6 @@ swfdec_movie_dispose (GObject *object) { SwfdecMovie * movie = SWFDEC_MOVIE (object); - g_assert (movie->jsobj == NULL); g_assert (movie->list == NULL); g_assert (movie->content == &default_content); @@ -626,13 +625,37 @@ swfdec_movie_iterate_end (SwfdecMovie *m g_list_find (movie->parent->list, movie) != NULL; } +static JSObject * +swfdec_movie_create_js_object (SwfdecScriptable *script) +{ + GList *walk; + JSObject *ret; + + ret = SWFDEC_SCRIPTABLE_CLASS (swfdec_movie_parent_class)->create_js_object (script); + if (ret == NULL) + return NULL; + script->jsobj = ret; + /* add all children */ + for (walk = SWFDEC_MOVIE (script)->list; walk; walk = walk->next) { + SwfdecMovie *child = walk->data; + if (child->has_name) + swfdec_js_movie_add_property (child); + } + return ret; +} + +extern const JSClass movieclip_class; static void swfdec_movie_class_init (SwfdecMovieClass * movie_class) { GObjectClass *object_class = G_OBJECT_CLASS (movie_class); + SwfdecScriptableClass *script_class = SWFDEC_SCRIPTABLE_CLASS (movie_class); object_class->dispose = swfdec_movie_dispose; + script_class->jsclass = &movieclip_class; + script_class->create_js_object = swfdec_movie_create_js_object; + movie_class->iterate_end = swfdec_movie_iterate_end; } @@ -723,6 +746,7 @@ swfdec_movie_new (SwfdecMovie *parent, c g_return_val_if_fail (klass->create_movie != NULL, NULL); ret = klass->create_movie (content->graphic); ret->parent = parent; + SWFDEC_SCRIPTABLE (ret)->jscx = SWFDEC_SCRIPTABLE (parent)->jscx; g_object_ref (parent); ret->root = parent->root; swfdec_movie_initialize (ret, content); @@ -742,6 +766,7 @@ swfdec_movie_new_for_player (SwfdecPlaye ret = g_object_new (SWFDEC_TYPE_ROOT_MOVIE, NULL); g_object_weak_ref (G_OBJECT (ret), (GWeakNotify) swfdec_content_free, content); SWFDEC_ROOT_MOVIE (ret)->player = player; + SWFDEC_SCRIPTABLE (ret)->jscx = player->jscx; ret->root = ret; swfdec_movie_initialize (ret, content); ret->has_name = FALSE; diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h index 7787ee1..61f495c 100644 --- a/libswfdec/swfdec_movie.h +++ b/libswfdec/swfdec_movie.h @@ -1,5 +1,5 @@ /* Swfdec - * Copyright (C) 2006 Benjamin Otte <otte@gnome.org> + * Copyright (C) 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,8 +25,8 @@ #include <libswfdec/swfdec.h> #include <libswfdec/swfdec_rect.h> #include <libswfdec/swfdec_event.h> +#include <libswfdec/swfdec_scriptable.h> #include <libswfdec/swfdec_types.h> -#include <libswfdec/js/jspubtd.h> G_BEGIN_DECLS @@ -75,11 +75,10 @@ typedef enum { } SwfdecMovieState; struct _SwfdecMovie { - GObject object; + SwfdecScriptable scriptable; char * name; /* name used in to_string */ gboolean has_name; /* TRUE if name wasn't given automagically */ - JSObject * jsobj; /* our object in javascript */ GList * list; /* our contained movie clips (ordered by depth) */ int depth; /* depth of movie (equals content->depth unless explicitly set) */ const SwfdecContent * content; /* the content we are displaying */ @@ -116,7 +115,7 @@ struct _SwfdecMovie { }; struct _SwfdecMovieClass { - GObjectClass object_class; + SwfdecScriptableClass scriptable_class; /* general vfuncs */ void (* init_movie) (SwfdecMovie * movie); diff --git a/libswfdec/swfdec_scriptable.c b/libswfdec/swfdec_scriptable.c new file mode 100644 index 0000000..479bad9 --- /dev/null +++ b/libswfdec/swfdec_scriptable.c @@ -0,0 +1,154 @@ +/* Swfdec + * Copyright (C) 2007 Benjamin Otte <otte@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "swfdec_scriptable.h" +#include "swfdec_debug.h" +#include "js/jsapi.h" + +G_DEFINE_ABSTRACT_TYPE (SwfdecScriptable, swfdec_scriptable, G_TYPE_OBJECT) + +static void +swfdec_scriptable_dispose (GObject *object) +{ + SwfdecScriptable *script = SWFDEC_SCRIPTABLE (object); + + g_assert (script->jsobj == NULL); + + G_OBJECT_CLASS (swfdec_scriptable_parent_class)->dispose (object); +} + +static JSObject * +swfdec_scriptable_create_js_object (SwfdecScriptable *scriptable) +{ + SwfdecScriptableClass *klass; + JSContext *cx; + JSObject *obj; + + klass = SWFDEC_SCRIPTABLE_GET_CLASS (scriptable); + g_return_val_if_fail (klass->jsclass != NULL, NULL); + cx = scriptable->jscx; + + obj = JS_NewObject (cx, (JSClass *) klass->jsclass, NULL, NULL); + if (obj == NULL) { + SWFDEC_ERROR ("failed to create JS object for %s %p", + G_OBJECT_TYPE_NAME (scriptable), scriptable); + return NULL; + } + SWFDEC_LOG ("created JSObject %p for %s %p", obj, + G_OBJECT_TYPE_NAME (scriptable), scriptable); + g_object_ref (scriptable); + JS_SetPrivate (cx, obj, scriptable); + return obj; +} + +static void +swfdec_scriptable_class_init (SwfdecScriptableClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = swfdec_scriptable_dispose; + + klass->create_js_object = swfdec_scriptable_create_js_object; +} + +static void +swfdec_scriptable_init (SwfdecScriptable *stream) +{ +} + +/*** PUBLIC API ***/ + +/** + * swfdec_scriptable_finalize: + * @cx: a #JSContext + * @obj: a #JSObject to finalize + * + * This function is intended to be used as the finalizer in the #JSClass used + * by a scriptable subtype. + **/ +void +swfdec_scriptable_finalize (JSContext *cx, JSObject *obj) +{ + SwfdecScriptable *script; + + script = JS_GetPrivate (cx, obj); + /* since we also finalize the prototype, not everyone has a private object */ + if (script) { + g_assert (SWFDEC_IS_SCRIPTABLE (script)); + g_assert (script->jsobj != NULL); + + SWFDEC_LOG ("destroying JSObject %p for %s %p", obj, + G_OBJECT_TYPE_NAME (script), script); + script->jsobj = NULL; + g_object_unref (script); + } else { + SWFDEC_LOG ("destroying JSObject %p without Scriptable (probably a prototype)", obj); + } +} + +JSObject * +swfdec_scriptable_get_object (SwfdecScriptable *scriptable) +{ + SwfdecScriptableClass *klass; + + g_return_val_if_fail (SWFDEC_IS_SCRIPTABLE (scriptable), NULL); + + if (scriptable->jsobj) + return scriptable->jsobj; + klass = SWFDEC_SCRIPTABLE_GET_CLASS (scriptable); + g_return_val_if_fail (klass->create_js_object, NULL); + scriptable->jsobj = klass->create_js_object (scriptable); + + return scriptable->jsobj; +} + +/** + * swfdec_scriptable_from_jsval: + * @cx: a #JSContext + * @val: the jsval to convert + * @type: type of the object to get. + * + * Converts the given value @val to a #SwfdecScriptable, if it represents one. + * The object must be of @type, otherwise %NULL will be returned. + * + * Returns: the scriptable represented by @val or NULL if @val does not + * reference a @scriptable + **/ +gpointer +swfdec_scriptable_from_jsval (JSContext *cx, jsval val, GType type) +{ + SwfdecScriptableClass *klass; + JSObject *object; + + g_return_val_if_fail (g_type_is_a (type, SWFDEC_TYPE_SCRIPTABLE), NULL); + + if (!JSVAL_IS_OBJECT (val)) + return NULL; + object = JSVAL_TO_OBJECT (val); + klass = g_type_class_peek (type); + if (klass == NULL) + return NULL; /* class doesn't exist -> no object of this type exists */ + if (!JS_InstanceOf (cx, object, klass->jsclass, NULL)) + return NULL; + return JS_GetPrivate (cx, object); +} diff --git a/libswfdec/swfdec_scriptable.h b/libswfdec/swfdec_scriptable.h new file mode 100644 index 0000000..45190c4 --- /dev/null +++ b/libswfdec/swfdec_scriptable.h @@ -0,0 +1,66 @@ +/* Swfdec + * Copyright (C) 2007 Benjamin Otte <otte@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef _SWFDEC_SCRIPTABLE_H_ +#define _SWFDEC_SCRIPTABLE_H_ + +#include <libswfdec/swfdec.h> +#include <libswfdec/swfdec_types.h> +#include <libswfdec/js/jspubtd.h> + +G_BEGIN_DECLS + +//typedef struct _SwfdecScriptable SwfdecScriptable; +typedef struct _SwfdecScriptableClass SwfdecScriptableClass; + +#define SWFDEC_TYPE_SCRIPTABLE (swfdec_scriptable_get_type()) +#define SWFDEC_IS_SCRIPTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_SCRIPTABLE)) +#define SWFDEC_IS_SCRIPTABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_SCRIPTABLE)) +#define SWFDEC_SCRIPTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_SCRIPTABLE, SwfdecScriptable)) +#define SWFDEC_SCRIPTABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_SCRIPTABLE, SwfdecScriptableClass)) +#define SWFDEC_SCRIPTABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_SCRIPTABLE, SwfdecScriptableClass)) + +struct _SwfdecScriptable { + GObject object; + + JSContext * jscx; /* context for jsobj */ + JSObject * jsobj; /* JS object belonging to us or NULL if none */ +}; + +struct _SwfdecScriptableClass { + GObjectClass object_class; + + const JSClass * jsclass; /* class used by objects of this type (filled by subclasses) */ + /* the default should be good enough most of the time */ + JSObject * (* create_js_object) (SwfdecScriptable * scriptable); +}; + +GType swfdec_scriptable_get_type (void); + +void swfdec_scriptable_finalize (JSContext * cx, + JSObject * obj); + +JSObject * swfdec_scriptable_get_object (SwfdecScriptable * scriptable); +gpointer swfdec_scriptable_from_jsval (JSContext * cx, + jsval val, + GType type); + + +G_END_DECLS +#endif diff --git a/libswfdec/swfdec_types.h b/libswfdec/swfdec_types.h index 774486e..49212d5 100644 --- a/libswfdec/swfdec_types.h +++ b/libswfdec/swfdec_types.h @@ -44,6 +44,7 @@ typedef struct _SwfdecShape SwfdecShape; typedef struct _SwfdecShapeVec SwfdecShapeVec; typedef struct _SwfdecRect SwfdecRect; typedef struct _SwfdecRootMovie SwfdecRootMovie; +typedef struct _SwfdecScriptable SwfdecScriptable; typedef struct _SwfdecSound SwfdecSound; typedef struct _SwfdecSoundChunk SwfdecSoundChunk; typedef struct _SwfdecSprite SwfdecSprite; diff-tree a98207b6015a3cfbbd3fc287ad6aaa6e7dc39938 (from 80aba02f5745e1aaa6cbf16370dfcda5f8bb5d9d) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 11:45:22 2007 +0100 apparently we need even more const diff --git a/libswfdec/js/jsapi.c b/libswfdec/js/jsapi.c index b98e232..e33b846 100644 --- a/libswfdec/js/jsapi.c +++ b/libswfdec/js/jsapi.c @@ -1889,7 +1889,7 @@ JS_FinalizeStub(JSContext *cx, JSObject JS_PUBLIC_API(JSObject *) JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, - JSClass *clasp, JSNative constructor, uintN nargs, + const JSClass *clasp, JSNative constructor, uintN nargs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs) { @@ -1979,7 +1979,7 @@ JS_GetClass(JSObject *obj) #endif JS_PUBLIC_API(JSBool) -JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv) +JS_InstanceOf(JSContext *cx, JSObject *obj, const JSClass *clasp, jsval *argv) { JSFunction *fun; diff --git a/libswfdec/js/jsapi.h b/libswfdec/js/jsapi.h index 1718acc..9cc1dd0 100644 --- a/libswfdec/js/jsapi.h +++ b/libswfdec/js/jsapi.h @@ -877,7 +877,7 @@ struct JSFunctionSpec { extern JS_PUBLIC_API(JSObject *) JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, - JSClass *clasp, JSNative constructor, uintN nargs, + const JSClass *clasp, JSNative constructor, uintN nargs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs); @@ -894,7 +894,7 @@ JS_GetClass(JSObject *obj); #endif extern JS_PUBLIC_API(JSBool) -JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv); +JS_InstanceOf(JSContext *cx, JSObject *obj, const JSClass *clasp, jsval *argv); extern JS_PUBLIC_API(void *) JS_GetPrivate(JSContext *cx, JSObject *obj); diff --git a/libswfdec/js/jsfun.h b/libswfdec/js/jsfun.h index 1a36d6b..5dad235 100644 --- a/libswfdec/js/jsfun.h +++ b/libswfdec/js/jsfun.h @@ -58,7 +58,7 @@ struct JSFunction { uint8 flags; /* bound method and other flags, see jsapi.h */ uint8 spare; /* reserved for future use */ JSAtom *atom; /* name for diagnostics and decompiling */ - JSClass *clasp; /* if non-null, constructor for this class */ + const JSClass *clasp; /* if non-null, constructor for this class */ void *priv; }; diff --git a/libswfdec/js/jsinterp.c b/libswfdec/js/jsinterp.c index a9b4982..ff45d22 100644 --- a/libswfdec/js/jsinterp.c +++ b/libswfdec/js/jsinterp.c @@ -1393,7 +1393,7 @@ js_Interpret(JSContext *cx, jsval *resul JSString *str, *str2; jsint i, j; jsdouble d, d2; - JSClass *clasp, *funclasp; + const JSClass *clasp, *funclasp; JSFunction *fun; JSType type; #ifdef DEBUG diff-tree 80aba02f5745e1aaa6cbf16370dfcda5f8bb5d9d (from e6fa9c03b3333781cfaa260d0001885c1527e368) Author: Benjamin Otte <otte@gnome.org> Date: Tue Jan 16 10:01:06 2007 +0100 constify JSClass functions as far as we need them diff --git a/libswfdec/js/jsapi.c b/libswfdec/js/jsapi.c index 75194b7..b98e232 100644 --- a/libswfdec/js/jsapi.c +++ b/libswfdec/js/jsapi.c @@ -2098,7 +2098,7 @@ JS_GetObjectId(JSContext *cx, JSObject * } JS_PUBLIC_API(JSObject *) -JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent) +JS_NewObject(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *parent) { CHECK_REQUEST(cx); if (!clasp) diff --git a/libswfdec/js/jsapi.h b/libswfdec/js/jsapi.h index 441bf74..1718acc 100644 --- a/libswfdec/js/jsapi.h +++ b/libswfdec/js/jsapi.h @@ -930,7 +930,7 @@ extern JS_PUBLIC_API(JSBool) JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp); extern JS_PUBLIC_API(JSObject *) -JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); +JS_NewObject(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *parent); extern JS_PUBLIC_API(JSBool) JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep); diff --git a/libswfdec/js/jsobj.c b/libswfdec/js/jsobj.c index e7bb433..2033c97 100644 --- a/libswfdec/js/jsobj.c +++ b/libswfdec/js/jsobj.c @@ -1692,7 +1692,7 @@ JS_FRIEND_DATA(JSObjectOps) js_WithObjec }; static JSObjectOps * -with_getObjectOps(JSContext *cx, JSClass *clasp) +with_getObjectOps(JSContext *cx, const JSClass *clasp) { return &js_WithObjectOps; } @@ -1782,7 +1782,7 @@ js_InitObjectClass(JSContext *cx, JSObje void js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp) + const JSClass *clasp) { map->nrefs = nrefs; map->ops = ops; @@ -1792,7 +1792,7 @@ js_InitObjectMap(JSObjectMap *map, jsref JSObjectMap * js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp, JSObject *obj) + const JSClass *clasp, JSObject *obj) { return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj); } @@ -1830,7 +1830,7 @@ GetClassPrototype(JSContext *cx, JSObjec JSObject **protop); JSObject * -js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent) +js_NewObject(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *parent) { JSObject *obj, *ctor; JSObjectOps *ops; diff --git a/libswfdec/js/jsobj.h b/libswfdec/js/jsobj.h index fd7b665..c358d79 100644 --- a/libswfdec/js/jsobj.h +++ b/libswfdec/js/jsobj.h @@ -277,11 +277,11 @@ extern const char js_lookupSetter_str[]; extern void js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp); + const JSClass *clasp); extern JSObjectMap * js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp, JSObject *obj); + const JSClass *clasp, JSObject *obj); extern void js_DestroyObjectMap(JSContext *cx, JSObjectMap *map); @@ -293,7 +293,7 @@ extern JSObjectMap * js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj); extern JSObject * -js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); +js_NewObject(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *parent); extern JSObject * js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, diff --git a/libswfdec/js/jspubtd.h b/libswfdec/js/jspubtd.h index 9dbfdff..1112e58 100644 --- a/libswfdec/js/jspubtd.h +++ b/libswfdec/js/jspubtd.h @@ -271,7 +271,7 @@ typedef void * code and data used by the native (js_ObjectOps, see jsobj.c) ops. */ typedef JSObjectOps * -(* JS_DLL_CALLBACK JSGetObjectOps)(JSContext *cx, JSClass *clasp); +(* JS_DLL_CALLBACK JSGetObjectOps)(JSContext *cx, const JSClass *clasp); /* * JSClass.checkAccess type: check whether obj[id] may be accessed per mode, @@ -343,7 +343,7 @@ typedef uint32 */ typedef JSObjectMap * (* JS_DLL_CALLBACK JSNewObjectMapOp)(JSContext *cx, jsrefcount nrefs, - JSObjectOps *ops, JSClass *clasp, + JSObjectOps *ops, const JSClass *clasp, JSObject *obj); /* diff --git a/libswfdec/js/jsscope.c b/libswfdec/js/jsscope.c index 20243e9..4b85a66 100644 --- a/libswfdec/js/jsscope.c +++ b/libswfdec/js/jsscope.c @@ -132,7 +132,7 @@ CreateScopeTable(JSScope *scope) } JSScope * -js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp, +js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, const JSClass *clasp, JSObject *obj) { JSScope *scope; diff --git a/libswfdec/js/jsscope.h b/libswfdec/js/jsscope.h index 4f66441..5d5ca45 100644 --- a/libswfdec/js/jsscope.h +++ b/libswfdec/js/jsscope.h @@ -336,7 +336,7 @@ extern JSScope * js_GetMutableScope(JSContext *cx, JSObject *obj); extern JSScope * -js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp, +js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, const JSClass *clasp, JSObject *obj); extern void
Reasonably Related Threads
- 17 commits - libswfdec/js libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c libswfdec/swfdec_js.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_root_movie.c
- 4 commits - configure.ac libswfdec/swfdec_as_internal.h libswfdec/swfdec_as_object.h libswfdec/swfdec_scriptable.c libswfdec/swfdec_scriptable.h NEWS
- Branch 'as' - 16 commits - configure.ac libswfdec/Makefile.am libswfdec/swfdec_as_context.c libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_function.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_script_function.c
- 7 commits - libswfdec/swfdec_connection.c libswfdec/swfdec_js_connection.c libswfdec/swfdec_js_movie.c libswfdec/swfdec_js_net_stream.c libswfdec/swfdec_js_xml.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_scriptable.c libswfdec/swfdec_scriptable.h
- 11 commits - libswfdec/Makefile.am libswfdec/swfdec_connection.c libswfdec/swfdec_connection.h libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_js.c libswfdec/swfdec_js_connection.c libswfdec/swfdec_js.h libswfdec/swfdec_js_net_stream.c