[Swfdec] 11 commits - libswfdec/swfdec_event.c libswfdec/swfdec_event.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_scriptable.c libswfdec/swfdec_scriptable.h libswfdec/swfdec_script.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_swf_decoder.h libswfdec/swfdec_tag.c player/swfdec_player_manager.c test/dump.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Wed Mar 7 02:24:09 PST 2007


 libswfdec/swfdec_event.c       |   90 +++++++++++++++++++++++++++++++++---
 libswfdec/swfdec_event.h       |    3 +
 libswfdec/swfdec_js_movie.c    |    6 +-
 libswfdec/swfdec_movie.c       |   24 +++++++--
 libswfdec/swfdec_script.c      |    2 
 libswfdec/swfdec_scriptable.c  |   68 +++++++++++++++++++++++++++
 libswfdec/swfdec_scriptable.h  |    6 ++
 libswfdec/swfdec_sprite.c      |  102 ++++++++++++++++++++---------------------
 libswfdec/swfdec_sprite.h      |    3 -
 libswfdec/swfdec_swf_decoder.c |   39 +++------------
 libswfdec/swfdec_swf_decoder.h |    8 +--
 libswfdec/swfdec_tag.c         |    3 -
 player/swfdec_player_manager.c |   69 ++++++++++++++++-----------
 test/dump.c                    |   68 ++++++++++++---------------
 test/trace/Makefile.am         |    2 
 15 files changed, 323 insertions(+), 170 deletions(-)

New commits:
diff-tree ca675ea7b69b11cbc58c1ee4ea94e95a50ef4a90 (from b83df26d3c0ff337c64e3108907b4b8f8f674805)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 21:30:53 2007 +0100

    update to list -> hash table change in SwfdecSwfDecoder

diff --git a/test/dump.c b/test/dump.c
index efddeee..e248729 100644
--- a/test/dump.c
+++ b/test/dump.c
@@ -317,43 +317,39 @@ dump_image (SwfdecImage *image)
 }
 
 static void 
-dump_objects (SwfdecSwfDecoder *s)
+dump_object (gpointer key, gpointer value, gpointer unused)
 {
-  GList *g;
-  SwfdecCharacter *c;
+  SwfdecCharacter *c = value;
 
-  for (g = g_list_last (s->characters); g; g = g->prev) {
-    c = g->data;
-    g_print ("%d: %s\n", c->id, G_OBJECT_TYPE_NAME (c));
-    if (verbose && SWFDEC_IS_GRAPHIC (c)) {
-      SwfdecGraphic *graphic = SWFDEC_GRAPHIC (c);
-      g_print ("  extents: %g %g  %g %g\n", graphic->extents.x0, graphic->extents.y0,
-	  graphic->extents.x1, graphic->extents.y1);
-    }
-    if (SWFDEC_IS_IMAGE (c)) {
-      dump_image (SWFDEC_IMAGE (c));
-    }
-    if (SWFDEC_IS_SPRITE (c)) {
-      dump_sprite (SWFDEC_SPRITE (c));
-    }
-    if (SWFDEC_IS_SHAPE(c)) {
-      dump_shape(SWFDEC_SHAPE(c));
-    }
-    if (SWFDEC_IS_TEXT (c)) {
-      dump_text (SWFDEC_TEXT (c));
-    }
-    if (SWFDEC_IS_EDIT_TEXT (c)) {
-      dump_edit_text (SWFDEC_EDIT_TEXT (c));
-    }
-    if (SWFDEC_IS_FONT (c)) {
-      dump_font (SWFDEC_FONT (c));
-    }
-    if (SWFDEC_IS_BUTTON (c)) {
-      dump_button (SWFDEC_BUTTON (c));
-    }
-    if (SWFDEC_IS_SOUND (c)) {
-      dump_sound (SWFDEC_SOUND (c));
-    }
+  g_print ("%d: %s\n", c->id, G_OBJECT_TYPE_NAME (c));
+  if (verbose && SWFDEC_IS_GRAPHIC (c)) {
+    SwfdecGraphic *graphic = SWFDEC_GRAPHIC (c);
+    g_print ("  extents: %g %g  %g %g\n", graphic->extents.x0, graphic->extents.y0,
+	graphic->extents.x1, graphic->extents.y1);
+  }
+  if (SWFDEC_IS_IMAGE (c)) {
+    dump_image (SWFDEC_IMAGE (c));
+  }
+  if (SWFDEC_IS_SPRITE (c)) {
+    dump_sprite (SWFDEC_SPRITE (c));
+  }
+  if (SWFDEC_IS_SHAPE(c)) {
+    dump_shape(SWFDEC_SHAPE(c));
+  }
+  if (SWFDEC_IS_TEXT (c)) {
+    dump_text (SWFDEC_TEXT (c));
+  }
+  if (SWFDEC_IS_EDIT_TEXT (c)) {
+    dump_edit_text (SWFDEC_EDIT_TEXT (c));
+  }
+  if (SWFDEC_IS_FONT (c)) {
+    dump_font (SWFDEC_FONT (c));
+  }
+  if (SWFDEC_IS_BUTTON (c)) {
+    dump_button (SWFDEC_BUTTON (c));
+  }
+  if (SWFDEC_IS_SOUND (c)) {
+    dump_sound (SWFDEC_SOUND (c));
   }
 }
 
@@ -406,7 +402,7 @@ main (int argc, char *argv[])
   g_print ("  rate   : %g fps\n",  SWFDEC_DECODER (s)->rate / 256.0);
   g_print ("  size   : %ux%u pixels\n", SWFDEC_DECODER (s)->width, SWFDEC_DECODER (s)->height);
   g_print ("objects:\n");
-  dump_objects(s);
+  g_hash_table_foreach (s->characters, dump_object, NULL);
 
   g_print ("main sprite:\n");
   dump_sprite(s->main_sprite);
diff-tree b83df26d3c0ff337c64e3108907b4b8f8f674805 (from 99028e122d8c91ad4d6f56ef3d38205a4347b374)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 21:29:47 2007 +0100

    keep a list of current contents while parsing for faster lookup when
    tags affect them

diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index af7e913..84e6973 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -50,6 +50,10 @@ swfdec_sprite_dispose (GObject *object)
   SwfdecSprite * sprite = SWFDEC_SPRITE (object);
   unsigned int i;
 
+  if (sprite->live_content) {
+    g_hash_table_destroy (sprite->live_content);
+    sprite->live_content = NULL;
+  }
   if (sprite->frames) {
     for (i = 0; i < sprite->n_frames; i++) {
       g_free (sprite->frames[i].label);
@@ -123,39 +127,7 @@ swfdec_sprite_add_sound_chunk (SwfdecSpr
 static SwfdecContent *
 swfdec_content_find (SwfdecSprite *sprite, int depth)
 {
-  guint i, j;
-  SwfdecContent *content;
-  static unsigned long long int count = 0;
-
-  if (++count % 10000 == 0)
-    g_print ("%llu\n", count);
-
-  for (i = sprite->parse_frame; i <= sprite->parse_frame /* wait for underflow */; i--) {
-    SwfdecSpriteFrame *frame = &sprite->frames[i];
-    if (frame->actions == NULL)
-      continue;
-    for (j = frame->actions->len - 1; j < frame->actions->len; j--) {
-      SwfdecSpriteAction *action = 
-	&g_array_index (frame->actions, SwfdecSpriteAction, j);
-      switch (action->type) {
-	case SWFDEC_SPRITE_ACTION_SCRIPT:
-	  break;
-	case SWFDEC_SPRITE_ACTION_ADD:
-	case SWFDEC_SPRITE_ACTION_UPDATE:
-	  content = action->data;
-	  if (content->depth == depth)
-	    return content;
-	  break;
-	case SWFDEC_SPRITE_ACTION_REMOVE:
-	  if (GPOINTER_TO_INT (action->data) == depth)
-	    return NULL;
-	  break;
-	default:
-	  g_assert_not_reached ();
-      }
-    }
-  }
-  return NULL;
+  return g_hash_table_lookup (sprite->live_content, GINT_TO_POINTER (depth));
 }
 
 static void
@@ -184,6 +156,30 @@ swfdec_content_update_lifetime (SwfdecSp
   content->sequence->end = sprite->parse_frame;
 }
 
+static void
+swfdec_content_update_live (SwfdecSprite *sprite,
+    SwfdecSpriteActionType type, gpointer data)
+{
+  SwfdecContent *content;
+  switch (type) {
+    case SWFDEC_SPRITE_ACTION_SCRIPT:
+      return;
+    case SWFDEC_SPRITE_ACTION_UPDATE:
+    case SWFDEC_SPRITE_ACTION_ADD:
+      content = data;
+      g_hash_table_insert (sprite->live_content, 
+	  GINT_TO_POINTER (content->depth), content);
+      break;
+    case SWFDEC_SPRITE_ACTION_REMOVE:
+      /* data is GINT_TO_POINTER (depth) */
+      g_hash_table_remove (sprite->live_content, data);
+      break;
+    default:
+      g_assert_not_reached ();
+      return;
+  }
+}
+
 /* NB: does not free the action data */
 static void
 swfdec_sprite_remove_last_action (SwfdecSprite * sprite, unsigned int frame_id)
@@ -212,6 +208,7 @@ swfdec_sprite_add_action (SwfdecSprite *
     frame->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction));
 
   swfdec_content_update_lifetime (sprite, type, data);
+  swfdec_content_update_live (sprite, type, data);
   action.type = type;
   action.data = data;
   g_array_append_val (frame->actions, action);
@@ -505,7 +502,7 @@ swfdec_sprite_class_init (SwfdecSpriteCl
 static void
 swfdec_sprite_init (SwfdecSprite * sprite)
 {
-
+  sprite->live_content = g_hash_table_new (g_direct_hash, g_direct_equal);
 }
 
 void
diff --git a/libswfdec/swfdec_sprite.h b/libswfdec/swfdec_sprite.h
index d0e3bb8..f2e7be5 100644
--- a/libswfdec/swfdec_sprite.h
+++ b/libswfdec/swfdec_sprite.h
@@ -76,6 +76,7 @@ struct _SwfdecSprite
 
   /* parse state */
   unsigned int		parse_frame;	/* frame we're currently parsing. == n_frames if done parsing */
+  GHashTable *		live_content;	/* depth->SwfdecSpriteContent for every content in parse_frame */
 };
 
 struct _SwfdecSpriteClass
diff-tree 99028e122d8c91ad4d6f56ef3d38205a4347b374 (from 324a772186b03ab45ba730faa742ff35041d6a2a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 17:21:10 2007 +0100

    even more functions don't take a frame_id anymore but use parse_frame

diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index 1eeac3b..af7e913 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -121,12 +121,16 @@ swfdec_sprite_add_sound_chunk (SwfdecSpr
 /* NB: we look in the current frame, too - so call this before adding actions
  * that might modify the frame you're looking for */
 static SwfdecContent *
-swfdec_content_find (SwfdecSprite *sprite, unsigned int frame_id, int depth)
+swfdec_content_find (SwfdecSprite *sprite, int depth)
 {
   guint i, j;
   SwfdecContent *content;
+  static unsigned long long int count = 0;
 
-  for (i = frame_id; i <= frame_id /* wait for underflow */; i--) {
+  if (++count % 10000 == 0)
+    g_print ("%llu\n", count);
+
+  for (i = sprite->parse_frame; i <= sprite->parse_frame /* wait for underflow */; i--) {
     SwfdecSpriteFrame *frame = &sprite->frames[i];
     if (frame->actions == NULL)
       continue;
@@ -155,7 +159,7 @@ swfdec_content_find (SwfdecSprite *sprit
 }
 
 static void
-swfdec_content_update_lifetime (SwfdecSprite *sprite, unsigned int frame_id,
+swfdec_content_update_lifetime (SwfdecSprite *sprite,
     SwfdecSpriteActionType type, gpointer data)
 {
   SwfdecContent *content;
@@ -174,10 +178,10 @@ swfdec_content_update_lifetime (SwfdecSp
       g_assert_not_reached ();
       return;
   }
-  content = swfdec_content_find (sprite, frame_id, depth);
+  content = swfdec_content_find (sprite, depth);
   if (content == NULL)
     return;
-  content->sequence->end = frame_id;
+  content->sequence->end = sprite->parse_frame;
 }
 
 /* NB: does not free the action data */
@@ -207,7 +211,7 @@ swfdec_sprite_add_action (SwfdecSprite *
   if (frame->actions == NULL)
     frame->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction));
 
-  swfdec_content_update_lifetime (sprite, sprite->parse_frame, type, data);
+  swfdec_content_update_lifetime (sprite, type, data);
   action.type = type;
   action.data = data;
   g_array_append_val (frame->actions, action);
@@ -289,7 +293,7 @@ swfdec_contents_create (SwfdecSprite *sp
   if (copy) {
     SwfdecContent *copy;
 
-    copy = swfdec_content_find (sprite, sprite->parse_frame, depth);
+    copy = swfdec_content_find (sprite, depth);
     if (copy == NULL) {
       SWFDEC_WARNING ("Couldn't copy depth %u in frame %u", depth, sprite->parse_frame);
     } else {
diff-tree 324a772186b03ab45ba730faa742ff35041d6a2a (from ed9874096d7a17d4a9b37235ff1a777c263a7c44)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 15:02:06 2007 +0100

    make the frame_id implicit in some calls

diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index f5496b9..1eeac3b 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -195,19 +195,19 @@ swfdec_sprite_remove_last_action (Swfdec
 }
 
 void
-swfdec_sprite_add_action (SwfdecSprite * sprite, unsigned int frame_id, 
-    SwfdecSpriteActionType type, gpointer data)
+swfdec_sprite_add_action (SwfdecSprite *sprite, SwfdecSpriteActionType type, 
+    gpointer data)
 {
   SwfdecSpriteAction action;
   SwfdecSpriteFrame *frame;
   
-  g_assert (frame_id < sprite->n_frames);
-  frame = &sprite->frames[frame_id];
+  g_assert (sprite->parse_frame < sprite->n_frames);
+  frame = &sprite->frames[sprite->parse_frame];
 
   if (frame->actions == NULL)
     frame->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction));
 
-  swfdec_content_update_lifetime (sprite, frame_id, type, data);
+  swfdec_content_update_lifetime (sprite, sprite->parse_frame, type, data);
   action.type = type;
   action.data = data;
   g_array_append_val (frame->actions, action);
@@ -279,19 +279,19 @@ swfdec_content_new (int depth)
 }
 
 static SwfdecContent *
-swfdec_contents_create (SwfdecSprite *sprite, unsigned int frame_id, 
+swfdec_contents_create (SwfdecSprite *sprite, 
     int depth, gboolean copy, gboolean new)
 {
   SwfdecContent *content = swfdec_content_new (depth);
 
-  content->start = frame_id;
+  content->start = sprite->parse_frame;
   content->end = sprite->n_frames;
   if (copy) {
     SwfdecContent *copy;
 
-    copy = swfdec_content_find (sprite, frame_id, depth);
+    copy = swfdec_content_find (sprite, sprite->parse_frame, depth);
     if (copy == NULL) {
-      SWFDEC_WARNING ("Couldn't copy depth %u in frame %u", depth, frame_id);
+      SWFDEC_WARNING ("Couldn't copy depth %u in frame %u", depth, sprite->parse_frame);
     } else {
       *content = *copy;
       SWFDEC_LOG ("Copying from content %p", copy);
@@ -300,15 +300,15 @@ swfdec_contents_create (SwfdecSprite *sp
       if (content->events)
 	content->events = swfdec_event_list_copy (copy->events);
       if (new) {
-	content->start = frame_id;
+	content->start = sprite->parse_frame;
 	content->end = sprite->n_frames;
       }
-      swfdec_sprite_add_action (sprite, frame_id, 
+      swfdec_sprite_add_action (sprite, 
 	  new ? SWFDEC_SPRITE_ACTION_ADD : SWFDEC_SPRITE_ACTION_UPDATE, content);
       return content;
     }
   }
-  swfdec_sprite_add_action (sprite, frame_id, SWFDEC_SPRITE_ACTION_ADD, content);
+  swfdec_sprite_add_action (sprite, SWFDEC_SPRITE_ACTION_ADD, content);
   return content;
 }
 
@@ -349,8 +349,7 @@ swfdec_spriteseg_place_object_2 (SwfdecS
   depth -= 16384;
 
   /* new name always means new object */
-  content = swfdec_contents_create (s->parse_sprite, 
-      s->parse_sprite->parse_frame, depth, move, has_character || has_name);
+  content = swfdec_contents_create (s->parse_sprite, depth, move, has_character || has_name);
   if (has_character) {
     int id = swfdec_bits_get_u16 (bits);
     content->graphic = swfdec_swf_decoder_get_character (s, id);
@@ -460,8 +459,7 @@ swfdec_spriteseg_remove_object (SwfdecSw
   depth = swfdec_bits_get_u16 (&s->b);
   SWFDEC_LOG ("  depth = %d (=> %d)", depth, depth - 16384);
   depth -= 16384;
-  swfdec_sprite_add_action (s->parse_sprite, s->parse_sprite->parse_frame, 
-      SWFDEC_SPRITE_ACTION_REMOVE, GINT_TO_POINTER (depth));
+  swfdec_sprite_add_action (s->parse_sprite, SWFDEC_SPRITE_ACTION_REMOVE, GINT_TO_POINTER (depth));
 
   return SWFDEC_STATUS_OK;
 }
@@ -474,8 +472,7 @@ swfdec_spriteseg_remove_object_2 (Swfdec
   depth = swfdec_bits_get_u16 (&s->b);
   SWFDEC_LOG ("  depth = %u", depth);
   depth -= 16384;
-  swfdec_sprite_add_action (s->parse_sprite, s->parse_sprite->parse_frame, 
-      SWFDEC_SPRITE_ACTION_REMOVE, GINT_TO_POINTER (depth));
+  swfdec_sprite_add_action (s->parse_sprite, SWFDEC_SPRITE_ACTION_REMOVE, GINT_TO_POINTER (depth));
 
   return SWFDEC_STATUS_OK;
 }
diff --git a/libswfdec/swfdec_sprite.h b/libswfdec/swfdec_sprite.h
index e4c7467..d0e3bb8 100644
--- a/libswfdec/swfdec_sprite.h
+++ b/libswfdec/swfdec_sprite.h
@@ -89,7 +89,7 @@ int tag_func_define_sprite (SwfdecSwfDec
 void swfdec_sprite_add_sound_chunk (SwfdecSprite * sprite, unsigned int frame,
     SwfdecBuffer * chunk, int skip, unsigned int n_samples);
 void swfdec_sprite_set_n_frames (SwfdecSprite *sprite, unsigned int n_frames, unsigned int rate);
-void swfdec_sprite_add_action (SwfdecSprite * sprite, unsigned int frame, 
+void swfdec_sprite_add_action (SwfdecSprite * sprite,
     SwfdecSpriteActionType type, gpointer data);
 unsigned int swfdec_sprite_get_next_frame (SwfdecSprite *sprite, unsigned int current_frame);
 int		swfdec_sprite_get_frame		(SwfdecSprite *		sprite,
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index fab6c1f..c81d3b9 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -276,8 +276,7 @@ tag_func_do_action (SwfdecSwfDecoder * s
   script = swfdec_script_new_for_player (SWFDEC_DECODER (s)->player, &s->b, name, s->version);
   g_free (name);
   if (script)
-    swfdec_sprite_add_action (s->parse_sprite, s->parse_sprite->parse_frame, 
-	SWFDEC_SPRITE_ACTION_SCRIPT, script);
+    swfdec_sprite_add_action (s->parse_sprite, SWFDEC_SPRITE_ACTION_SCRIPT, script);
 
   return SWFDEC_STATUS_OK;
 }
diff-tree ed9874096d7a17d4a9b37235ff1a777c263a7c44 (from 0edfa987b4002895c7634cd98a4302b5af0ed02f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 14:55:32 2007 +0100

    use a hash table to store characters for faster indexing by id

diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index 2a45d5e..5ceb57b 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		      2006 Benjamin Otte <otte at gnome.org>
+ *		 2006-2007 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -52,8 +52,7 @@ swfdec_decoder_dispose (GObject *object)
 {
   SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (object);
 
-  g_list_foreach (s->characters, (GFunc) g_object_unref, NULL);
-  g_list_free (s->characters);
+  g_hash_table_destroy (s->characters);
   g_object_unref (s->main_sprite);
   g_hash_table_destroy (s->exports);
 
@@ -85,20 +84,6 @@ zfree (void *opaque, void *addr)
   g_free (addr);
 }
 
-#if 0
-static void
-dumpbits (SwfdecBits * b)
-{
-  int i;
-
-  printf ("    ");
-  for (i = 0; i < 16; i++) {
-    printf ("%02x ", swfdec_bits_get_u8 (b));
-  }
-  printf ("\n");
-}
-#endif
-
 static gboolean
 swfdec_swf_decoder_deflate_all (SwfdecSwfDecoder * s)
 {
@@ -359,6 +344,8 @@ swfdec_swf_decoder_init (SwfdecSwfDecode
 {
   s->main_sprite = g_object_new (SWFDEC_TYPE_SPRITE, NULL);
 
+  s->characters = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
+      NULL, g_object_unref);
   s->input_queue = swfdec_buffer_queue_new ();
   s->exports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 }
@@ -376,20 +363,11 @@ swfdec_swf_decoder_get_export (SwfdecSwf
 }
 
 gpointer
-swfdec_swf_decoder_get_character (SwfdecSwfDecoder * s, int id)
+swfdec_swf_decoder_get_character (SwfdecSwfDecoder * s, unsigned int id)
 {
-  SwfdecCharacter *character;
-  GList *g;
-
   g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (s), NULL);
 
-  for (g = s->characters; g; g = g_list_next (g)) {
-    character = SWFDEC_CHARACTER (g->data);
-    if (character->id == id)
-      return character;
-  }
-
-  return NULL;
+  return g_hash_table_lookup (s->characters, GUINT_TO_POINTER (id));
 }
 
 /**
@@ -405,12 +383,11 @@ swfdec_swf_decoder_get_character (Swfdec
  * Returns: The requested character or NULL on failure;
  **/
 gpointer
-swfdec_swf_decoder_create_character (SwfdecSwfDecoder * s, int id, GType type)
+swfdec_swf_decoder_create_character (SwfdecSwfDecoder * s, unsigned int id, GType type)
 {
   SwfdecCharacter *result;
 
   g_return_val_if_fail (SWFDEC_IS_DECODER (s), NULL);
-  g_return_val_if_fail (id >= 0, NULL);
   g_return_val_if_fail (g_type_is_a (type, SWFDEC_TYPE_CHARACTER), NULL);
 
   SWFDEC_INFO ("  id = %d", id);
@@ -421,7 +398,7 @@ swfdec_swf_decoder_create_character (Swf
   }
   result = g_object_new (type, NULL);
   result->id = id;
-  s->characters = g_list_prepend (s->characters, result);
+  g_hash_table_insert (s->characters, GUINT_TO_POINTER (id), result);
   if (SWFDEC_IS_CACHED (result)) {
     swfdec_cached_set_cache (SWFDEC_CACHED (result), SWFDEC_DECODER (s)->player->cache);
   }
diff --git a/libswfdec/swfdec_swf_decoder.h b/libswfdec/swfdec_swf_decoder.h
index 5d2109f..48541eb 100644
--- a/libswfdec/swfdec_swf_decoder.h
+++ b/libswfdec/swfdec_swf_decoder.h
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		      2006 Benjamin Otte <otte at gnome.org>
+ *		 2006-2007 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -59,7 +59,7 @@ struct _SwfdecSwfDecoder
   SwfdecBits b;				/* temporary state while parsing */
 
   /* defined objects */
-  GList *characters;			/* list of all objects with an id (called characters) */
+  GHashTable *characters;		/* list of all objects with an id (called characters) */
   SwfdecSprite *main_sprite;
   SwfdecSprite *parse_sprite;
 
@@ -79,9 +79,9 @@ struct _SwfdecSwfDecoderClass {
 GType		swfdec_swf_decoder_get_type		(void);
 
 gpointer	swfdec_swf_decoder_get_character	(SwfdecSwfDecoder *	s, 
-							 int			id);
+							 unsigned int	      	id);
 gpointer	swfdec_swf_decoder_create_character	(SwfdecSwfDecoder *	s,
-							 int			id,
+							 unsigned int	      	id,
 							 GType			type);
 gpointer	swfdec_swf_decoder_get_export		(SwfdecSwfDecoder *	s,
 							 const char *		name);
diff-tree 0edfa987b4002895c7634cd98a4302b5af0ed02f (from 6a39b304d10aecf93c35c23390e649a9994cca89)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 13:15:19 2007 +0100

    add event-order tets that checks onFoo and foo events are executed in the right order

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index d087ed3..e1c8e02 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -55,6 +55,8 @@ EXTRA_DIST = \
 	currentframe.swf.trace \
 	double.swf \
 	double.swf.trace \
+	event-order.swf \
+	event-order.swf.trace \
 	function1.swf \
 	function1.swf.trace \
 	function2.swf \
diff-tree 6a39b304d10aecf93c35c23390e649a9994cca89 (from e472a12007feae2e81d257b5f1e826cc68d7586a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 13:14:20 2007 +0100

    add support for onFoo events in addition to frame events loaded from the file

diff --git a/libswfdec/swfdec_event.c b/libswfdec/swfdec_event.c
index d988ad3..06526fa 100644
--- a/libswfdec/swfdec_event.c
+++ b/libswfdec/swfdec_event.c
@@ -41,6 +41,75 @@ struct _SwfdecEventList {
   GArray *		events;
 };
 
+static const char *event_names[] = {
+  "onLoad",
+  "onEnterFrame",
+  "onUnload",
+  "onMouseMove",
+  "onMouseDown",
+  "onMouseUp",
+  "onKeyUp",
+  "onKeyDown",
+  "onData",
+  NULL,
+  "onPress",
+  "onRelease",
+  "onReleaseOutside",
+  "onRollOver",
+  "onRollOut",
+  "onDragOver",
+  "onDragOut",
+  NULL,
+  NULL
+};
+
+const char *
+swfdec_event_type_get_name (SwfdecEventType type)
+{
+  switch (type) {
+    case SWFDEC_EVENT_LOAD:
+      return event_names[0];
+    case SWFDEC_EVENT_ENTER:
+      return event_names[1];
+    case SWFDEC_EVENT_UNLOAD:
+      return event_names[2];
+    case SWFDEC_EVENT_MOUSE_MOVE:
+      return event_names[3];
+    case SWFDEC_EVENT_MOUSE_DOWN:
+      return event_names[4];
+    case SWFDEC_EVENT_MOUSE_UP:
+      return event_names[5];
+    case SWFDEC_EVENT_KEY_UP:
+      return event_names[6];
+    case SWFDEC_EVENT_KEY_DOWN:
+      return event_names[7];
+    case SWFDEC_EVENT_DATA:
+      return event_names[8];
+    case SWFDEC_EVENT_INITIALIZE:
+      return event_names[9];
+    case SWFDEC_EVENT_PRESS:
+      return event_names[10];
+    case SWFDEC_EVENT_RELEASE:
+      return event_names[11];
+    case SWFDEC_EVENT_RELEASE_OUTSIDE:
+      return event_names[12];
+    case SWFDEC_EVENT_ROLL_OVER:
+      return event_names[13];
+    case SWFDEC_EVENT_ROLL_OUT:
+      return event_names[14];
+    case SWFDEC_EVENT_DRAG_OVER:
+      return event_names[15];
+    case SWFDEC_EVENT_DRAG_OUT:
+      return event_names[16];
+    case SWFDEC_EVENT_KEY_PRESS:
+      return event_names[17];
+    case SWFDEC_EVENT_CONSTRUCT:
+      return event_names[18];
+    default:
+      g_assert_not_reached ();
+      return NULL;
+  }
+}
 
 SwfdecEventList *
 swfdec_event_list_new (SwfdecPlayer *player)
@@ -154,36 +223,45 @@ swfdec_event_list_parse (SwfdecEventList
 
 void
 swfdec_event_list_execute (SwfdecEventList *list, SwfdecScriptable *scriptable, 
-    unsigned int conditions, guint8 key)
+    unsigned int condition, guint8 key)
 {
   unsigned int i;
+  const char *name;
 
   g_return_if_fail (list != NULL);
 
   for (i = 0; i < list->events->len; i++) {
     SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
-    if ((event->conditions & conditions) &&
+    if ((event->conditions & condition) &&
 	event->key == key) {
-      SWFDEC_LOG ("executing script for event %u on scriptable %p", conditions, scriptable);
+      SWFDEC_LOG ("executing script for event %u on scriptable %p", condition, scriptable);
       swfdec_script_execute (event->script, scriptable);
     }
   }
+  name = swfdec_event_type_get_name (condition);
+  if (name)
+    swfdec_scriptable_execute (scriptable, name, 0, NULL);
 }
 
 gboolean
-swfdec_event_list_has_conditions (SwfdecEventList *list, 
-    unsigned int conditions, guint8 key)
+swfdec_event_list_has_conditions (SwfdecEventList *list, SwfdecScriptable *scriptable,
+    unsigned int condition, guint8 key)
 {
   unsigned int i;
+  const char *name;
 
   g_return_val_if_fail (list != NULL, FALSE);
+  g_return_val_if_fail (SWFDEC_IS_SCRIPTABLE (scriptable), FALSE);
 
   for (i = 0; i < list->events->len; i++) {
     SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
-    if ((event->conditions & conditions) &&
+    if ((event->conditions & condition) &&
 	event->key == key)
       return TRUE;
   }
+  name = swfdec_event_type_get_name (condition);
+  if (name)
+    return swfdec_scriptable_can_execute (scriptable, name);
   return FALSE;
 }
 
diff --git a/libswfdec/swfdec_event.h b/libswfdec/swfdec_event.h
index 2906bb4..768dc8d 100644
--- a/libswfdec/swfdec_event.h
+++ b/libswfdec/swfdec_event.h
@@ -48,6 +48,8 @@ typedef enum _SwfdecEventType {
   SWFDEC_EVENT_CONSTRUCT	= (1 << 18)
 } SwfdecEventType;
 
+const char *		swfdec_event_type_get_name	(SwfdecEventType      type);
+
 SwfdecEventList *	swfdec_event_list_new		(SwfdecPlayer *	      player);
 SwfdecEventList *	swfdec_event_list_copy		(SwfdecEventList *    list);
 void			swfdec_event_list_free		(SwfdecEventList *    list);
@@ -63,6 +65,7 @@ void			swfdec_event_list_execute	(Swfdec
 							 unsigned int	      condition,
 							 guint8		      key);
 gboolean		swfdec_event_list_has_conditions(SwfdecEventList *    list,
+							 SwfdecScriptable *	scriptable,
 							 unsigned int	      conditions,
 							 guint8		      key);
 							 
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index a1df353..0e7715c 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -339,8 +339,14 @@ swfdec_movie_execute_script (gpointer mo
   SwfdecMovie *movie = moviep;
   guint condition = GPOINTER_TO_UINT (data);
 
-  g_assert (movie->content->events);
-  swfdec_event_list_execute (movie->content->events, SWFDEC_SCRIPTABLE (movie), condition, 0);
+  if (movie->content->events) {
+    swfdec_event_list_execute (movie->content->events, 
+	SWFDEC_SCRIPTABLE (movie), condition, 0);
+  } else {
+    const char *name = swfdec_event_type_get_name (condition);
+    if (name != NULL)
+      swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (movie), name, 0, NULL);
+  }
 }
 
 /**
@@ -360,10 +366,16 @@ swfdec_movie_queue_script (SwfdecMovie *
   g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), FALSE);
   g_return_val_if_fail (condition != 0, FALSE);
 
-  if (movie->content->events == NULL)
-    return FALSE;
-  if (!swfdec_event_list_has_conditions (movie->content->events, condition, 0))
-    return FALSE;
+  if (movie->content->events) {
+    if (!swfdec_event_list_has_conditions (movie->content->events, 
+	  SWFDEC_SCRIPTABLE (movie), condition, 0))
+      return FALSE;
+  } else {
+    const char *name = swfdec_event_type_get_name (condition);
+    if (name == NULL ||
+	!swfdec_scriptable_can_execute (SWFDEC_SCRIPTABLE (movie), name))
+      return FALSE;
+  }
 
   player = SWFDEC_ROOT_MOVIE (movie->root)->player;
   swfdec_player_add_action (player, movie, swfdec_movie_execute_script, 
diff-tree e472a12007feae2e81d257b5f1e826cc68d7586a (from ce1244ddd18afd0ce1b83999304ac5b9282c7564)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 13:03:53 2007 +0100

    output trace messages in the window
    
    requires some refactoring of the order in which functions are defined, so
    this diff looks bigger than it really is

diff --git a/player/swfdec_player_manager.c b/player/swfdec_player_manager.c
index 31e9772..b0bdc55 100644
--- a/player/swfdec_player_manager.c
+++ b/player/swfdec_player_manager.c
@@ -41,9 +41,40 @@ enum {
   MESSAGE,
   LAST_SIGNAL
 };
+guint signals[LAST_SIGNAL];
+
+/*** command handling ***/
+
+typedef enum {
+  SWFDEC_MESSAGE_INPUT,
+  SWFDEC_MESSAGE_OUTPUT,
+  SWFDEC_MESSAGE_ERROR
+} SwfdecMessageType;
+
+static void
+swfdec_player_manager_send_message (SwfdecPlayerManager *manager,
+    SwfdecMessageType type, char *format, ...) G_GNUC_PRINTF (3, 4);
+static void
+swfdec_player_manager_send_message (SwfdecPlayerManager *manager,
+    SwfdecMessageType type, char *format, ...)
+{
+  va_list args;
+  char *msg;
+
+  va_start (args, format);
+  msg = g_strdup_vprintf (format, args);
+  va_end (args);
+  g_signal_emit (manager, signals[MESSAGE], 0, (guint) type, msg);
+  g_free (msg);
+}
+#define swfdec_player_manager_output(manager, ...) \
+  swfdec_player_manager_send_message (manager, SWFDEC_MESSAGE_OUTPUT, __VA_ARGS__)
+#define swfdec_player_manager_error(manager, ...) \
+  swfdec_player_manager_send_message (manager, SWFDEC_MESSAGE_ERROR, __VA_ARGS__)
+
+/*** SWFDEC_PLAYER_MANAGER ***/
 
 G_DEFINE_TYPE (SwfdecPlayerManager, swfdec_player_manager, G_TYPE_OBJECT)
-guint signals[LAST_SIGNAL];
 
 static void
 swfdec_player_manager_get_property (GObject *object, guint param_id, GValue *value, 
@@ -89,6 +120,12 @@ swfdec_player_manager_set_property (GObj
 static void breakpoint_hit_cb (SwfdecDebugger *debugger, guint id, SwfdecPlayerManager *manager);
 
 static void
+trace_cb (SwfdecPlayer *player, const char *str, SwfdecPlayerManager *manager)
+{
+  swfdec_player_manager_output (manager, "Trace: %s", str);
+}
+
+static void
 swfdec_player_manager_set_player (SwfdecPlayerManager *manager, SwfdecPlayer *player)
 {
   if (manager->player == player)
@@ -102,6 +139,7 @@ swfdec_player_manager_set_player (Swfdec
   if (player) {
     g_object_ref (player);
     g_signal_connect (player, "breakpoint", G_CALLBACK (breakpoint_hit_cb), manager);
+    g_signal_connect (player, "trace", G_CALLBACK (trace_cb), manager);
   }
 }
 
@@ -293,34 +331,7 @@ swfdec_player_manager_continue (SwfdecPl
   g_main_loop_quit (manager->interrupt_loop);
 }
 
-/*** command handling ***/
-
-typedef enum {
-  SWFDEC_MESSAGE_INPUT,
-  SWFDEC_MESSAGE_OUTPUT,
-  SWFDEC_MESSAGE_ERROR
-} SwfdecMessageType;
-
-static void
-swfdec_player_manager_send_message (SwfdecPlayerManager *manager,
-    SwfdecMessageType type, char *format, ...) G_GNUC_PRINTF (3, 4);
-static void
-swfdec_player_manager_send_message (SwfdecPlayerManager *manager,
-    SwfdecMessageType type, char *format, ...)
-{
-  va_list args;
-  char *msg;
-
-  va_start (args, format);
-  msg = g_strdup_vprintf (format, args);
-  va_end (args);
-  g_signal_emit (manager, signals[MESSAGE], 0, (guint) type, msg);
-  g_free (msg);
-}
-#define swfdec_player_manager_output(manager, ...) \
-  swfdec_player_manager_send_message (manager, SWFDEC_MESSAGE_OUTPUT, __VA_ARGS__)
-#define swfdec_player_manager_error(manager, ...) \
-  swfdec_player_manager_send_message (manager, SWFDEC_MESSAGE_ERROR, __VA_ARGS__)
+/*** commands ***/
 
 const char *
 parse_skip (const char *input)
diff-tree ce1244ddd18afd0ce1b83999304ac5b9282c7564 (from 5e9b7d35d8857e9eb5377b28205ec1ba1bba6ea0)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 13:02:49 2007 +0100

    Add swfdec_scriptable_(can_)execute
    
    - swfdec_scriptable_can_execute checks if a property of a given name exists
      and can be executed
    - swfdec_scriptable_execute executes that property if it exists

diff --git a/libswfdec/swfdec_scriptable.c b/libswfdec/swfdec_scriptable.c
index 6554666..951a726 100644
--- a/libswfdec/swfdec_scriptable.c
+++ b/libswfdec/swfdec_scriptable.c
@@ -25,6 +25,8 @@
 #include "swfdec_debug.h"
 #include "swfdec_loader_internal.h"
 #include "js/jsapi.h"
+#include "js/jsfun.h"
+#include "js/jsinterp.h"
 
 G_DEFINE_ABSTRACT_TYPE (SwfdecScriptable, swfdec_scriptable, G_TYPE_OBJECT)
 
@@ -234,3 +236,69 @@ swfdec_scriptable_set_variables (SwfdecS
   }
 }
 
+/**
+ * swfdec_scriptable_execute:
+ * @script: a #SwfdecScriptable
+ * @name: property name that contains the handler
+ * @n_args: number of arguments to pass to handler
+ * @args: @n_args arguments that will be passed to handler
+ *
+ * Executes a callback function (like onMouseMove) on the scriptable if it is
+ * defined.
+ **/
+void
+swfdec_scriptable_execute (SwfdecScriptable *script, const char *name,
+    guint n_args, jsval *args)
+{
+  JSObject *obj;
+  jsval fun;
+
+  g_return_if_fail (SWFDEC_IS_SCRIPTABLE (script));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (n_args == 0 || args != NULL);
+
+  obj = swfdec_scriptable_get_object (script);
+  if (!obj)
+    return;
+  if (!JS_GetProperty (script->jscx, obj, name, &fun))
+    return;
+  if (!JSVAL_IS_OBJECT (fun) || fun == JSVAL_NULL ||
+      JS_GetClass (JSVAL_TO_OBJECT (fun)) != &js_FunctionClass) {
+    SWFDEC_LOG ("scriptable has no handler for %s event", name);
+    return;
+  }
+  js_InternalCall (script->jscx, obj, fun, n_args, args, &fun);
+}
+
+/**
+ * swfdec_scriptable_can_execute:
+ * @script: a #SwfdecScriptable
+ * @name: name of the function
+ *
+ * Checks if @script contains a function property named @name that can be
+ * executed via swfdec_scriptable_execute().
+ *
+ * Returns: %TRUE if such a function exists, %FALSE otherwise
+ **/
+gboolean
+swfdec_scriptable_can_execute (SwfdecScriptable *script, const char *name)
+{
+  JSObject *obj;
+  jsval fun;
+
+  g_return_val_if_fail (SWFDEC_IS_SCRIPTABLE (script), FALSE);
+  g_return_val_if_fail (name != NULL, FALSE);
+
+  obj = swfdec_scriptable_get_object (script);
+  if (!obj)
+    return FALSE;
+  if (!JS_GetProperty (script->jscx, obj, name, &fun))
+    return FALSE;
+  if (!JSVAL_IS_OBJECT (fun) || fun == JSVAL_NULL ||
+      JS_GetClass (JSVAL_TO_OBJECT (fun)) != &js_FunctionClass) {
+    SWFDEC_LOG ("scriptable has no handler for %s event", name);
+    return FALSE;
+  }
+  return TRUE;
+}
+
diff --git a/libswfdec/swfdec_scriptable.h b/libswfdec/swfdec_scriptable.h
index a197d8f..a53ca4a 100644
--- a/libswfdec/swfdec_scriptable.h
+++ b/libswfdec/swfdec_scriptable.h
@@ -66,6 +66,12 @@ gpointer		swfdec_scriptable_from_object	
 
 void			swfdec_scriptable_set_variables	(SwfdecScriptable *	script,
 							 const char *		variables);
+gboolean		swfdec_scriptable_can_execute	(SwfdecScriptable *	script,
+							 const char *		name);
+void			swfdec_scriptable_execute	(SwfdecScriptable *	script,
+							 const char *		name,
+							 guint			n_args,
+							 jsval *		args);
 
 
 G_END_DECLS
diff-tree 5e9b7d35d8857e9eb5377b28205ec1ba1bba6ea0 (from c2b82521e27908e41d3f3fd354f9a73c51ee26df)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 12:57:32 2007 +0100

    really delete properties, don't just pretend to

diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c
index 1c4d80a..2a860a4 100644
--- a/libswfdec/swfdec_js_movie.c
+++ b/libswfdec/swfdec_js_movie.c
@@ -1153,6 +1153,7 @@ swfdec_js_movie_remove_property (SwfdecM
   JSObject *jsobj;
   JSContext *cx;
   JSBool found = JS_FALSE;
+  jsval deleted = JSVAL_FALSE;
 
   if (!movie->has_name ||
       script->jsobj == NULL)
@@ -1168,9 +1169,10 @@ swfdec_js_movie_remove_property (SwfdecM
   }
 
   SWFDEC_LOG ("removing %s as property", movie->name);
-  if (!JS_SetPropertyAttributes (cx, jsobj, movie->name, JSPROP_READONLY | JSPROP_PERMANENT, &found) ||
+  if (!JS_SetPropertyAttributes (cx, jsobj, movie->name, 0, &found) ||
       found != JS_TRUE ||
-      !JS_DeleteProperty (cx, jsobj, movie->name)) {
+      !JS_DeleteProperty2 (cx, jsobj, movie->name, &deleted) ||
+      deleted == JSVAL_FALSE) {
     SWFDEC_ERROR ("could not remove property %s correctly", movie->name);
   }
 }
diff-tree c2b82521e27908e41d3f3fd354f9a73c51ee26df (from beacb0853da743a6505e50517683ab6541db0b39)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 6 12:56:51 2007 +0100

    apaprently i'm too stupid to implement ActionSwap correctly

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index f00a6f1..88b1b1d 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1902,7 +1902,7 @@ swfdec_action_swap (JSContext *cx, guint
 {
   jsval tmp = cx->fp->sp[-2];
   cx->fp->sp[-2] = cx->fp->sp[-1];
-  cx->fp->sp[-2] = tmp;
+  cx->fp->sp[-1] = tmp;
   return JS_TRUE;
 }
 


More information about the Swfdec mailing list