[Swfdec] Branch 'as' - 17 commits - configure.ac doc/Makefile.am doc/swfdec-docs.sgml doc/swfdec-sections.txt doc/swfdec.types libswfdec-gtk/Makefile.am libswfdec-gtk/swfdec-gtk.h libswfdec-gtk/swfdec_gtk_loader.c libswfdec-gtk/swfdec_gtk_loader.h libswfdec-gtk/swfdec_gtk_player.c libswfdec-gtk/swfdec_gtk_player.h libswfdec-gtk/swfdec_playback_alsa.c libswfdec-gtk/swfdec_source.c libswfdec/Makefile.am libswfdec/swfdec_amf.c libswfdec/swfdec_amf.h libswfdec/swfdec_as_array.c libswfdec/swfdec_as_array.h libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h libswfdec/swfdec_as_types.c libswfdec/swfdec_as_types.h libswfdec/swfdec_button.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_cached.c libswfdec/swfdec_connection.c libswfdec/swfdec_connection.h libswfdec/swfdec_debugger.c libswfdec/swfdec_edittext.c libswfdec/swfdec_edittext.h libswfdec/swfdec_edittext_movie.c libswfdec/swfdec_event.c libswfdec/swfdec_event.h libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_font.c libswfdec/swfdec_graphic.c libswfdec/swfdec_graphic.h libswfdec/swfdec_js.c libswfdec/swfdec_js_movie.c libswfdec/swfdec_listener.c libswfdec/swfdec_listener.h libswfdec/swfdec_loader.c libswfdec/swfdec_loader.h libswfdec/swfdec_loader_internal.h libswfdec/swfdec_morphshape.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_net_stream.c libswfdec/swfdec_net_stream.h libswfdec/swfdec_player.c libswfdec/swfdec_player.h libswfdec/swfdec_player_internal.h libswfdec/swfdec_root_movie.c libswfdec/swfdec_script.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_video.c libswfdec/swfdec_video_movie.c libswfdec/swfdec_xml.c libswfdec/swfdec_xml.h player/swfdebug.c player/swfplay.c test/dump.c test/image test/parse.c test/sound test/swfdec-extract.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Wed Apr 4 00:39:18 PDT 2007


 configure.ac                         |   27 +++
 doc/Makefile.am                      |    3 
 doc/swfdec-docs.sgml                 |    1 
 doc/swfdec-sections.txt              |   18 ++
 doc/swfdec.types                     |    2 
 libswfdec-gtk/Makefile.am            |    6 
 libswfdec-gtk/swfdec-gtk.h           |    1 
 libswfdec-gtk/swfdec_gtk_loader.c    |  243 +++++++++++++++++++++++++++++++++++
 libswfdec-gtk/swfdec_gtk_loader.h    |   44 ++++++
 libswfdec-gtk/swfdec_gtk_player.c    |   23 +--
 libswfdec-gtk/swfdec_gtk_player.h    |    9 -
 libswfdec-gtk/swfdec_playback_alsa.c |    3 
 libswfdec-gtk/swfdec_source.c        |   32 +++-
 libswfdec/Makefile.am                |   35 ++---
 libswfdec/swfdec_amf.c               |  126 ++++++++----------
 libswfdec/swfdec_amf.h               |   16 +-
 libswfdec/swfdec_as_array.c          |  104 ++++++++++++++
 libswfdec/swfdec_as_array.h          |   56 ++++++++
 libswfdec/swfdec_as_context.c        |  188 ++++++++++++++++++++++++++-
 libswfdec/swfdec_as_context.h        |   13 +
 libswfdec/swfdec_as_object.c         |   49 ++++++-
 libswfdec/swfdec_as_object.h         |   11 +
 libswfdec/swfdec_as_types.c          |   31 ++++
 libswfdec/swfdec_as_types.h          |   33 ++++
 libswfdec/swfdec_button.c            |    4 
 libswfdec/swfdec_button_movie.c      |    4 
 libswfdec/swfdec_cached.c            |    3 
 libswfdec/swfdec_connection.c        |   61 +++-----
 libswfdec/swfdec_connection.h        |    8 -
 libswfdec/swfdec_debugger.c          |   55 +------
 libswfdec/swfdec_edittext.c          |   56 +++-----
 libswfdec/swfdec_edittext.h          |    4 
 libswfdec/swfdec_edittext_movie.c    |   65 +++------
 libswfdec/swfdec_event.c             |   85 +++++-------
 libswfdec/swfdec_event.h             |   11 -
 libswfdec/swfdec_flv_decoder.c       |    5 
 libswfdec/swfdec_font.c              |   19 ++
 libswfdec/swfdec_graphic.c           |    3 
 libswfdec/swfdec_graphic.h           |    5 
 libswfdec/swfdec_js.c                |    2 
 libswfdec/swfdec_js_movie.c          |   50 -------
 libswfdec/swfdec_listener.c          |   98 +++++---------
 libswfdec/swfdec_listener.h          |    9 -
 libswfdec/swfdec_loader.c            |   46 ++----
 libswfdec/swfdec_loader.h            |    3 
 libswfdec/swfdec_loader_internal.h   |   22 +++
 libswfdec/swfdec_morphshape.c        |   14 +-
 libswfdec/swfdec_movie.c             |  146 +++++++++++++++++----
 libswfdec/swfdec_movie.h             |   10 -
 libswfdec/swfdec_net_stream.c        |   90 ++++++------
 libswfdec/swfdec_net_stream.h        |    6 
 libswfdec/swfdec_player.c            |  124 +++++++++--------
 libswfdec/swfdec_player.h            |    3 
 libswfdec/swfdec_player_internal.h   |   19 +-
 libswfdec/swfdec_root_movie.c        |   12 -
 libswfdec/swfdec_script.c            |   10 -
 libswfdec/swfdec_sprite.c            |    3 
 libswfdec/swfdec_sprite_movie.c      |    4 
 libswfdec/swfdec_swf_decoder.c       |    1 
 libswfdec/swfdec_video.c             |   12 +
 libswfdec/swfdec_video_movie.c       |    4 
 libswfdec/swfdec_xml.c               |   53 ++-----
 libswfdec/swfdec_xml.h               |   14 +-
 player/swfdebug.c                    |    8 -
 player/swfplay.c                     |   15 --
 test/dump.c                          |    8 -
 test/image/image.c                   |   10 -
 test/parse.c                         |   10 -
 test/sound/sound.c                   |   10 -
 test/swfdec-extract.c                |   10 -
 test/trace/trace.c                   |    9 -
 71 files changed, 1515 insertions(+), 782 deletions(-)

New commits:
diff-tree df9459902a3d4cc821233ce7a973c1284cb4ffcf (from 31b77da7d447857b2a0769833c11a06fe870586a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Apr 4 09:38:49 2007 +0200

    unhook SpiderMonkey
    
    The current code does no ActionScript execution at all

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index be8455c..b46bcc0 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -1,6 +1,4 @@
-SUBDIRS = jpeg js
-
-DIST_SUBDIRS = jpeg js 
+SUBDIRS = jpeg
 
 CODECS =
 
@@ -13,9 +11,20 @@ endif
 
 lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJORMINOR@.la
 
-js_cflags = -I$(srcdir)/js/ -I./js -DXP_UNIX -DDEBUG
+foofiles = \
+	swfdec_js.c \
+	swfdec_js_color.c \
+	swfdec_js_connection.c \
+	swfdec_js_global.c \
+	swfdec_js_mouse.c \
+	swfdec_js_movie.c \
+	swfdec_js_net_stream.c \
+	swfdec_js_sound.c \
+	swfdec_js_video.c \
+	swfdec_js_xml.c
 
 libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
+	swfdec_as_array.c \
 	swfdec_as_context.c \
 	swfdec_as_frame.c \
 	swfdec_as_function.c \
@@ -53,16 +62,6 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_graphic_movie.c \
 	swfdec_html_parser.c \
 	swfdec_image.c \
-	swfdec_js.c \
-	swfdec_js_color.c \
-	swfdec_js_connection.c \
-	swfdec_js_global.c \
-	swfdec_js_mouse.c \
-	swfdec_js_movie.c \
-	swfdec_js_net_stream.c \
-	swfdec_js_sound.c \
-	swfdec_js_video.c \
-	swfdec_js_xml.c \
 	swfdec_listener.c \
 	swfdec_loader.c \
 	swfdec_loadertarget.c \
@@ -78,7 +77,6 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_root_movie.c \
 	swfdec_root_sprite.c \
 	swfdec_script.c \
-	swfdec_scriptable.c \
 	swfdec_shape.c \
 	swfdec_sound.c \
 	swfdec_sprite.c \
@@ -92,7 +90,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 
 libswfdec_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
 	$(GLOBAL_CFLAGS) $(CAIRO_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) \
-	-I$(srcdir)/jpeg/ $(js_cflags) $(LIBOIL_CFLAGS) $(FFMPEG_CFLAGS) \
+	-I$(srcdir)/jpeg/ $(LIBOIL_CFLAGS) $(FFMPEG_CFLAGS) \
 	-DG_LOG_DOMAIN=\"Swfdec\"
 libswfdec_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
 	-version-info $(SWFDEC_LIBVERSION) \
@@ -107,11 +105,12 @@ public_headers = \
 	swfdec_loader.h \
 	swfdec_player.h
 
-libswfdec_ at SWFDEC_MAJORMINOR@_la_LIBADD = jpeg/libjpeg.la js/libjs.la
+libswfdec_ at SWFDEC_MAJORMINOR@_la_LIBADD = jpeg/libjpeg.la 
 libswfdec_ at SWFDEC_MAJORMINOR@includedir = $(includedir)/swfdec- at SWFDEC_MAJORMINOR@/libswfdec
 libswfdec_ at SWFDEC_MAJORMINOR@include_HEADERS = $(public_headers) swfdec_enums.h
 
 noinst_HEADERS = \
+	swfdec_as_array.h \
 	swfdec_as_context.h \
 	swfdec_as_frame.h \
 	swfdec_as_function.h \
@@ -143,7 +142,6 @@ noinst_HEADERS = \
 	swfdec_graphic.h \
 	swfdec_graphic_movie.h \
 	swfdec_image.h \
-	swfdec_js.h \
 	swfdec_listener.h \
 	swfdec_loader_internal.h \
 	swfdec_loadertarget.h \
@@ -159,7 +157,6 @@ noinst_HEADERS = \
 	swfdec_root_movie.h \
 	swfdec_root_sprite.h \
 	swfdec_script.h \
-	swfdec_scriptable.h \
 	swfdec_shape.h \
 	swfdec_sound.h \
 	swfdec_sprite.h \
diff --git a/libswfdec/swfdec_amf.c b/libswfdec/swfdec_amf.c
index e1ac8ba..9e47ae3 100644
--- a/libswfdec/swfdec_amf.c
+++ b/libswfdec/swfdec_amf.c
@@ -22,140 +22,137 @@
 #endif
 
 #include "swfdec_amf.h"
-#include "swfdec_bits.h"
+#include "swfdec_as_array.h"
 #include "swfdec_debug.h"
-#include "js/jsapi.h"
 
-typedef gboolean (* SwfdecAmfParseFunc) (JSContext *cx, SwfdecBits *bits, jsval *val);
+typedef gboolean (* SwfdecAmfParseFunc) (SwfdecAsContext *cx, SwfdecBits *bits, SwfdecAsValue *val);
 extern const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES];
 
 static gboolean
-swfdec_amf_parse_boolean (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_boolean (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
-  *val = swfdec_bits_get_u8 (bits) ? JSVAL_TRUE : JSVAL_FALSE;
+  SWFDEC_AS_VALUE_SET_BOOLEAN (val, swfdec_bits_get_u8 (bits) ? TRUE : FALSE);
   return TRUE;
 }
 
 static gboolean
-swfdec_amf_parse_number (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_number (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
-  double d = swfdec_bits_get_bdouble (bits);
-
-  if (!JS_NewNumberValue (cx, d, val))
-    return FALSE;
+  SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_bits_get_bdouble (bits));
   return TRUE;
 }
 
 static gboolean
-swfdec_amf_parse_string (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_string (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
   guint len = swfdec_bits_get_bu16 (bits);
   char *s;
-  JSString *string;
   
   s = swfdec_bits_get_string_length (bits, len);
   if (s == NULL)
     return FALSE;
-
-  string = JS_NewStringCopyZ (cx, s);
-  g_free (s);
-  if (!string)
-    return FALSE;
-  *val = STRING_TO_JSVAL (string);
+  SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_get_string (context, s));
   return TRUE;
 }
+
 static gboolean
-swfdec_amf_parse_properties (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_properties (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsObject *object)
 {
   guint type;
   SwfdecAmfParseFunc func;
-  JSObject *object;
-
-  g_assert (JSVAL_IS_OBJECT (*val));
-  object = JSVAL_TO_OBJECT (*val);
 
+  /* need to root here due to GC */
+  swfdec_as_object_root (object);
   while (swfdec_bits_left (bits)) {
-    jsval id, val;
-    if (!swfdec_amf_parse_string (cx, bits, &id))
+    SwfdecAsValue id, val;
+
+    if (!swfdec_amf_parse_string (context, bits, &id))
       return FALSE;
     type = swfdec_bits_get_u8 (bits);
     if (type == SWFDEC_AMF_END_OBJECT)
-      return TRUE;
+      break;
     if (type >= SWFDEC_AMF_N_TYPES ||
 	(func = parse_funcs[type]) == NULL) {
       SWFDEC_ERROR ("no parse func for AMF type %u", type);
-      return FALSE;
+      goto error;
     }
-    if (!func (cx, bits, &val))
-      return FALSE;
-    if (!JS_SetProperty (cx, object, JS_GetStringBytes (JSVAL_TO_STRING (id)), &val))
-      return FALSE;
+    swfdec_as_object_set_variable (object, &id, &id); /* GC... */
+    if (!func (context, bits, &val)) {
+      goto error;
+    }
+    swfdec_as_object_set_variable (object, &id, &val); /* GC... */
   }
   /* no more bytes seems to end automatically */
+  swfdec_as_object_unroot (object);
   return TRUE;
+
+error:
+  swfdec_as_object_unroot (object);
+  return FALSE;
 }
 
 static gboolean
-swfdec_amf_parse_object (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_object (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
-  JSObject *object;
+  SwfdecAsObject *object;
   
-  object = JS_NewObject (cx, NULL, NULL, NULL);
+  object = swfdec_as_object_new (context);
   if (object == NULL)
     return FALSE;
-
-  *val = OBJECT_TO_JSVAL (object);
-  return swfdec_amf_parse_properties (cx, bits, val);
+  if (!swfdec_amf_parse_properties (context, bits, object))
+    return FALSE;
+  SWFDEC_AS_VALUE_SET_OBJECT (val, object);
+  return TRUE;
 }
 
 static gboolean
-swfdec_amf_parse_mixed_array (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_mixed_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
   guint len;
-  JSObject *object;
+  SwfdecAsObject *array;
   
   len = swfdec_bits_get_bu32 (bits);
-  object = JS_NewArrayObject (cx, len, NULL);
-  if (object == NULL)
+  array = swfdec_as_array_new (context, len);
+  if (array == NULL)
     return FALSE;
-
-  *val = OBJECT_TO_JSVAL (object);
-  return swfdec_amf_parse_properties (cx, bits, val);
+  if (!swfdec_amf_parse_properties (context, bits, array))
+    return FALSE;
+  SWFDEC_AS_VALUE_SET_OBJECT (val, array);
+  return TRUE;
 }
 
 static gboolean
-swfdec_amf_parse_array (JSContext *cx, SwfdecBits *bits, jsval *val)
+swfdec_amf_parse_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
   guint i, len;
-  JSObject *object;
-  jsval *vector;
+  SwfdecAsObject *array;
   guint type;
   SwfdecAmfParseFunc func;
   
   len = swfdec_bits_get_bu32 (bits);
-  vector = g_try_new (jsval, len);
-  if (vector == NULL)
+  array = swfdec_as_array_new (context, len);
+  if (array == NULL)
     return FALSE;
+  swfdec_as_object_root (array);
   for (i = 0; i < len; i++) {
     type = swfdec_bits_get_u8 (bits);
+    SwfdecAsValue val;
     if (type >= SWFDEC_AMF_N_TYPES ||
 	(func = parse_funcs[type]) == NULL) {
       SWFDEC_ERROR ("no parse func for AMF type %u", type);
       goto fail;
     }
-    if (!func (cx, bits, &vector[i]))
+    if (!func (context, bits, &val))
       goto fail;
+    g_array_append_val (SWFDEC_AS_ARRAY (array)->values, val);
   }
-  object = JS_NewArrayObject (cx, len, vector);
-  if (object == NULL)
-    goto fail;
 
-  *val = OBJECT_TO_JSVAL (object);
-  g_free (vector);
+  swfdec_as_object_unroot (array);
+  SWFDEC_AS_VALUE_SET_OBJECT (val, array);
   return TRUE;
 
 fail:
-  g_free (vector);
+  swfdec_as_object_unroot (array);
   return FALSE;
 }
 
@@ -183,13 +180,13 @@ const SwfdecAmfParseFunc parse_funcs[SWF
 };
 
 gboolean
-swfdec_amf_parse_one (JSContext *cx, SwfdecBits *bits, SwfdecAmfType expected_type, 
-    jsval *rval)
+swfdec_amf_parse_one (SwfdecAsContext *context, SwfdecBits *bits, 
+    SwfdecAmfType expected_type, SwfdecAsValue *rval)
 {
   SwfdecAmfParseFunc func;
   guint type;
 
-  g_return_val_if_fail (cx != NULL, FALSE);
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
   g_return_val_if_fail (bits != NULL, FALSE);
   g_return_val_if_fail (rval != NULL, FALSE);
   g_return_val_if_fail (expected_type < SWFDEC_AMF_N_TYPES, FALSE);
@@ -205,23 +202,24 @@ swfdec_amf_parse_one (JSContext *cx, Swf
     SWFDEC_ERROR ("no parse func for AMF type %u", type);
     return FALSE;
   }
-  return func (cx, bits, rval);
+  return func (context, bits, rval);
 }
 
+/* FIXME: parsed values aren't gc rooted... */
 guint
-swfdec_amf_parse (JSContext *cx, SwfdecBits *bits, guint n_items, ...)
+swfdec_amf_parse (SwfdecAsContext *context, SwfdecBits *bits, guint n_items, ...)
 {
   va_list args;
   guint i;
 
-  g_return_val_if_fail (cx != NULL, 0);
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
   g_return_val_if_fail (bits != NULL, 0);
 
   va_start (args, n_items);
   for (i = 0; i < n_items; i++) {
     SwfdecAmfType type = va_arg (args, SwfdecAmfType);
-    jsval *val = va_arg (args, jsval *);
-    if (!swfdec_amf_parse_one (cx, bits, type, val))
+    SwfdecAsValue *val = va_arg (args, SwfdecAsValue *);
+    if (!swfdec_amf_parse_one (context, bits, type, val))
       break;
   }
   va_end (args);
diff --git a/libswfdec/swfdec_amf.h b/libswfdec/swfdec_amf.h
index 564fbb5..0f9c67e 100644
--- a/libswfdec/swfdec_amf.h
+++ b/libswfdec/swfdec_amf.h
@@ -20,7 +20,7 @@
 #ifndef __SWFDEC_AMF_H__
 #define __SWFDEC_AMF_H__
 
-#include <libswfdec/js/jspubtd.h>
+#include <libswfdec/swfdec_as_context.h>
 #include <libswfdec/swfdec_bits.h>
 
 typedef enum {
@@ -46,13 +46,13 @@ typedef enum {
   SWFDEC_AMF_N_TYPES
 } SwfdecAmfType;
 
-gboolean	swfdec_amf_parse_one		(JSContext *	cx, 
-						 SwfdecBits *	bits,
-						 SwfdecAmfType	expected_type,
-						 jsval *	rval);
-guint		swfdec_amf_parse		(JSContext *	cx, 
-						 SwfdecBits *	bits,
-						 guint		n_items,
+gboolean	swfdec_amf_parse_one		(SwfdecAsContext *	context, 
+						 SwfdecBits *		bits,
+						 SwfdecAmfType		expected_type,
+						 SwfdecAsValue *	rval);
+guint		swfdec_amf_parse		(SwfdecAsContext *	context, 
+						 SwfdecBits *		bits,
+						 guint			n_items,
 						 ...);
 
 
diff --git a/libswfdec/swfdec_as_array.c b/libswfdec/swfdec_as_array.c
new file mode 100644
index 0000000..b436e86
--- /dev/null
+++ b/libswfdec/swfdec_as_array.c
@@ -0,0 +1,104 @@
+/* SwfdecAs
+ * Copyright (C) 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
+ * 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_as_array.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_stack.h"
+#include "swfdec_debug.h"
+
+G_DEFINE_TYPE (SwfdecAsArray, swfdec_as_array, SWFDEC_TYPE_AS_OBJECT)
+
+static void
+swfdec_as_array_dispose (GObject *object)
+{
+  SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
+
+  g_array_free (array->values, TRUE);
+
+  G_OBJECT_CLASS (swfdec_as_array_parent_class)->dispose (object);
+}
+
+static void
+swfdec_as_array_mark (SwfdecAsObject *object)
+{
+  SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
+  guint i;
+
+  for (i = 0; i < array->values->len; i++) {
+    swfdec_as_value_mark (&g_array_index (array->values, SwfdecAsValue, i));
+  }
+
+  SWFDEC_AS_OBJECT_CLASS (swfdec_as_array_parent_class)->mark (object);
+}
+
+static void
+swfdec_as_array_class_init (SwfdecAsArrayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+
+  object_class->dispose = swfdec_as_array_dispose;
+
+  asobject_class->mark = swfdec_as_array_mark;
+}
+
+static void
+swfdec_as_array_init (SwfdecAsArray *array)
+{
+  array->values = g_array_new (FALSE, TRUE, sizeof (SwfdecAsValue));
+}
+
+/**
+ * swfdec_as_array_new:
+ * @context: a #SwfdecAsContext
+ * @preallocated_items: number of items to preallocate
+ *
+ * Creates a new #SwfdecAsArray. @preallocated_items is a hint on how many
+ * space to reserve to avoid frequent reallocations later on.
+ *
+ * Returns: the new array or %NULL on OOM.
+ **/
+SwfdecAsObject *
+swfdec_as_array_new (SwfdecAsContext *context, guint preallocated_items)
+{
+  guint size;
+  SwfdecAsObject *object;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
+  if (preallocated_items > 1024) {
+    SWFDEC_INFO ("%u items is a lot, better only preallocate 1024", preallocated_items);
+    preallocated_items = 1024;
+  }
+  
+  size = sizeof (SwfdecAsArray);
+  if (!swfdec_as_context_use_mem (context, size))
+    return NULL;
+  object = g_object_new (SWFDEC_TYPE_AS_ARRAY, NULL);
+  swfdec_as_object_add (object, context, size);
+  if (preallocated_items) {
+    g_array_set_size (SWFDEC_AS_ARRAY (object)->values, preallocated_items);
+    g_array_set_size (SWFDEC_AS_ARRAY (object)->values, 0);
+  }
+  return object;
+}
+
diff --git a/libswfdec/swfdec_as_array.h b/libswfdec/swfdec_as_array.h
new file mode 100644
index 0000000..c4a2b82
--- /dev/null
+++ b/libswfdec/swfdec_as_array.h
@@ -0,0 +1,56 @@
+/* SwfdecAs
+ * Copyright (C) 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
+ * 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_AS_ARRAY_H_
+#define _SWFDEC_AS_ARRAY_H_
+
+#include <libswfdec/swfdec_as_object.h>
+#include <libswfdec/swfdec_as_types.h>
+#include <libswfdec/swfdec_script.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecAsArrayClass SwfdecAsArrayClass;
+
+#define SWFDEC_TYPE_AS_ARRAY                    (swfdec_as_array_get_type())
+#define SWFDEC_IS_AS_ARRAY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AS_ARRAY))
+#define SWFDEC_IS_AS_ARRAY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AS_ARRAY))
+#define SWFDEC_AS_ARRAY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AS_ARRAY, SwfdecAsArray))
+#define SWFDEC_AS_ARRAY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AS_ARRAY, SwfdecAsArrayClass))
+#define SWFDEC_AS_ARRAY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_ARRAY, SwfdecAsArrayClass))
+
+struct _SwfdecAsArray {
+  SwfdecAsObject	object;
+
+  GArray *		values;		/* the indexed values in the array */
+};
+
+struct _SwfdecAsArrayClass {
+  SwfdecAsObjectClass	object_class;
+};
+
+GType		swfdec_as_array_get_type	(void);
+
+SwfdecAsObject *swfdec_as_array_new		(SwfdecAsContext *	context,
+						 guint			preallocated_items);
+
+
+
+G_END_DECLS
+#endif
diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 037e146..8fe289a 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -221,13 +221,23 @@ swfdec_as_context_mark_roots (gpointer k
     swfdec_as_object_mark (object);
 }
 
+static void
+swfdec_as_context_do_mark (SwfdecAsContext *context)
+{
+  g_hash_table_foreach (context->objects, swfdec_as_context_mark_roots, NULL);
+}
+
 void
 swfdec_as_context_gc (SwfdecAsContext *context)
 {
+  SwfdecAsContextClass *klass;
+
   g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
 
   SWFDEC_INFO ("invoking the garbage collector");
-  g_hash_table_foreach (context->objects, swfdec_as_context_mark_roots, NULL);
+  klass = SWFDEC_AS_CONTEXT_GET_CLASS (context);
+  g_assert (klass->mark);
+  klass->mark (context);
   swfdec_as_context_collect (context);
 }
 
@@ -257,6 +267,8 @@ swfdec_as_context_class_init (SwfdecAsCo
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_as_context_dispose;
+
+  klass->mark = swfdec_as_context_do_mark;
 }
 
 static void
@@ -451,3 +463,177 @@ swfdec_as_context_return (SwfdecAsContex
     swfdec_as_stack_push (context->frame->stack, &value);
   }
 }
+
+/*** EVAL ***/
+
+char *
+swfdec_as_slash_to_dot (const char *slash_str)
+{
+  const char *cur = slash_str;
+  GString *str = g_string_new ("");
+
+  if (*cur == '/') {
+    g_string_append (str, "_root");
+  } else {
+    goto start;
+  }
+  while (cur && *cur == '/') {
+    cur++;
+start:
+    if (str->len > 0)
+      g_string_append_c (str, '.');
+    if (cur[0] == '.' && cur[1] == '.') {
+      g_string_append (str, "_parent");
+      cur += 2;
+    } else {
+      char *slash = strchr (cur, '/');
+      if (slash) {
+	g_string_append_len (str, cur, slash - cur);
+	cur = slash;
+      } else {
+	g_string_append (str, cur);
+	cur = NULL;
+      }
+    }
+    /* cur should now point to the slash */
+  }
+  if (cur) {
+    if (*cur != '\0')
+      goto fail;
+  }
+  SWFDEC_DEBUG ("parsed slash-notated string \"%s\" into dot notation \"%s\"",
+      slash_str, str->str);
+  return g_string_free (str, FALSE);
+
+fail:
+  SWFDEC_WARNING ("failed to parse slash-notated string \"%s\" into dot notation", slash_str);
+  g_string_free (str, TRUE);
+  return NULL;
+}
+
+static void
+swfdec_as_context_eval_get_property (SwfdecAsContext *cx, 
+    SwfdecAsObject *obj, const char *name, SwfdecAsValue *ret)
+{
+  if (obj) {
+    swfdec_as_object_get (obj, name, ret);
+  } else {
+    g_assert_not_reached ();
+#if 0
+    if (cx->fp == NULL || cx->fp->scopeChain == NULL)
+      return JS_FALSE;
+    if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
+      return JS_FALSE;
+    if (!prop)
+      return JS_FALSE;
+    return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret);
+#endif
+  }
+}
+
+static void
+swfdec_as_context_eval_set_property (SwfdecAsContext *cx, 
+    SwfdecAsObject *obj, const char *name, const SwfdecAsValue *ret)
+{
+  if (obj == NULL) {
+    g_assert_not_reached ();
+#if 0
+    JSObject *pobj;
+    JSProperty *prop;
+    if (cx->fp == NULL || cx->fp->varobj == NULL)
+      return JS_FALSE;
+    if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
+      return JS_FALSE;
+    if (pobj)
+      obj = pobj;
+    else
+      obj = cx->fp->varobj;
+#endif
+  }
+  return swfdec_as_object_set (obj, name, ret);
+}
+
+static void
+swfdec_as_context_eval_internal (SwfdecAsContext *cx, SwfdecAsObject *obj, const char *str,
+        SwfdecAsValue *val, gboolean set)
+{
+  SwfdecAsValue cur;
+  char **varlist;
+  guint i;
+
+  SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj);
+  if (strchr (str, '/')) {
+    char *work = swfdec_as_slash_to_dot (str);
+    if (!work) {
+      SWFDEC_AS_VALUE_SET_UNDEFINED (val);
+      return;
+    }
+    varlist = g_strsplit (work, ".", -1);
+    g_free (work);
+  } else {
+    varlist = g_strsplit (str, ".", -1);
+  }
+  SWFDEC_AS_VALUE_SET_OBJECT (&cur, obj); /* FIXME: can be NULL here */
+  for (i = 0; varlist[i] != NULL; i++) {
+    const char *dot = swfdec_as_context_get_string (cx, varlist[i]);
+    if (!SWFDEC_AS_VALUE_IS_OBJECT (&cur)) {
+      SWFDEC_AS_VALUE_SET_UNDEFINED (&cur);
+      break;
+    }
+    obj = SWFDEC_AS_VALUE_GET_OBJECT (&cur);
+    if (varlist[i+1] != NULL) {
+      swfdec_as_context_eval_get_property (cx, obj, dot, &cur);
+    } else {
+      if (set) {
+	swfdec_as_context_eval_set_property (cx, obj, dot, &cur);
+      } else {
+	swfdec_as_context_eval_get_property (cx, obj, dot, &cur);
+      }
+      goto finish;
+    }
+  }
+  if (obj == NULL && cx->frame) {
+    swfdec_as_object_get (SWFDEC_AS_OBJECT (cx->frame), SWFDEC_AS_STR_THIS, &cur);
+  }
+
+finish:
+  g_strfreev (varlist);
+  *val = cur;
+}
+
+/**
+ * swfdec_as_context_eval:
+ * @context: a #SwfdecAsContext
+ * @obj: #SwfdecAsObject to use as source for evaluating or NULL for the 
+ *       current frame's scope
+ * @str: The string to evaluate
+ * @val: location for the return value
+ *
+ * This function works like the Actionscript eval function used on @obj.
+ * It handles both slash-style and dot-style notation. If an error occured
+ * during evaluation, the return value will be the undefined value.
+ **/
+void
+swfdec_as_context_eval (SwfdecAsContext *cx, SwfdecAsObject *obj, const char *str, 
+    SwfdecAsValue *val)
+{
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (cx));
+  g_return_if_fail (obj == NULL || SWFDEC_IS_AS_OBJECT (obj));
+  g_return_if_fail (str != NULL);
+  g_return_if_fail (val != NULL);
+
+  swfdec_as_context_eval_internal (cx, obj, str, val, FALSE);
+}
+
+void
+swfdec_as_context_eval_set (SwfdecAsContext *cx, SwfdecAsObject *obj, const char *str,
+    const SwfdecAsValue *val)
+{
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (cx));
+  g_return_if_fail (obj == NULL || SWFDEC_IS_AS_OBJECT (obj));
+  g_return_if_fail (str != NULL);
+  g_return_if_fail (val != NULL);
+
+  swfdec_as_context_eval_internal (cx, obj, str, (SwfdecAsValue *) val, TRUE);
+}
+
diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h
index b3061f7..c1d12dc 100644
--- a/libswfdec/swfdec_as_context.h
+++ b/libswfdec/swfdec_as_context.h
@@ -60,6 +60,9 @@ struct _SwfdecAsContext {
 
 struct _SwfdecAsContextClass {
   GObjectClass		object_class;
+
+  /* mark all objects that should not be collected */
+  void			(* mark)		(SwfdecAsContext *	context);
 };
 
 GType		swfdec_as_context_get_type	(void);
@@ -82,8 +85,18 @@ void		swfdec_as_value_mark		(SwfdecAsVal
 void		swfdec_as_string_mark		(const char *		string);
 void		swfdec_as_context_gc		(SwfdecAsContext *	context);
 
+void		swfdec_as_context_run		(SwfdecAsContext *	context);
 void		swfdec_as_context_return	(SwfdecAsContext *	context,
 						 SwfdecAsValue *	retval);
 
+void		swfdec_as_context_eval		(SwfdecAsContext *	cx,
+						 SwfdecAsObject *	obj,
+						 const char *		str,
+						 SwfdecAsValue *	val);
+void		swfdec_as_context_eval_set	(SwfdecAsContext *	cx,
+						 SwfdecAsObject *	obj,
+						 const char *		str,
+						 const SwfdecAsValue *	val);
+
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 34db07b..6f5ac61 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -23,6 +23,7 @@
 
 #include "swfdec_as_object.h"
 #include "swfdec_as_context.h"
+#include "swfdec_as_function.h"
 #include "swfdec_debug.h"
 
 
@@ -39,7 +40,7 @@ swfdec_as_object_dispose (GObject *gobje
 {
   SwfdecAsObject *object = SWFDEC_AS_OBJECT (gobject);
 
-  g_assert (object->properties == NULL);
+  g_assert (!SWFDEC_AS_OBJECT_HAS_CONTEXT (object));
 
   G_OBJECT_CLASS (swfdec_as_object_parent_class)->dispose (gobject);
 }
@@ -80,7 +81,7 @@ swfdec_as_object_init (SwfdecAsObject *o
  *
  * Allocates a new Object. This does the same as the Actionscript code 
  * "new Object()".
- * <warn>This function may run the garbage collector.</warn>
+ * <warning>This function may run the garbage collector.</warning>
  *
  * Returns: the new object or NULL on out of memory.
  **/
@@ -115,7 +116,7 @@ swfdec_as_object_add (SwfdecAsObject *ob
 {
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
   g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
-  g_return_if_fail (object->properties == NULL);
+  g_return_if_fail (!SWFDEC_AS_OBJECT_HAS_CONTEXT (object));
 
   object->context = context;
   object->size = size;
@@ -136,7 +137,7 @@ void
 swfdec_as_object_collect (SwfdecAsObject *object)
 {
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
-  g_return_if_fail (object->properties != NULL);
+  g_return_if_fail (SWFDEC_AS_OBJECT_HAS_CONTEXT (object));
 
   g_hash_table_foreach (object->properties, swfdec_as_object_free_property, object);
   g_hash_table_destroy (object->properties);
@@ -248,3 +249,43 @@ swfdec_as_object_delete_variable (Swfdec
   }
 }
 
+/**
+ * swfdec_as_object_run:
+ * @object: a #SwfdecAsObject
+ * @script: script to execute
+ *
+ * Executes the given @script with @object as this pointer.
+ **/
+void
+swfdec_as_object_run (SwfdecAsObject *object, SwfdecScript *script)
+{
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
+  g_return_if_fail (SWFDEC_AS_OBJECT_HAS_CONTEXT (object));
+  g_return_if_fail (script != NULL);
+
+  g_assert_not_reached ();
+  swfdec_as_context_run (object->context);
+}
+
+void
+swfdec_as_object_call (SwfdecAsObject *object, const char *name, guint argc, SwfdecAsValue *argv)
+{
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (argc == 0 || argv != NULL);
+}
+
+gboolean
+swfdec_as_object_has_function (SwfdecAsObject *object, const char *name)
+{
+  SwfdecAsValue val;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), FALSE);
+  g_return_val_if_fail (name != NULL, FALSE);
+
+  swfdec_as_object_get (object, name, &val);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&val))
+    return FALSE;
+  return SWFDEC_IS_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (&val));
+}
+
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index 0accee4..6462784 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -22,6 +22,7 @@
 
 #include <glib-object.h>
 #include <libswfdec/swfdec_as_types.h>
+#include <libswfdec/swfdec_types.h>
 
 G_BEGIN_DECLS
 
@@ -40,6 +41,8 @@ typedef struct _SwfdecAsObjectClass Swfd
 #define SWFDEC_AS_OBJECT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AS_OBJECT, SwfdecAsObjectClass))
 #define SWFDEC_AS_OBJECT_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_OBJECT, SwfdecAsObjectClass))
 
+#define SWFDEC_AS_OBJECT_HAS_CONTEXT(obj)	 (SWFDEC_AS_OBJECT (obj)->properties != NULL)
+
 struct _SwfdecAsObject {
   GObject		object;
 
@@ -89,6 +92,14 @@ void		swfdec_as_object_delete_variable(S
   swfdec_as_object_get_variable ((object), &__variable, (value)); \
 }G_STMT_END
 
+void		swfdec_as_object_run		(SwfdecAsObject *       object,
+						 SwfdecScript *		script);
+gboolean	swfdec_as_object_has_function	(SwfdecAsObject *       object,
+						 const char *		name);
+void		swfdec_as_object_call		(SwfdecAsObject *       object,
+						 const char *		name,
+						 guint			argc,
+						 SwfdecAsValue *	argv);
 
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_as_types.c b/libswfdec/swfdec_as_types.c
index 2b84330..12f0d44 100644
--- a/libswfdec/swfdec_as_types.c
+++ b/libswfdec/swfdec_as_types.c
@@ -31,6 +31,37 @@ const char *swfdec_as_strings[] = {
   SWFDEC_AS_CONSTANT_STRING (""),
   SWFDEC_AS_CONSTANT_STRING ("__proto__"),
   SWFDEC_AS_CONSTANT_STRING ("this"),
+  SWFDEC_AS_CONSTANT_STRING ("code"),
+  SWFDEC_AS_CONSTANT_STRING ("level"),
+  SWFDEC_AS_CONSTANT_STRING ("description"),
+  SWFDEC_AS_CONSTANT_STRING ("status"),
+  SWFDEC_AS_CONSTANT_STRING ("success"),
+  SWFDEC_AS_CONSTANT_STRING ("NetConnection.Connect.Success"),
+  SWFDEC_AS_CONSTANT_STRING ("onLoad"),
+  SWFDEC_AS_CONSTANT_STRING ("onEnterFrame"),
+  SWFDEC_AS_CONSTANT_STRING ("onUnload"),
+  SWFDEC_AS_CONSTANT_STRING ("onMouseMove"),
+  SWFDEC_AS_CONSTANT_STRING ("onMouseDown"),
+  SWFDEC_AS_CONSTANT_STRING ("onMouseUp"),
+  SWFDEC_AS_CONSTANT_STRING ("onKeyUp"),
+  SWFDEC_AS_CONSTANT_STRING ("onKeyDown"),
+  SWFDEC_AS_CONSTANT_STRING ("onData"),
+  SWFDEC_AS_CONSTANT_STRING ("onPress"),
+  SWFDEC_AS_CONSTANT_STRING ("onRelease"),
+  SWFDEC_AS_CONSTANT_STRING ("onReleaseOutside"),
+  SWFDEC_AS_CONSTANT_STRING ("onRollOver"),
+  SWFDEC_AS_CONSTANT_STRING ("onRollOut"),
+  SWFDEC_AS_CONSTANT_STRING ("onDragOver"),
+  SWFDEC_AS_CONSTANT_STRING ("onDragOut"),
+  SWFDEC_AS_CONSTANT_STRING ("onConstruct"),
+  SWFDEC_AS_CONSTANT_STRING ("onStatus"),
+  SWFDEC_AS_CONSTANT_STRING ("error"),
+  SWFDEC_AS_CONSTANT_STRING ("NetStream.Buffer.Empty"),
+  SWFDEC_AS_CONSTANT_STRING ("NetStream.Buffer.Full"),
+  SWFDEC_AS_CONSTANT_STRING ("NetStream.Buffer.Flush"),
+  SWFDEC_AS_CONSTANT_STRING ("NetStream.Play.Start"),
+  SWFDEC_AS_CONSTANT_STRING ("NetStream.Play.Stop"),
+  SWFDEC_AS_CONSTANT_STRING ("NetStream.Play.StreamNotFound"),
   /* add more here */
   NULL
 };
diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h
index 9a293a4..92a7355 100644
--- a/libswfdec/swfdec_as_types.h
+++ b/libswfdec/swfdec_as_types.h
@@ -34,12 +34,14 @@ G_BEGIN_DECLS
 #define SWFDEC_TYPE_AS_ASOBJECT	(6)
 
 typedef guint8 SwfdecAsType;
+typedef struct _SwfdecAsArray SwfdecAsArray;
 typedef struct _SwfdecAsContext SwfdecAsContext;
 typedef struct _SwfdecAsFrame SwfdecAsFrame;
 typedef struct _SwfdecAsObject SwfdecAsObject;
 typedef struct _SwfdecAsStack SwfdecAsStack;
 typedef struct _SwfdecAsValue SwfdecAsValue;
 
+/* IMPORTANT: a SwfdecAsValue memset to 0 is a valid undefined value */
 struct _SwfdecAsValue {
   SwfdecAsType		type;
   union {
@@ -92,6 +94,37 @@ extern const char *swfdec_as_strings[];
 #define SWFDEC_AS_STR_EMPTY (swfdec_as_strings[0] + 1)
 #define SWFDEC_AS_STR_PROTO (swfdec_as_strings[1] + 1)
 #define SWFDEC_AS_STR_THIS (swfdec_as_strings[2] + 1)
+#define SWFDEC_AS_STR_CODE (swfdec_as_strings[3] + 1)
+#define SWFDEC_AS_STR_LEVEL (swfdec_as_strings[4] + 1)
+#define SWFDEC_AS_STR_DESCRIPTION (swfdec_as_strings[5] + 1)
+#define SWFDEC_AS_STR_STATUS (swfdec_as_strings[6] + 1)
+#define SWFDEC_AS_STR_SUCCESS (swfdec_as_strings[7] + 1)
+#define SWFDEC_AS_STR_NET_CONNECTION_CONNECT_SUCCESS (swfdec_as_strings[8] + 1)
+#define SWFDEC_AS_STR_ON_LOAD (swfdec_as_strings[9] + 1)
+#define SWFDEC_AS_STR_ON_ENTER_FRAME (swfdec_as_strings[10] + 1)
+#define SWFDEC_AS_STR_ON_UNLOAD (swfdec_as_strings[11] + 1)
+#define SWFDEC_AS_STR_ON_MOUSE_MOVE (swfdec_as_strings[12] + 1)
+#define SWFDEC_AS_STR_ON_MOUSE_DOWN (swfdec_as_strings[13] + 1)
+#define SWFDEC_AS_STR_ON_MOUSE_UP (swfdec_as_strings[14] + 1)
+#define SWFDEC_AS_STR_ON_KEY_UP (swfdec_as_strings[15] + 1)
+#define SWFDEC_AS_STR_ON_KEY_DOWN (swfdec_as_strings[16] + 1)
+#define SWFDEC_AS_STR_ON_DATA (swfdec_as_strings[17] + 1)
+#define SWFDEC_AS_STR_ON_PRESS (swfdec_as_strings[18] + 1)
+#define SWFDEC_AS_STR_ON_RELEASE (swfdec_as_strings[19] + 1)
+#define SWFDEC_AS_STR_ON_RELEASE_OUTSIDE (swfdec_as_strings[20] + 1)
+#define SWFDEC_AS_STR_ON_ROLL_OVER (swfdec_as_strings[21] + 1)
+#define SWFDEC_AS_STR_ON_ROLL_OUT (swfdec_as_strings[22] + 1)
+#define SWFDEC_AS_STR_ON_DRAG_OVER (swfdec_as_strings[23] + 1)
+#define SWFDEC_AS_STR_ON_DRAG_OUT (swfdec_as_strings[24] + 1)
+#define SWFDEC_AS_STR_ON_CONSTRUCT (swfdec_as_strings[25] + 1)
+#define SWFDEC_AS_STR_ON_STATUS (swfdec_as_strings[26] + 1)
+#define SWFDEC_AS_STR_ERROR (swfdec_as_strings[27] + 1)
+#define SWFDEC_AS_STR_NETSTREAM_BUFFER_EMPTY (swfdec_as_strings[28] + 1)
+#define SWFDEC_AS_STR_NETSTREAM_BUFFER_FULL (swfdec_as_strings[29] + 1)
+#define SWFDEC_AS_STR_NETSTREAM_BUFFER_FLUSH (swfdec_as_strings[30] + 1)
+#define SWFDEC_AS_STR_NETSTREAM_PLAY_START (swfdec_as_strings[31] + 1)
+#define SWFDEC_AS_STR_NETSTREAM_PLAY_STOP (swfdec_as_strings[32] + 1)
+#define SWFDEC_AS_STR_NETSTREAM_PLAY_STREAMNOTFOUND (swfdec_as_strings[33] + 1)
 
 /* all existing actions */
 typedef enum {
diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 13eed56..d537952 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -23,7 +23,6 @@
 #include "config.h"
 #endif
 #include <string.h>
-#include <js/jsapi.h>
 #include "swfdec_button.h"
 #include "swfdec_button_movie.h"
 #include "swfdec_sound.h"
@@ -60,11 +59,12 @@ swfdec_button_dispose (GObject *object)
 }
 
 static SwfdecMovie *
-swfdec_button_create_movie (SwfdecGraphic *graphic)
+swfdec_button_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
   SwfdecButtonMovie *movie = g_object_new (SWFDEC_TYPE_BUTTON_MOVIE, NULL);
 
   movie->button = SWFDEC_BUTTON (graphic);
+  *size = sizeof (SwfdecButtonMovie);
 
   return SWFDEC_MOVIE (movie);
 }
diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 3c7b0b4..15267b6 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -107,9 +107,9 @@ swfdec_button_movie_execute (SwfdecButto
   }
   if (movie->button->events)
     swfdec_event_list_execute (movie->button->events, 
-	SWFDEC_SCRIPTABLE (SWFDEC_MOVIE (movie)->parent), condition, 0);
+	SWFDEC_AS_OBJECT (SWFDEC_MOVIE (movie)->parent), condition, 0);
   name = swfdec_button_condition_get_name (condition);
-  swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (movie), name, 0, NULL);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL);
 }
 
 #define CONTENT_IN_FRAME(content, frame) \
diff --git a/libswfdec/swfdec_connection.c b/libswfdec/swfdec_connection.c
index 464affb..d55c916 100644
--- a/libswfdec/swfdec_connection.c
+++ b/libswfdec/swfdec_connection.c
@@ -23,13 +23,13 @@
 
 #include <string.h>
 #include "swfdec_connection.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_object.h"
 #include "swfdec_debug.h"
-#include "js/jsapi.h"
-#include "js/jsinterp.h"
 
 /*** SwfdecConnection ***/
 
-G_DEFINE_TYPE (SwfdecConnection, swfdec_connection, SWFDEC_TYPE_SCRIPTABLE)
+G_DEFINE_TYPE (SwfdecConnection, swfdec_connection, SWFDEC_TYPE_AS_OBJECT)
 
 static void
 swfdec_connection_dispose (GObject *object)
@@ -42,16 +42,12 @@ swfdec_connection_dispose (GObject *obje
   G_OBJECT_CLASS (swfdec_connection_parent_class)->dispose (object);
 }
 
-extern const JSClass connection_class;
 static void
 swfdec_connection_class_init (SwfdecConnectionClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecScriptableClass *scriptable_class = SWFDEC_SCRIPTABLE_CLASS (klass);
 
   object_class->dispose = swfdec_connection_dispose;
-
-  scriptable_class->jsclass = &connection_class;
 }
 
 static void
@@ -63,46 +59,37 @@ static void
 swfdec_connection_onstatus (SwfdecConnection *conn, const char *code,
     const char *level, const char *description)
 {
-  JSContext *cx = SWFDEC_SCRIPTABLE (conn)->jscx;
-  JSObject *obj = SWFDEC_SCRIPTABLE (conn)->jsobj;
-  JSObject *info;
-  jsval val, fun;
-  JSString *string;
+  SwfdecAsValue value;
+  SwfdecAsObject *info;
 
-  if (!JS_GetProperty (cx, obj, "onStatus", &fun))
-    return;
-  if (fun == JSVAL_VOID)
-    return;
-  info = JS_NewObject (cx, NULL, NULL, NULL);
-  if (info == NULL ||
-      (string = JS_NewStringCopyZ (cx, code)) == NULL ||
-      (val = STRING_TO_JSVAL (string)) == 0 ||
-      !JS_SetProperty (cx, info, "code", &val) ||
-      (string = JS_NewStringCopyZ (cx, level)) == NULL ||
-      (val = STRING_TO_JSVAL (string)) == 0 ||
-      !JS_SetProperty (cx, info, "level", &val))
+  info = swfdec_as_object_new (SWFDEC_AS_OBJECT (conn)->context);
+  if (info == NULL)
     return;
+  swfdec_as_object_root (info);
+  SWFDEC_AS_VALUE_SET_STRING (&value, code);
+  swfdec_as_object_set (info, SWFDEC_AS_STR_CODE, &value);
+  SWFDEC_AS_VALUE_SET_STRING (&value, level);
+  swfdec_as_object_set (info, SWFDEC_AS_STR_LEVEL, &value);
   if (description) {
-    if ((string = JS_NewStringCopyZ (cx, level)) == NULL ||
-	(val = STRING_TO_JSVAL (string)) == 0 ||
-	!JS_SetProperty (cx, info, "description", &val))
-      return;
+    SWFDEC_AS_VALUE_SET_STRING (&value, description);
+    swfdec_as_object_set (info, SWFDEC_AS_STR_DESCRIPTION, &value);
   }
-  val = OBJECT_TO_JSVAL (info);
-  js_InternalCall (cx, obj, fun, 1, &val, &fun);
+  SWFDEC_AS_VALUE_SET_OBJECT (&value, info);
+  swfdec_as_object_unroot (info);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (conn), SWFDEC_AS_STR_STATUS, 1, &value);
 }
 
 SwfdecConnection *
-swfdec_connection_new (JSContext *cx)
+swfdec_connection_new (SwfdecAsContext *context)
 {
   SwfdecConnection *conn;
-  SwfdecScriptable *script;
 
-  g_return_val_if_fail (cx != NULL, NULL);
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
+  if (!swfdec_as_context_use_mem (context, sizeof (SwfdecConnection)))
+    return NULL;
   conn = g_object_new (SWFDEC_TYPE_CONNECTION, NULL);
-  script = SWFDEC_SCRIPTABLE (conn);
-  script->jscx = cx;
+  swfdec_as_object_add (SWFDEC_AS_OBJECT (conn), context, sizeof (SwfdecConnection));
 
   return conn;
 }
@@ -117,7 +104,7 @@ swfdec_connection_connect (SwfdecConnect
   if (url) {
     SWFDEC_ERROR ("FIXME: using NetConnection with non-null URLs is not implemented");
   }
-  swfdec_connection_onstatus (conn, "NetConnection.Connect.Success",
-      "status", NULL);
+  swfdec_connection_onstatus (conn, SWFDEC_AS_STR_NET_CONNECTION_CONNECT_SUCCESS,
+       SWFDEC_AS_STR_SUCCESS, NULL);
 }
 
diff --git a/libswfdec/swfdec_connection.h b/libswfdec/swfdec_connection.h
index 7219a89..d093c30 100644
--- a/libswfdec/swfdec_connection.h
+++ b/libswfdec/swfdec_connection.h
@@ -20,7 +20,7 @@
 #ifndef _SWFDEC_CONNECTION_H_
 #define _SWFDEC_CONNECTION_H_
 
-#include <libswfdec/swfdec_scriptable.h>
+#include <libswfdec/swfdec_as_object.h>
 
 G_BEGIN_DECLS
 
@@ -36,18 +36,18 @@ typedef struct _SwfdecConnectionClass Sw
 #define SWFDEC_CONNECTION_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_CONNECTION, SwfdecConnectionClass))
 
 struct _SwfdecConnection {
-  SwfdecScriptable	scriptable;
+  SwfdecAsObject	object;
 
   char *		url;		/* url for this connection or NULL for none */
 };
 
 struct _SwfdecConnectionClass {
-  SwfdecScriptableClass	scriptable_class;
+  SwfdecAsObjectClass	object_class;
 };
 
 GType			swfdec_connection_get_type	(void);
 
-SwfdecConnection *	swfdec_connection_new		(JSContext *		cx);
+SwfdecConnection *	swfdec_connection_new		(SwfdecAsContext *	context);
 
 void			swfdec_connection_connect	(SwfdecConnection *	conn,
 							 const char *		url);
diff --git a/libswfdec/swfdec_debugger.c b/libswfdec/swfdec_debugger.c
index 5e3cebc..52fb38c 100644
--- a/libswfdec/swfdec_debugger.c
+++ b/libswfdec/swfdec_debugger.c
@@ -25,11 +25,8 @@
 #include "swfdec_debugger.h"
 #include "swfdec_debug.h"
 #include "swfdec_decoder.h"
-#include "swfdec_js.h"
 #include "swfdec_movie.h"
 #include "swfdec_player_internal.h"
-#include "js/jsdbgapi.h"
-#include "js/jsinterp.h" /* for frame->swf */
 
 /*** SwfdecDebuggerScript ***/
 
@@ -112,7 +109,7 @@ swfdec_debugger_print_push (ScriptParser
 	break;
       default:
 	SWFDEC_ERROR ("Push: type %u not implemented", type);
-	return JS_FALSE;
+	return NULL;
     }
   }
   return g_string_free (string, FALSE);
@@ -321,6 +318,7 @@ typedef struct {
   guint				line;
 } Breakpoint;
 
+#if 0
 static void
 swfdec_debugger_do_breakpoint (SwfdecDebugger *debugger, guint id)
 {
@@ -345,22 +343,7 @@ swfdec_debugger_do_breakpoint (SwfdecDeb
 
   g_object_freeze_notify (G_OBJECT (debugger));
 }
-
-static JSTrapStatus
-swfdec_debugger_interrupt_cb (JSContext *cx, JSScript *script,
-        jsbytecode *pc, jsval *rval, void *debugger)
-{
-  SwfdecDebuggerScript *dscript;
-  guint line;
-  if (!swfdec_debugger_get_current (debugger, &dscript, &line))
-    return JSTRAP_CONTINUE; 
-  if (dscript->commands[line].breakpoint) {
-    swfdec_debugger_do_breakpoint (debugger, dscript->commands[line].breakpoint);
-  } else if (SWFDEC_DEBUGGER (debugger)->stepping) {
-    swfdec_debugger_do_breakpoint (debugger, 0);
-  }
-  return JSTRAP_CONTINUE;
-}
+#endif
 
 static void
 swfdec_debugger_update_interrupting (SwfdecDebugger *debugger)
@@ -377,10 +360,9 @@ swfdec_debugger_update_interrupting (Swf
     }
   }
   if (should_interrupt) {
-    JS_SetInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), 
-	swfdec_debugger_interrupt_cb, debugger);
+    g_assert_not_reached ();
   } else {
-    JS_ClearInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), NULL, NULL);
+    g_assert_not_reached ();
   }
 }
 
@@ -444,8 +426,8 @@ swfdec_debugger_unset_breakpoint (Swfdec
 }
 
 static gboolean
-swfdec_debugger_get_from_js (SwfdecDebugger *debugger, SwfdecScript *script, 
-    jsbytecode *pc, SwfdecDebuggerScript **script_out, guint *line_out)
+swfdec_debugger_get_from_as (SwfdecDebugger *debugger, SwfdecScript *script, 
+    guint8 *pc, SwfdecDebuggerScript **script_out, guint *line_out)
 {
   guint line;
   SwfdecDebuggerScript *dscript = swfdec_debugger_get_script (debugger, script);
@@ -460,7 +442,7 @@ swfdec_debugger_get_from_js (SwfdecDebug
 	*line_out = line;
       return TRUE;
     }
-    if (pc < (jsbytecode *) dscript->commands[line].code)
+    if (pc < (guint8 *) dscript->commands[line].code)
       return FALSE;
   }
   return FALSE;
@@ -470,18 +452,8 @@ gboolean
 swfdec_debugger_get_current (SwfdecDebugger *debugger,
     SwfdecDebuggerScript **dscript, guint *line)
 {
-  JSStackFrame *frame = NULL;
-  JSContext *cx;
-  jsbytecode *pc;
-
-  cx = SWFDEC_PLAYER (debugger)->jscx;
-  JS_FrameIterator (cx, &frame);
-  if (frame == NULL)
-    return FALSE;
-  if (frame->swf == NULL)
-    return FALSE;
-  pc = JS_GetFramePC (cx, frame);
-  return swfdec_debugger_get_from_js (debugger, frame->swf, pc, dscript, line);
+  /* totally bogus code just to avoid gcc warning */
+  return swfdec_debugger_get_from_as (debugger, NULL, NULL, dscript, line);
 }
 
 gboolean
@@ -542,7 +514,6 @@ swfdec_debugger_run (SwfdecDebugger *deb
 {
   SwfdecPlayer *player;
   GList *walk;
-  jsval rval;
   const char *ret;
 
   g_return_val_if_fail (SWFDEC_IS_DEBUGGER (debugger), NULL);
@@ -552,11 +523,7 @@ swfdec_debugger_run (SwfdecDebugger *deb
   g_object_freeze_notify (G_OBJECT (debugger));
 
 
-  if (swfdec_js_run (player, command, &rval)) {
-    ret = swfdec_js_to_string (player->jscx, rval);
-  } else {
-    ret = NULL;
-  }
+  SWFDEC_ERROR ("ooops");
 
 
   for (walk = player->roots; walk; walk = walk->next) {
diff --git a/libswfdec/swfdec_edittext.c b/libswfdec/swfdec_edittext.c
index 151feb2..11245d7 100644
--- a/libswfdec/swfdec_edittext.c
+++ b/libswfdec/swfdec_edittext.c
@@ -1,15 +1,32 @@
+/* Swfdec
+ * Copyright (C) 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
+ * 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 <pango/pangocairo.h>
 #include <string.h>
-#include <js/jsapi.h>
 #include "swfdec_edittext.h"
 #include "swfdec_debug.h"
 #include "swfdec_edittext_movie.h"
 #include "swfdec_font.h"
-#include "swfdec_js.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_swf_decoder.h"
 
@@ -22,7 +39,7 @@ swfdec_edit_text_mouse_in (SwfdecGraphic
 }
 
 static SwfdecMovie *
-swfdec_edit_text_create_movie (SwfdecGraphic *graphic)
+swfdec_edit_text_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
   SwfdecEditText *text = SWFDEC_EDIT_TEXT (graphic);
   SwfdecEditTextMovie *ret = g_object_new (SWFDEC_TYPE_EDIT_TEXT_MOVIE, NULL);
@@ -30,6 +47,7 @@ swfdec_edit_text_create_movie (SwfdecGra
   ret->text = text;
   if (text->text)
     swfdec_edit_text_movie_set_text (ret, text->text);
+  *size = sizeof (SwfdecEditTextMovie);
 
   return SWFDEC_MOVIE (ret);
 }
@@ -40,10 +58,9 @@ swfdec_edit_text_dispose (GObject *objec
   SwfdecEditText *text = SWFDEC_EDIT_TEXT (object);
 
   g_free (text->text);
+  text->text = NULL;
   g_free (text->variable);
   text->variable = NULL;
-  g_free (text->variable_prefix);
-  text->variable_prefix = NULL;
   
   G_OBJECT_CLASS (swfdec_edit_text_parent_class)->dispose (object);
 }
@@ -65,34 +82,6 @@ swfdec_edit_text_init (SwfdecEditText * 
   text->max_length = G_MAXUINT;
 }
 
-static void
-swfdec_edit_text_parse_variable (SwfdecEditText *text)
-{
-  char *s;
-
-  if (text->variable && text->variable[0] == '\0') {
-    g_free (text->variable);
-    text->variable = NULL;
-    return;
-  }
-  /* FIXME: check the variable for valid identifiers */
-  if (strchr (text->variable, '/')) {
-    char *ret = swfdec_js_slash_to_dot (text->variable);
-    g_free (text->variable);
-    text->variable = ret;
-  }
-  if (!text->variable)
-    return;
-  s = strrchr (text->variable, '.');
-  if (s) {
-    guint len = s - text->variable;
-    text->variable_prefix = g_strndup (text->variable, len);
-    text->variable_name = s + 1;
-  } else {
-    text->variable_name = text->variable;
-  }
-}
-
 int
 tag_func_define_edit_text (SwfdecSwfDecoder * s)
 {
@@ -178,7 +167,6 @@ tag_func_define_edit_text (SwfdecSwfDeco
     text->spacing = swfdec_bits_get_s16 (b);
   }
   text->variable = swfdec_bits_get_string (b);
-  swfdec_edit_text_parse_variable (text);
   if (has_text)
     text->text = swfdec_bits_get_string (b);
 
diff --git a/libswfdec/swfdec_edittext.h b/libswfdec/swfdec_edittext.h
index d6051ec..0bf5c27 100644
--- a/libswfdec/swfdec_edittext.h
+++ b/libswfdec/swfdec_edittext.h
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 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
@@ -67,8 +67,6 @@ struct _SwfdecEditText
 
   /* variable info */
   char *		variable;	/* full name of the variable in dot notation */
-  char *		variable_prefix;/* prefix of the variable (or NULL) */
-  char *		variable_name;	/* name of the variable without dots */
   gboolean		readonly;
 };
 
diff --git a/libswfdec/swfdec_edittext_movie.c b/libswfdec/swfdec_edittext_movie.c
index 421f6bc..1cef508 100644
--- a/libswfdec/swfdec_edittext_movie.c
+++ b/libswfdec/swfdec_edittext_movie.c
@@ -22,8 +22,8 @@
 #endif
 
 #include "swfdec_edittext_movie.h"
+#include "swfdec_as_context.h"
 #include "swfdec_debug.h"
-#include "swfdec_js.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_root_movie.h"
 
@@ -68,26 +68,21 @@ static void
 swfdec_edit_text_movie_iterate (SwfdecMovie *movie)
 {
   SwfdecEditTextMovie *text = SWFDEC_EDIT_TEXT_MOVIE (movie);
-  SwfdecScriptable *parent;
-  JSObject *jsobj;
-  jsval val;
+  SwfdecAsObject *parent;
   const char *s;
+  SwfdecAsValue val = { 0, };
 
   if (text->text->variable == NULL)
     return;
 
-  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))
+  parent = SWFDEC_AS_OBJECT (movie->parent);
+  swfdec_as_context_eval (parent->context, parent, text->text->variable, &val);
+  if (SWFDEC_AS_VALUE_IS_UNDEFINED (&val))
     return;
 
-  s = swfdec_js_to_string (parent->jscx, val);
-  if (!s && !text->str)
-    return;
-  if (s && text->str && g_str_equal (s, text->str))
+  s = swfdec_as_value_to_string (parent->context, &val);
+  g_assert (s);
+  if (text->str && g_str_equal (s, text->str))
     return;
 
   swfdec_edit_text_movie_set_text (text, s);
@@ -97,44 +92,30 @@ static void
 swfdec_edit_text_movie_init_movie (SwfdecMovie *movie)
 {
   SwfdecEditTextMovie *text = SWFDEC_EDIT_TEXT_MOVIE (movie);
-  SwfdecScriptable *parent;
-  JSObject *jsobj;
-  JSString *string;
-  jsval val;
+  SwfdecAsObject *parent;
+  SwfdecAsValue val = { 0, };
+  const char *s;
 
   if (text->text->variable == NULL)
     return;
 
-  parent = SWFDEC_SCRIPTABLE (movie->parent);
-  jsobj = swfdec_scriptable_get_object (parent);
-  if (jsobj == NULL)
-    return;
-  if (text->text->variable_prefix) {
-    val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix);
-    if (!JSVAL_IS_OBJECT (val))
-      return;
-    jsobj = JSVAL_TO_OBJECT (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 (parent->jscx, val);
-    if (!s && !text->str)
-      return;
-    if (s && text->str && g_str_equal (s, text->str))
+  parent = SWFDEC_AS_OBJECT (movie->parent);
+  swfdec_as_context_eval (parent->context, parent, text->text->variable, &val);
+  if (!SWFDEC_AS_VALUE_IS_UNDEFINED (&val)) {
+    s = swfdec_as_value_to_string (parent->context, &val);
+    g_assert (s);
+    if (text->str && g_str_equal (s, text->str))
       return;
 
     swfdec_edit_text_movie_set_text (text, s);
     return;
   }
 
-  SWFDEC_LOG ("setting variable %s (%s) to \"%s\"", text->text->variable_name,
-      text->text->variable, text->str ? text->str : "");
-  string = JS_NewStringCopyZ (parent->jscx, text->str ? text->str : "");
-  if (string == NULL)
-    return;
-  val = STRING_TO_JSVAL (string);
-  JS_SetProperty (parent->jscx, jsobj, text->text->variable_name, &val);
+  SWFDEC_LOG ("setting variable %s to \"%s\"", text->text->variable, 
+      text->str ? text->str : "");
+  s = text->str ? swfdec_as_context_get_string (parent->context, text->str) : SWFDEC_AS_STR_EMPTY;
+  SWFDEC_AS_VALUE_SET_STRING (&val, s);
+  swfdec_as_context_eval_set (parent->context, parent, text->text->variable, &val);
 }
 
 static void
diff --git a/libswfdec/swfdec_event.c b/libswfdec/swfdec_event.c
index af41b9e..ab48140 100644
--- a/libswfdec/swfdec_event.c
+++ b/libswfdec/swfdec_event.c
@@ -20,10 +20,9 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-#include <js/jsapi.h>
 #include "swfdec_event.h"
+#include "swfdec_as_object.h"
 #include "swfdec_debug.h"
-#include "swfdec_js.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_script.h"
 
@@ -41,70 +40,57 @@ 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,
-  "onConstruct"
-};
-
+/**
+ * swfdec_event_type_get_name:
+ * @type: a #SwfdecEventType
+ *
+ * Gets the name for the event as a refcounted string or %NULL if the
+ * given clip event has no associated event.
+ *
+ * Returns: The name of the event or %NULL if none.
+ **/
 const char *
 swfdec_event_type_get_name (SwfdecEventType type)
 {
   switch (type) {
     case SWFDEC_EVENT_LOAD:
-      return event_names[0];
+      return SWFDEC_AS_STR_ON_LOAD;
     case SWFDEC_EVENT_ENTER:
-      return event_names[1];
+      return SWFDEC_AS_STR_ON_ENTER_FRAME;
     case SWFDEC_EVENT_UNLOAD:
-      return event_names[2];
+      return SWFDEC_AS_STR_ON_UNLOAD;
     case SWFDEC_EVENT_MOUSE_MOVE:
-      return event_names[3];
+      return SWFDEC_AS_STR_ON_MOUSE_MOVE;
     case SWFDEC_EVENT_MOUSE_DOWN:
-      return event_names[4];
+      return SWFDEC_AS_STR_ON_MOUSE_DOWN;
     case SWFDEC_EVENT_MOUSE_UP:
-      return event_names[5];
+      return SWFDEC_AS_STR_ON_MOUSE_UP;
     case SWFDEC_EVENT_KEY_UP:
-      return event_names[6];
+      return SWFDEC_AS_STR_ON_KEY_UP;
     case SWFDEC_EVENT_KEY_DOWN:
-      return event_names[7];
+      return SWFDEC_AS_STR_ON_KEY_DOWN;
     case SWFDEC_EVENT_DATA:
-      return event_names[8];
+      return SWFDEC_AS_STR_ON_DATA;
     case SWFDEC_EVENT_INITIALIZE:
-      return event_names[9];
+      return NULL;
     case SWFDEC_EVENT_PRESS:
-      return event_names[10];
+      return SWFDEC_AS_STR_ON_PRESS;
     case SWFDEC_EVENT_RELEASE:
-      return event_names[11];
+      return SWFDEC_AS_STR_ON_RELEASE;
     case SWFDEC_EVENT_RELEASE_OUTSIDE:
-      return event_names[12];
+      return SWFDEC_AS_STR_ON_RELEASE_OUTSIDE;
     case SWFDEC_EVENT_ROLL_OVER:
-      return event_names[13];
+      return SWFDEC_AS_STR_ON_ROLL_OVER;
     case SWFDEC_EVENT_ROLL_OUT:
-      return event_names[14];
+      return SWFDEC_AS_STR_ON_ROLL_OUT;
     case SWFDEC_EVENT_DRAG_OVER:
-      return event_names[15];
+      return SWFDEC_AS_STR_ON_DRAG_OVER;
     case SWFDEC_EVENT_DRAG_OUT:
-      return event_names[16];
+      return SWFDEC_AS_STR_ON_DRAG_OUT;
     case SWFDEC_EVENT_KEY_PRESS:
-      return event_names[17];
+      return NULL;
     case SWFDEC_EVENT_CONSTRUCT:
-      return event_names[18];
+      return SWFDEC_AS_STR_ON_CONSTRUCT;
     default:
       g_assert_not_reached ();
       return NULL;
@@ -222,32 +208,33 @@ swfdec_event_list_parse (SwfdecEventList
 }
 
 void
-swfdec_event_list_execute (SwfdecEventList *list, SwfdecScriptable *scriptable, 
+swfdec_event_list_execute (SwfdecEventList *list, SwfdecAsObject *object, 
     guint condition, guint8 key)
 {
   guint i;
 
   g_return_if_fail (list != NULL);
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
 
   for (i = 0; i < list->events->len; i++) {
     SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
     if ((event->conditions & condition) &&
 	event->key == key) {
-      SWFDEC_LOG ("executing script for event %u on scriptable %p", condition, scriptable);
-      swfdec_script_execute (event->script, scriptable);
+      SWFDEC_LOG ("executing script for event %u on scriptable %p", condition, object);
+      swfdec_as_object_run (object, event->script);
     }
   }
 }
 
 gboolean
-swfdec_event_list_has_conditions (SwfdecEventList *list, SwfdecScriptable *scriptable,
+swfdec_event_list_has_conditions (SwfdecEventList *list, SwfdecAsObject *object,
     guint condition, guint8 key)
 {
   guint i;
   const char *name;
 
   g_return_val_if_fail (list != NULL, FALSE);
-  g_return_val_if_fail (SWFDEC_IS_SCRIPTABLE (scriptable), FALSE);
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), FALSE);
 
   for (i = 0; i < list->events->len; i++) {
     SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
@@ -257,7 +244,7 @@ swfdec_event_list_has_conditions (Swfdec
   }
   name = swfdec_event_type_get_name (condition);
   if (name)
-    return swfdec_scriptable_can_execute (scriptable, name);
+    return swfdec_as_object_has_function (object, name);
   return FALSE;
 }
 
diff --git a/libswfdec/swfdec_event.h b/libswfdec/swfdec_event.h
index 604e74b..6c5be7f 100644
--- a/libswfdec/swfdec_event.h
+++ b/libswfdec/swfdec_event.h
@@ -18,6 +18,7 @@
  */
 
 #include <libswfdec/swfdec_bits.h>
+#include <libswfdec/swfdec_as_types.h>
 #include <libswfdec/swfdec_player.h>
 #include <libswfdec/swfdec_types.h>
 
@@ -57,16 +58,16 @@ void			swfdec_event_list_free		(SwfdecEv
 void			swfdec_event_list_parse		(SwfdecEventList *    list,
 							 SwfdecBits *	      bits,
 							 int		      version,
-							 guint	      conditions,
+							 guint		      conditions,
 							 guint8		      key,
 							 const char *	      description);
 void			swfdec_event_list_execute	(SwfdecEventList *    list,
-							 SwfdecScriptable *	scriptable,
-							 guint	      condition,
+							 SwfdecAsObject *     object,
+							 guint		      condition,
 							 guint8		      key);
 gboolean		swfdec_event_list_has_conditions(SwfdecEventList *    list,
-							 SwfdecScriptable *	scriptable,
-							 guint	      conditions,
+							 SwfdecAsObject *     object,
+							 guint		      conditions,
 							 guint8		      key);
 							 
 
diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index 807447e..fe35ed2 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -614,6 +614,7 @@ swfdec_flv_decoder_get_data (SwfdecFlvDe
 #include "swfdec_sprite.h"
 #include "swfdec_video_movie.h"
 
+#if 0
 static void
 notify_initialized (SwfdecPlayer *player, GParamSpec *pspec, SwfdecVideoMovie *movie)
 {
@@ -623,6 +624,7 @@ notify_initialized (SwfdecPlayer *player
   swfdec_movie_queue_update (SWFDEC_MOVIE (movie), SWFDEC_MOVIE_INVALID_MATRIX);
   swfdec_movie_invalidate (SWFDEC_MOVIE (movie));
 }
+#endif
 
 gboolean
 swfdec_flv_decoder_is_eof (SwfdecFlvDecoder *flv)
@@ -643,6 +645,8 @@ swfdec_flv_decoder_eof (SwfdecFlvDecoder
 SwfdecMovie *
 swfdec_flv_decoder_add_movie (SwfdecFlvDecoder *flv, SwfdecMovie *parent)
 {
+  g_assert_not_reached ();
+#if 0
   SwfdecContent *content = swfdec_content_new (0);
   SwfdecMovie *movie;
   SwfdecVideo *video;
@@ -670,5 +674,6 @@ swfdec_flv_decoder_add_movie (SwfdecFlvD
   g_object_unref (stream);
 
   return movie;
+#endif
 }
 
diff --git a/libswfdec/swfdec_graphic.c b/libswfdec/swfdec_graphic.c
index a0df25d..bc7f46c 100644
--- a/libswfdec/swfdec_graphic.c
+++ b/libswfdec/swfdec_graphic.c
@@ -30,12 +30,13 @@
 G_DEFINE_ABSTRACT_TYPE (SwfdecGraphic, swfdec_graphic, SWFDEC_TYPE_CHARACTER)
 
 static SwfdecMovie *
-swfdec_graphic_create_movie (SwfdecGraphic *graphic)
+swfdec_graphic_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
   SwfdecGraphicMovie *movie = g_object_new (SWFDEC_TYPE_GRAPHIC_MOVIE, NULL);
 
   movie->graphic = graphic;
   g_object_ref (graphic);
+  *size = sizeof (SwfdecGraphicMovie);
   return SWFDEC_MOVIE (movie);
 }
 
diff --git a/libswfdec/swfdec_graphic.h b/libswfdec/swfdec_graphic.h
index 1fded88..daa1066 100644
--- a/libswfdec/swfdec_graphic.h
+++ b/libswfdec/swfdec_graphic.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
@@ -51,7 +51,8 @@ struct _SwfdecGraphicClass
   SwfdecCharacterClass	character_class;
 
   /* when creating a movie for this graphic, calls this function */
-  SwfdecMovie *	      	(*create_movie)	(SwfdecGraphic *		graphic);
+  SwfdecMovie *	      	(*create_movie)	(SwfdecGraphic *		graphic,
+					 gsize *      			size);
   /* optional vfuncs */
   void			(* render)	(SwfdecGraphic *	      	graphic, 
                                          cairo_t *			cr,
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 5ec2303..a3c8119 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -103,8 +103,6 @@ swfdec_js_init_player (SwfdecPlayer *pla
   swfdec_js_add_xml (player);
   swfdec_js_add_connection (player);
   swfdec_js_add_net_stream (player);
-  player->mouse_listener = swfdec_listener_new (player);
-  player->key_listener = swfdec_listener_new (player);
 }
 
 typedef struct _SwfdecJSInterval SwfdecJSInterval;
diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c
index 3f6333c..9f58d56 100644
--- a/libswfdec/swfdec_js_movie.c
+++ b/libswfdec/swfdec_js_movie.c
@@ -1427,56 +1427,6 @@ swfdec_js_movie_create_jsobject	(SwfdecM
   swfdec_js_movie_add_property (movie);
 }
 
-/**
- * swfdec_movie_run_init:
- * @movie: a #SwfdecMovie
- *
- * Runs onClipEvent(initialize) on the given @movie.
- */
-void
-swfdec_movie_run_init (SwfdecMovie *movie)
-{
-  SwfdecPlayer *player;
-
-  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
-  g_return_if_fail (SWFDEC_SCRIPTABLE (movie)->jsobj != NULL);
-
-  player = SWFDEC_ROOT_MOVIE (movie->root)->player;
-  g_queue_remove (player->init_queue, movie);
-  swfdec_movie_execute_script (movie, SWFDEC_EVENT_INITIALIZE);
-}
-
-/**
- * swfdec_movie_run_construct:
- * @movie: a #SwfdecMovie
- *
- * Runs the constructors for @movie. This is (in the given order) 
- * onClipEvent(construct), movie.onConstruct and the constructor registered
- * via Object.registerClass.
- **/
-void
-swfdec_movie_run_construct (SwfdecMovie *movie)
-{
-  SwfdecPlayer *player;
-  jsval fun;
-
-  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
-  g_return_if_fail (SWFDEC_SCRIPTABLE (movie)->jsobj != NULL);
-
-  player = SWFDEC_ROOT_MOVIE (movie->root)->player;
-  g_queue_remove (player->construct_queue, movie);
-  swfdec_movie_execute_script (movie, SWFDEC_EVENT_CONSTRUCT);
-  /* FIXME: need a check if the constructor can be unregistered after construction */
-  if (SWFDEC_IS_SPRITE_MOVIE (movie) &&
-      (fun = swfdec_js_movie_lookup_class (SWFDEC_SPRITE_MOVIE (movie))) != JSVAL_NULL) {
-    SwfdecScriptable *script = SWFDEC_SCRIPTABLE (movie);
-    SWFDEC_LOG ("Executing constructor for %s %p", G_OBJECT_TYPE_NAME (movie), movie);
-    if (!js_InternalCall (script->jscx, script->jsobj, fun, 0, NULL, &fun)) {
-      SWFDEC_ERROR ("constructor execution failed");
-    }
-  }
-}
-
 void
 swfdec_js_movie_remove_jsobject	(SwfdecMovie *movie)
 {
diff --git a/libswfdec/swfdec_listener.c b/libswfdec/swfdec_listener.c
index 85ea67d..b4495e7 100644
--- a/libswfdec/swfdec_listener.c
+++ b/libswfdec/swfdec_listener.c
@@ -21,31 +21,32 @@
 #include "config.h"
 #endif
 #include "swfdec_listener.h"
-#include "js/jsapi.h"
-#include "js/jsfun.h"
-#include "js/jsinterp.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_object.h"
 #include "swfdec_debug.h"
-#include "swfdec_player_internal.h"
 
 typedef struct {
-  JSObject *	object;			/* the object we care about or NULL if empty */
-  gboolean	blocked :1;		/* TRUE if may not be removed */
-  gboolean	removed :1;		/* TRUE if was removed but is blocked */
+  SwfdecAsObject *	object;		/* the object we care about or NULL if empty */
+  const char *		blocked_by;	/* string of event we're about to execute */
+  gboolean		removed;   	/* TRUE if was removed but is blocked */
 } SwfdecListenerEntry;
 
 struct _SwfdecListener {
-  SwfdecPlayer *	player;
+  SwfdecAsContext *	context;
   /* we can't use GArray here because it reallocated below us, which JS_AddRoot doesn't like */
   SwfdecListenerEntry * entries;	/* all allocated entries */
   guint			n_entries;	/* number of allocated entries */
 };
 
 SwfdecListener *
-swfdec_listener_new (SwfdecPlayer *player)
+swfdec_listener_new (SwfdecAsContext *context)
 {
-  SwfdecListener *listener = g_new0 (SwfdecListener, 1);
+  SwfdecListener *listener;
+  
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  listener->player = player;
+  listener = g_new0 (SwfdecListener, 1);
+  listener->context = context;
   listener->entries = NULL;
   listener->n_entries = 0;
 
@@ -55,27 +56,19 @@ swfdec_listener_new (SwfdecPlayer *playe
 void
 swfdec_listener_free (SwfdecListener *listener)
 {
-  guint i;
-  JSContext *cx;
-
   g_return_if_fail (listener != NULL);
 
-  cx = listener->player->jscx;
-  for (i = 0; i < listener->n_entries; i++) {
-    JS_RemoveRoot (cx, &listener->entries[i].object);
-  }
   g_free (listener->entries);
-  swfdec_player_remove_all_actions (listener->player, listener);
   g_free (listener);
 }
 
 gboolean
-swfdec_listener_add (SwfdecListener *listener, JSObject *obj)
+swfdec_listener_add (SwfdecListener *listener, SwfdecAsObject *obj)
 {
   guint found, i;
 
   g_return_val_if_fail (listener != NULL, FALSE);
-  g_return_val_if_fail (obj != NULL, FALSE);
+  g_return_val_if_fail (SWFDEC_AS_OBJECT (obj), FALSE);
 
   found = listener->n_entries;
   for (i = 0; i < listener->n_entries; i++) {
@@ -87,24 +80,11 @@ swfdec_listener_add (SwfdecListener *lis
   if (found >= listener->n_entries) {
     gpointer mem;
     guint new_len = listener->n_entries + 16;
-    JSContext *cx = listener->player->jscx;
 
-    for (i = 0; i < listener->n_entries; i++) {
-      JS_RemoveRoot (cx, &listener->entries[i].object);
-    }
     mem = g_try_realloc (listener->entries, sizeof (SwfdecListenerEntry) * new_len);
     if (mem == NULL)
       return FALSE;
     listener->entries = mem;
-    for (i = listener->n_entries; i < new_len; i++) {
-      listener->entries[i].object = NULL;
-      listener->entries[i].blocked = 0;
-      listener->entries[i].removed = 0;
-      if (!JS_AddRoot (cx, &listener->entries[i].object)) {
-	listener->n_entries = i;
-	return FALSE;
-      }
-    }
     listener->n_entries = new_len;
   }
   g_assert (listener->entries[found].object == NULL);
@@ -113,7 +93,7 @@ swfdec_listener_add (SwfdecListener *lis
 }
 
 void
-swfdec_listener_remove (SwfdecListener *listener, JSObject *obj)
+swfdec_listener_remove (SwfdecListener *listener, SwfdecAsObject *obj)
 {
   guint i;
 
@@ -122,7 +102,7 @@ swfdec_listener_remove (SwfdecListener *
 
   for (i = 0; i < listener->n_entries; i++) {
     if (listener->entries[i].object == obj) {
-      if (listener->entries[i].blocked) {
+      if (listener->entries[i].blocked_by) {
 	listener->entries[i].removed = TRUE;
       } else {
 	listener->entries[i].object = NULL;
@@ -132,53 +112,47 @@ swfdec_listener_remove (SwfdecListener *
   }
 }
 
-static void
-swfdec_listener_do_execute (gpointer listenerp, gpointer event_name)
+void
+swfdec_listener_execute	(SwfdecListener *listener, const char *event_name)
 {
   guint i;
-  SwfdecListener *listener = listenerp;
-  JSContext *cx = listener->player->jscx;
+
+  g_return_if_fail (listener != NULL);
+  g_return_if_fail (event_name != NULL);
 
   for (i = 0; i < listener->n_entries; i++) {
-    if (listener->entries[i].blocked) {
-      jsval fun;
-      JSObject *obj = listener->entries[i].object;
+    g_assert (listener->entries[i].blocked_by == NULL); /* ensure this happens only once */
+    if (listener->entries[i].object) {
+      listener->entries[i].blocked_by = event_name;
+    }
+  }
+  for (i = 0; i < listener->n_entries; i++) {
+    if (listener->entries[i].blocked_by) {
+      SwfdecAsObject *obj = listener->entries[i].object;
+      const char *event = listener->entries[i].blocked_by;
       if (listener->entries[i].removed) {
 	listener->entries[i].object = NULL;
 	listener->entries[i].removed = FALSE;
       }
-      listener->entries[i].blocked = FALSE;
-      if (!JS_GetProperty (cx, obj, event_name, &fun))
-	continue;
-      if (!JSVAL_IS_OBJECT (fun) || fun == JSVAL_NULL ||
-	  JS_GetClass (JSVAL_TO_OBJECT (fun)) != &js_FunctionClass) {
-	SWFDEC_INFO ("object has no handler for %s event", (char *) event_name);
-	continue;
-      }
-      js_InternalCall (cx, obj, fun, 0, NULL, &fun);
+      listener->entries[i].blocked_by = NULL;
+      swfdec_as_object_call (obj, event, 0, NULL);
     }
   }
-  g_free (event_name);
 }
 
 void
-swfdec_listener_execute	(SwfdecListener *listener, const char *event_name)
+swfdec_listener_mark (SwfdecListener *listener)
 {
-  gboolean found = FALSE;
   guint i;
 
   g_return_if_fail (listener != NULL);
-  g_return_if_fail (event_name != NULL);
 
   for (i = 0; i < listener->n_entries; i++) {
-    g_assert (!listener->entries[i].blocked); /* ensure this happens only once */
     if (listener->entries[i].object) {
-      listener->entries[i].blocked = TRUE;
-      found = TRUE;
+      swfdec_as_object_mark (listener->entries[i].object);
+      if (listener->entries[i].blocked_by)
+	swfdec_as_string_mark (listener->entries[i].blocked_by);
     }
   }
-  if (found)
-    swfdec_player_add_action (listener->player, listener, 
-	swfdec_listener_do_execute, g_strdup (event_name));
 }
 
diff --git a/libswfdec/swfdec_listener.h b/libswfdec/swfdec_listener.h
index de4694d..f0a0791 100644
--- a/libswfdec/swfdec_listener.h
+++ b/libswfdec/swfdec_listener.h
@@ -18,8 +18,8 @@
  */
 
 #include <libswfdec/swfdec.h>
+#include <libswfdec/swfdec_as_types.h>
 #include <libswfdec/swfdec_types.h>
-#include <libswfdec/js/jspubtd.h>
 
 #ifndef _SWFDEC_LISTENER_H_
 #define _SWFDEC_LISTENER_H_
@@ -27,14 +27,15 @@
 G_BEGIN_DECLS
 
 
-SwfdecListener *	swfdec_listener_new	(SwfdecPlayer *		player);
+SwfdecListener *	swfdec_listener_new	(SwfdecAsContext *	context);
 void			swfdec_listener_free	(SwfdecListener *	listener);
 gboolean		swfdec_listener_add	(SwfdecListener *	listener,
-						 JSObject *		obj);
+						 SwfdecAsObject *     	obj);
 void			swfdec_listener_remove	(SwfdecListener *	listener,
-						 JSObject *		obj);
+						 SwfdecAsObject *     	obj);
 void			swfdec_listener_execute	(SwfdecListener *	listener,
 						 const char *		event);
+void			swfdec_listener_mark	(SwfdecListener *	listener);
 
 
 G_END_DECLS
diff --git a/libswfdec/swfdec_morphshape.c b/libswfdec/swfdec_morphshape.c
index 623e790..7d28130 100644
--- a/libswfdec/swfdec_morphshape.c
+++ b/libswfdec/swfdec_morphshape.c
@@ -31,7 +31,7 @@
 G_DEFINE_TYPE (SwfdecMorphShape, swfdec_morph_shape, SWFDEC_TYPE_SHAPE)
 
 static SwfdecMovie *
-swfdec_graphic_create_movie (SwfdecGraphic *graphic)
+swfdec_graphic_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
   guint i;
   SwfdecMorphShape *morph = SWFDEC_MORPH_SHAPE (graphic);
@@ -40,10 +40,12 @@ swfdec_graphic_create_movie (SwfdecGraph
   movie->morph = morph;
   g_object_ref (morph);
 
+  *size = sizeof (SwfdecMorphMovie) + sizeof (cairo_path_t) * morph->end_vecs->len;
   movie->paths = g_new0 (cairo_path_t, morph->end_vecs->len);
   for (i = 0; i < morph->end_vecs->len; i++) {
     movie->paths[i].num_data = g_array_index (morph->end_vecs, SwfdecShapeVec, i).path.num_data;
     movie->paths[i].data = g_new (cairo_path_data_t, movie->paths[i].num_data);
+    *size += sizeof (cairo_path_data_t) * movie->paths[i].num_data;
   }
 
   return SWFDEC_MOVIE (movie);
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 3317fb2..3b6a726 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -23,14 +23,13 @@
 #include <string.h>
 #include <math.h>
 
-#include <js/jsapi.h>
-
 #include "swfdec_movie.h"
+#include "swfdec_as_context.h"
 #include "swfdec_debug.h"
 #include "swfdec_debugger.h"
 #include "swfdec_event.h"
 #include "swfdec_graphic.h"
-#include "swfdec_js.h"
+#include "swfdec_loader_internal.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_root_movie.h"
 #include "swfdec_sprite.h"
@@ -39,7 +38,7 @@
 
 static const SwfdecContent default_content = SWFDEC_CONTENT_DEFAULT;
 
-G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_SCRIPTABLE)
+G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_AS_OBJECT)
 
 static void
 swfdec_movie_init (SwfdecMovie * movie)
@@ -324,7 +323,7 @@ swfdec_movie_destroy (SwfdecMovie *movie
   swfdec_movie_set_content (movie, NULL);
   if (klass->finish_movie)
     klass->finish_movie (movie);
-  swfdec_js_movie_remove_jsobject (movie);
+  //swfdec_js_movie_remove_jsobject (movie);
   player->movies = g_list_remove (player->movies, movie);
   g_object_unref (movie);
 }
@@ -348,6 +347,55 @@ swfdec_movie_remove (SwfdecMovie *movie)
     swfdec_movie_destroy (movie);
 }
 
+/**
+ * swfdec_movie_run_init:
+ * @movie: a #SwfdecMovie
+ *
+ * Runs onClipEvent(initialize) on the given @movie.
+ */
+void
+swfdec_movie_run_init (SwfdecMovie *movie)
+{
+  SwfdecPlayer *player;
+
+  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+
+  player = SWFDEC_ROOT_MOVIE (movie->root)->player;
+  g_queue_remove (player->init_queue, movie);
+  swfdec_movie_execute_script (movie, SWFDEC_EVENT_INITIALIZE);
+}
+
+/**
+ * swfdec_movie_run_construct:
+ * @movie: a #SwfdecMovie
+ *
+ * Runs the constructors for @movie. This is (in the given order) 
+ * onClipEvent(construct), movie.onConstruct and the constructor registered
+ * via Object.registerClass.
+ **/
+void
+swfdec_movie_run_construct (SwfdecMovie *movie)
+{
+  SwfdecPlayer *player;
+
+  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+
+  player = SWFDEC_ROOT_MOVIE (movie->root)->player;
+  g_queue_remove (player->construct_queue, movie);
+  swfdec_movie_execute_script (movie, SWFDEC_EVENT_CONSTRUCT);
+#if 0
+  /* FIXME: need a check if the constructor can be unregistered after construction */
+  if (SWFDEC_IS_SPRITE_MOVIE (movie) &&
+      (fun = swfdec_js_movie_lookup_class (SWFDEC_SPRITE_MOVIE (movie))) != JSVAL_NULL) {
+    SwfdecScriptable *script = SWFDEC_SCRIPTABLE (movie);
+    SWFDEC_LOG ("Executing constructor for %s %p", G_OBJECT_TYPE_NAME (movie), movie);
+    if (!js_InternalCall (script->jscx, script->jsobj, fun, 0, NULL, &fun)) {
+      SWFDEC_ERROR ("constructor execution failed");
+    }
+  }
+#endif
+}
+
 void
 swfdec_movie_execute_script (SwfdecMovie *movie, SwfdecEventType condition)
 {
@@ -358,11 +406,11 @@ swfdec_movie_execute_script (SwfdecMovie
 
   if (movie->content->events) {
     swfdec_event_list_execute (movie->content->events, 
-	SWFDEC_SCRIPTABLE (movie), condition, 0);
+	SWFDEC_AS_OBJECT (movie), condition, 0);
   }
   name = swfdec_event_type_get_name (condition);
   if (name != NULL)
-    swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (movie), name, 0, NULL);
+    swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL);
 }
 
 static void
@@ -390,12 +438,12 @@ swfdec_movie_queue_script (SwfdecMovie *
 
   if (movie->content->events) {
     if (!swfdec_event_list_has_conditions (movie->content->events, 
-	  SWFDEC_SCRIPTABLE (movie), condition, 0))
+	  SWFDEC_AS_OBJECT (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))
+	!swfdec_as_object_has_function (SWFDEC_AS_OBJECT (movie), name))
       return FALSE;
   }
 
@@ -405,6 +453,52 @@ swfdec_movie_queue_script (SwfdecMovie *
   return TRUE;
 }
 
+/**
+ * swfdec_movie_set_variables:
+ * @script: a #SwfdecMovie
+ * @variables: variables to set on @movie in application-x-www-form-urlencoded 
+ *             format
+ * 
+ * Verifies @variables to be encoded correctly and sets them as string 
+ * properties on the given @movie.
+ **/
+void
+swfdec_movie_set_variables (SwfdecMovie *movie, const char *variables)
+{
+  SwfdecAsObject *as;
+
+  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+  g_return_if_fail (variables != NULL);
+
+  as = SWFDEC_AS_OBJECT (movie);
+  SWFDEC_DEBUG ("setting variables on %p: %s", movie, variables);
+  while (TRUE) {
+    char *name, *value;
+    const char *asname;
+    SwfdecAsValue val;
+
+    if (!swfdec_urldecode_one (variables, &name, &value, &variables)) {
+      SWFDEC_WARNING ("variables invalid at \"%s\"", variables);
+      break;
+    }
+    if (*variables != '\0' && *variables != '&') {
+      SWFDEC_WARNING ("variables not delimited with & at \"%s\"", variables);
+      g_free (name);
+      g_free (value);
+      break;
+    }
+    asname = swfdec_as_context_get_string (as->context, name);
+    g_free (name);
+    SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (as->context, value));
+    g_free (value);
+    swfdec_as_object_set (as, asname, &val);
+    SWFDEC_LOG ("Set variable \"%s\" to \"%s\"", name, value);
+    if (*variables == '\0')
+      break;
+    variables++;
+  }
+}
+
 /* NB: coordinates are in movie's coordiante system. Use swfdec_movie_get_mouse
  * if you have global coordinates */
 static gboolean
@@ -672,25 +766,13 @@ swfdec_movie_iterate_end (SwfdecMovie *m
 	 g_list_find (movie->parent->list, movie) != NULL;
 }
 
-static JSObject *
-swfdec_movie_create_js_object (SwfdecScriptable *script)
-{
-  /* we create the objects manually and ensure persistence */
-  g_assert_not_reached ();
-}
-
-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;
 }
 
@@ -740,7 +822,7 @@ swfdec_movie_set_parent (SwfdecMovie *mo
    */
   player->movies = g_list_prepend (player->movies, movie);
   /* we have to create the JSObject here to get actions queued before init_movie executes */
-  swfdec_js_movie_create_jsobject (movie);
+  //swfdec_js_movie_create_jsobject (movie);
   /* queue init and construct events for non-root movies */
   if (movie != movie->root) {
     g_queue_push_tail (player->init_queue, movie);
@@ -781,6 +863,8 @@ swfdec_movie_new (SwfdecMovie *parent, c
 {
   SwfdecGraphicClass *klass;
   SwfdecMovie *ret;
+  SwfdecAsObject *object;
+  gsize size;
 
   g_return_val_if_fail (SWFDEC_IS_MOVIE (parent), NULL);
   g_return_val_if_fail (SWFDEC_IS_GRAPHIC (content->graphic), NULL);
@@ -789,9 +873,15 @@ swfdec_movie_new (SwfdecMovie *parent, c
   SWFDEC_DEBUG ("new movie for parent %p", parent);
   klass = SWFDEC_GRAPHIC_GET_CLASS (content->graphic);
   g_return_val_if_fail (klass->create_movie != NULL, NULL);
-  ret = klass->create_movie (content->graphic);
+  ret = klass->create_movie (content->graphic, &size);
+  object = SWFDEC_AS_OBJECT (parent);
+  if (swfdec_as_context_use_mem (object->context, size)) {
+    swfdec_as_object_add (SWFDEC_AS_OBJECT (ret), object->context, size);
+    g_object_ref (ret);
+  } else {
+    SWFDEC_AS_OBJECT (ret)->context = object->context;
+  }
   ret->parent = parent;
-  SWFDEC_SCRIPTABLE (ret)->jscx = SWFDEC_SCRIPTABLE (parent)->jscx;
   g_object_ref (parent);
   ret->root = parent->root;
   swfdec_movie_initialize (ret, content);
@@ -811,7 +901,13 @@ 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;
+  if (swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), sizeof (SwfdecRootMovie))) {
+    swfdec_as_object_add (SWFDEC_AS_OBJECT (ret),
+	SWFDEC_AS_CONTEXT (player), sizeof (SwfdecRootMovie));
+    g_object_ref (ret);
+  } else {
+    SWFDEC_AS_OBJECT (ret)->context = SWFDEC_AS_CONTEXT (player);
+  }
   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 f1db624..299c793 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -21,11 +21,11 @@
 #define _SWFDEC_MOVIE_H_
 
 #include <glib-object.h>
+#include <libswfdec/swfdec_as_object.h>
 #include <libswfdec/swfdec_color.h>
 #include <libswfdec/swfdec.h>
-#include <libswfdec/swfdec_rect.h>
 #include <libswfdec/swfdec_event.h>
-#include <libswfdec/swfdec_scriptable.h>
+#include <libswfdec/swfdec_rect.h>
 #include <libswfdec/swfdec_types.h>
 
 G_BEGIN_DECLS
@@ -75,7 +75,7 @@ typedef enum {
 } SwfdecMovieState;
 
 struct _SwfdecMovie {
-  SwfdecScriptable	scriptable;
+  SwfdecAsObject	object;
 
   char *		name;			/* name used in to_string */
   gboolean		has_name;		/* TRUE if name wasn't given automagically */
@@ -115,7 +115,7 @@ struct _SwfdecMovie {
 };
 
 struct _SwfdecMovieClass {
-  SwfdecScriptableClass	scriptable_class;
+  SwfdecAsObjectClass	object_class;
 
   /* general vfuncs */
   void			(* init_movie)		(SwfdecMovie *		movie);
@@ -189,6 +189,8 @@ void		swfdec_movie_execute_script	(Swfde
 						 SwfdecEventType	condition);
 gboolean      	swfdec_movie_queue_script	(SwfdecMovie *		movie,
   						 SwfdecEventType	condition);
+void		swfdec_movie_set_variables	(SwfdecMovie *		movie,
+						 const char *		variables);
 int		swfdec_movie_compare_depths	(gconstpointer		a,
 						 gconstpointer		b);
 SwfdecDepthClass
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index b0bcd4d..04d89a3 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -28,36 +28,25 @@
 #include "swfdec_debug.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_loadertarget.h"
-#include "js/jsapi.h"
 
+/* NB: code and level must be rooted gc-strings */
 static void
 swfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const char *level)
 {
-  jsval val;
-  JSString *string;
-  JSObject *object;
-  JSContext *cx;
+  SwfdecAsValue val;
+  SwfdecAsObject *object;
 
-  SWFDEC_INFO ("emitting onStatus for %s %s", level, code);
-  cx = stream->player->jscx;
-  object = JS_NewObject (cx, NULL, NULL, NULL);
+  object = swfdec_as_object_new (SWFDEC_AS_OBJECT (stream)->context);
   if (!object)
     return;
-  string = JS_NewStringCopyZ (cx, code);
-  if (!string)
-    return;
-  val = STRING_TO_JSVAL (string);
-  if (!JS_SetProperty (cx, object, "code", &val))
-    return;
-  string = JS_NewStringCopyZ (cx, level);
-  if (!string)
-    return;
-  val = STRING_TO_JSVAL (string);
-  if (!JS_SetProperty (cx, object, "level", &val))
-    return;
+  SWFDEC_INFO ("emitting onStatus for %s %s", level, code);
+  SWFDEC_AS_VALUE_SET_STRING (&val, code);
+  swfdec_as_object_set (object, SWFDEC_AS_STR_CODE, &val);
+  SWFDEC_AS_VALUE_SET_STRING (&val, level);
+  swfdec_as_object_set (object, SWFDEC_AS_STR_LEVEL, &val);
 
-  val = OBJECT_TO_JSVAL (object);
-  swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (stream), "onStatus", 1, &val);
+  SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), SWFDEC_AS_STR_ON_STATUS, 1, &val);
 }
 
 static void swfdec_net_stream_update_playing (SwfdecNetStream *stream);
@@ -116,16 +105,17 @@ swfdec_net_stream_video_goto (SwfdecNetS
   }
   if (stream->next_time <= stream->current_time) {
     if (swfdec_flv_decoder_is_eof (stream->flvdecoder)) {
-      swfdec_net_stream_onstatus (stream, "NetStream.Play.Stop", "status");
+      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_PLAY_STOP, SWFDEC_AS_STR_STATUS);
     } else {
       stream->buffering = TRUE;
-      swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Empty", "status");
+      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_BUFFER_EMPTY, 
+	  SWFDEC_AS_STR_STATUS);
     }
     swfdec_net_stream_update_playing (stream);
   }
   if (process_events) {
     while (process_events_from <= stream->current_time) {
-      jsval name, value;
+      SwfdecAsValue name, value;
       SwfdecBits bits;
       SwfdecBuffer *event = swfdec_flv_decoder_get_data (stream->flvdecoder, process_events_from, &process_events_from);
       if (!event)
@@ -133,12 +123,12 @@ swfdec_net_stream_video_goto (SwfdecNetS
       SWFDEC_LOG ("processing event from timestamp %u", process_events_from);
       process_events_from++; /* increase so we get the next event next time */
       swfdec_bits_init (&bits, event);
-      if (swfdec_amf_parse (SWFDEC_SCRIPTABLE (stream)->jscx, &bits, 2, 
+      if (swfdec_amf_parse (SWFDEC_AS_OBJECT (stream)->context, &bits, 2, 
 	    SWFDEC_AMF_STRING, &name, SWFDEC_AMF_MIXED_ARRAY, &value) != 2) {
 	SWFDEC_ERROR ("could not parse data tag");
       } else {
-	swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (stream), 
-	    JS_GetStringBytes (JSVAL_TO_STRING (name)), 1, &value);
+	swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), 
+	    SWFDEC_AS_VALUE_GET_STRING (&name), 1, &value);
       }
     }
   }
@@ -221,7 +211,8 @@ swfdec_net_stream_loader_target_parse (S
   
   if (loader->error) {
     if (stream->flvdecoder == NULL)
-      swfdec_net_stream_onstatus (stream, "NetStream.Play.StreamNotFound", "error");
+      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_PLAY_STREAMNOTFOUND,
+	  SWFDEC_AS_STR_ERROR);
     return;
   }
   if (!loader->eof && swfdec_buffer_queue_get_depth (loader->queue) == 0) {
@@ -233,7 +224,8 @@ swfdec_net_stream_loader_target_parse (S
     stream->flvdecoder = g_object_new (SWFDEC_TYPE_FLV_DECODER, NULL);
     SWFDEC_DECODER (stream->flvdecoder)->player = stream->player;
     SWFDEC_DECODER (stream->flvdecoder)->queue = loader->queue;
-    swfdec_net_stream_onstatus (stream, "NetStream.Play.Start", "status");
+    swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_PLAY_START,
+	SWFDEC_AS_STR_STATUS);
     swfdec_loader_set_data_type (loader, SWFDEC_LOADER_DATA_FLV);
   }
   klass = SWFDEC_DECODER_GET_CLASS (stream->flvdecoder);
@@ -267,12 +259,14 @@ out:
     guint first, last;
     swfdec_flv_decoder_eof (stream->flvdecoder);
     recheck = TRUE;
-    swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Flush", "status");
+    swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_BUFFER_FLUSH,
+	SWFDEC_AS_STR_STATUS);
     swfdec_net_stream_video_goto (stream, stream->current_time);
     stream->buffering = FALSE;
     if (swfdec_flv_decoder_get_video_info (stream->flvdecoder, &first, &last) &&
 	stream->current_time + stream->buffer_time <= last) {
-      swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Full", "status");
+      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_BUFFER_FULL,
+	  SWFDEC_AS_STR_STATUS);
     }
   }
   if (recheck) {
@@ -283,7 +277,8 @@ out:
 	if (current + stream->buffer_time <= last) {
 	  swfdec_net_stream_video_goto (stream, current);
 	  stream->buffering = FALSE;
-	  swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Full", "status");
+	  swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NETSTREAM_BUFFER_FULL,
+	      SWFDEC_AS_STR_STATUS);
 	}
       } else {
 	SWFDEC_ERROR ("no video stream, how do we update buffering?");
@@ -323,7 +318,7 @@ swfdec_net_stream_input_disconnect (Swfd
 
 /*** SWFDEC_NET_STREAM ***/
 
-G_DEFINE_TYPE_WITH_CODE (SwfdecNetStream, swfdec_net_stream, SWFDEC_TYPE_SCRIPTABLE,
+G_DEFINE_TYPE_WITH_CODE (SwfdecNetStream, swfdec_net_stream, SWFDEC_TYPE_AS_OBJECT,
     G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_LOADER_TARGET, swfdec_net_stream_loader_target_init))
 
 static void
@@ -346,16 +341,25 @@ swfdec_net_stream_dispose (GObject *obje
   G_OBJECT_CLASS (swfdec_net_stream_parent_class)->dispose (object);
 }
 
-extern const JSClass net_stream_class;
+static void
+swfdec_net_stream_mark (SwfdecAsObject *object)
+{
+  SwfdecNetStream *stream = SWFDEC_NET_STREAM (object);
+
+  swfdec_as_object_mark (SWFDEC_AS_OBJECT (stream->conn));
+
+  SWFDEC_AS_OBJECT_CLASS (swfdec_net_stream_parent_class)->mark (object);
+}
+
 static void
 swfdec_net_stream_class_init (SwfdecNetStreamClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecScriptableClass *scriptable_class = SWFDEC_SCRIPTABLE_CLASS (klass);
+  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_net_stream_dispose;
 
-  scriptable_class->jsclass = &net_stream_class;
+  asobject_class->mark = swfdec_net_stream_mark;
 }
 
 static void
@@ -370,16 +374,17 @@ swfdec_net_stream_init (SwfdecNetStream 
 SwfdecNetStream *
 swfdec_net_stream_new (SwfdecPlayer *player, SwfdecConnection *conn)
 {
+  SwfdecAsContext *context;
   SwfdecNetStream *stream;
   
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
   g_return_val_if_fail (SWFDEC_IS_CONNECTION (conn), NULL);
 
+  context = SWFDEC_AS_OBJECT (conn)->context;
+  if (!swfdec_as_context_use_mem (context, sizeof (SwfdecNetStream)))
+    return NULL;
   stream = g_object_new (SWFDEC_TYPE_NET_STREAM, NULL);
-  stream->player = player;
+  swfdec_as_object_add (SWFDEC_AS_OBJECT (stream), context, sizeof (SwfdecNetStream));
   stream->conn = conn;
-  SWFDEC_SCRIPTABLE (stream)->jscx = player->jscx;
-  g_object_ref (conn);
 
   return stream;
 }
diff --git a/libswfdec/swfdec_net_stream.h b/libswfdec/swfdec_net_stream.h
index 7973b5f..8f95d97 100644
--- a/libswfdec/swfdec_net_stream.h
+++ b/libswfdec/swfdec_net_stream.h
@@ -21,10 +21,10 @@
 #define _SWFDEC_NET_STREAM_H_
 
 #include <libswfdec/swfdec.h>
+#include <libswfdec/swfdec_as_object.h>
 #include <libswfdec/swfdec_connection.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
@@ -41,7 +41,7 @@ typedef struct _SwfdecNetStreamClass Swf
 
 struct _SwfdecNetStream
 {
-  SwfdecScriptable	scriptable;
+  SwfdecAsObject	object;
 
   SwfdecPlayer *	player;		/* the player we play in */
   SwfdecConnection *	conn;		/* connection used for opening streams */
@@ -71,7 +71,7 @@ struct _SwfdecNetStream
 
 struct _SwfdecNetStreamClass
 {
-  SwfdecScriptableClass	scriptable_class;
+  SwfdecAsObjectClass	object_class;
 };
 
 GType			swfdec_net_stream_get_type	(void);
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 6e03f55..28a1547 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -32,7 +32,6 @@
 #include "swfdec_debug.h"
 #include "swfdec_enums.h"
 #include "swfdec_event.h"
-#include "swfdec_js.h"
 #include "swfdec_listener.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_marshal.h"
@@ -309,7 +308,7 @@ enum {
   PROP_BACKGROUND_COLOR
 };
 
-G_DEFINE_TYPE (SwfdecPlayer, swfdec_player, G_TYPE_OBJECT)
+G_DEFINE_TYPE (SwfdecPlayer, swfdec_player, SWFDEC_TYPE_AS_CONTEXT)
 
 void
 swfdec_player_remove_movie (SwfdecPlayer *player, SwfdecMovie *movie)
@@ -365,31 +364,20 @@ swfdec_player_set_property (GObject *obj
   }
 }
 
-static gboolean
-free_registered_class (gpointer key, gpointer value, gpointer playerp)
-{
-  SwfdecPlayer *player = playerp;
-
-  g_free (key);
-  JS_RemoveRoot (player->jscx, value);
-  g_free (value);
-  return TRUE;
-}
-
 static void
 swfdec_player_dispose (GObject *object)
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (object);
 
   swfdec_player_stop_all_sounds (player);
-  /* this must happen before we finish the JS player, we have roots in there */
-  g_hash_table_foreach_steal (player->registered_classes, free_registered_class, player);
   g_hash_table_destroy (player->registered_classes);
 
   while (player->roots)
     swfdec_movie_destroy (player->roots->data);
 
-  swfdec_js_finish_player (player);
+  swfdec_listener_free (player->mouse_listener);
+  swfdec_listener_free (player->key_listener);
+  //swfdec_js_finish_player (player);
 
   swfdec_player_remove_all_actions (player, player); /* HACK to allow non-removable actions */
   g_assert (swfdec_ring_buffer_pop (player->actions) == NULL);
@@ -542,7 +530,7 @@ swfdec_player_do_mouse_move (SwfdecPlaye
   for (walk = player->movies; walk; walk = walk->next) {
     swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_MOVE);
   }
-  swfdec_listener_execute (player->mouse_listener, "onMouseMove");
+  swfdec_listener_execute (player->mouse_listener, SWFDEC_AS_STR_ON_MOUSE_MOVE);
   swfdec_player_update_mouse_position (player);
 }
 
@@ -555,10 +543,10 @@ swfdec_player_do_mouse_button (SwfdecPla
 
   if (player->mouse_button) {
     event = SWFDEC_EVENT_MOUSE_DOWN;
-    event_name = "onMouseDown";
+    event_name = SWFDEC_AS_STR_ON_MOUSE_DOWN;
   } else {
     event = SWFDEC_EVENT_MOUSE_UP;
-    event_name = "onMouseUp";
+    event_name = SWFDEC_AS_STR_ON_MOUSE_UP;
   }
   for (walk = player->movies; walk; walk = walk->next) {
     swfdec_movie_queue_script (walk->data, event);
@@ -773,9 +761,29 @@ swfdec_accumulate_or (GSignalInvocationH
 }
 
 static void
+swfdec_player_mark_string_object (gpointer key, gpointer value, gpointer data)
+{
+  swfdec_as_string_mark (key);
+  swfdec_as_object_mark (value);
+}
+
+static void
+swfdec_player_mark (SwfdecAsContext *context)
+{
+  SwfdecPlayer *player = SWFDEC_PLAYER (context);
+
+  g_hash_table_foreach (player->registered_classes, swfdec_player_mark_string_object, NULL);
+  swfdec_listener_mark (player->mouse_listener);
+  swfdec_listener_mark (player->key_listener);
+
+  SWFDEC_AS_CONTEXT_CLASS (swfdec_player_parent_class)->mark (context);
+}
+
+static void
 swfdec_player_class_init (SwfdecPlayerClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecAsContextClass *context_class = SWFDEC_AS_CONTEXT_CLASS (klass);
 
   object_class->get_property = swfdec_player_get_property;
   object_class->set_property = swfdec_player_set_property;
@@ -891,6 +899,8 @@ swfdec_player_class_init (SwfdecPlayerCl
       G_SIGNAL_RUN_LAST, 0, NULL, NULL, swfdec_marshal_VOID__STRING_STRING,
       G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
 
+  context_class->mark = swfdec_player_mark;
+
   klass->advance = swfdec_player_do_advance;
   klass->handle_mouse = swfdec_player_do_handle_mouse;
 }
@@ -898,9 +908,11 @@ swfdec_player_class_init (SwfdecPlayerCl
 static void
 swfdec_player_init (SwfdecPlayer *player)
 {
-  swfdec_js_init_player (player);
-  player->registered_classes = g_hash_table_new_full (g_str_hash, g_str_equal, 
-      g_free, NULL);
+  //swfdec_js_init_player (player);
+  player->mouse_listener = swfdec_listener_new (SWFDEC_AS_CONTEXT (player));
+  player->key_listener = swfdec_listener_new (SWFDEC_AS_CONTEXT (player));
+  player->registered_classes = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
+      NULL, NULL);
 
   player->actions = swfdec_ring_buffer_new_for_type (SwfdecPlayerAction, 16);
   player->cache = swfdec_cache_new (50 * 1024 * 1024); /* 100 MB */
@@ -960,7 +972,7 @@ swfdec_player_add_level_from_loader (Swf
   root->player = player;
   root->loader = loader;
   if (variables)
-    swfdec_scriptable_set_variables (SWFDEC_SCRIPTABLE (movie), variables);
+    swfdec_movie_set_variables (movie, variables);
   swfdec_loader_set_target (root->loader, SWFDEC_LOADER_TARGET (root));
   return root;
 }
@@ -1042,42 +1054,41 @@ swfdec_player_initialize (SwfdecPlayer *
   g_object_notify (G_OBJECT (player), "initialized");
 }
 
-jsval
+/**
+ * swfdec_player_get_export_class:
+ * @player: a #SwfdecPlayer
+ * @name: garbage-collected string naming the export
+ *
+ * Looks up the constructor for characters that are exported using @name.
+ *
+ * Returns: a #SwfdecAsObject naming the constructor or %NULL if none
+ **/
+SwfdecAsObject *
 swfdec_player_get_export_class (SwfdecPlayer *player, const char *name)
 {
-  jsval *val = g_hash_table_lookup (player->registered_classes, name);
-
-  if (val)
-    return *val;
-  else
-    return JSVAL_NULL;
+  return g_hash_table_lookup (player->registered_classes, name);
 }
 
+/**
+ * swfdec_player_set_export_class:
+ * @player: a #SwfdecPlayer
+ * @name: garbage-collected string naming the export
+ * @object: object to use as constructor or %NULL for none
+ *
+ * Sets the constructor to be used for instances created using the object 
+ * exported with @name.
+ **/
 void
-swfdec_player_set_export_class (SwfdecPlayer *player, const char *name, jsval val)
+swfdec_player_set_export_class (SwfdecPlayer *player, const char *name, SwfdecAsObject *object)
 {
-  jsval *insert;
-
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
   g_return_if_fail (name != NULL);
-  g_return_if_fail (JSVAL_IS_OBJECT (val));
+  g_return_if_fail (object == NULL || SWFDEC_IS_AS_OBJECT (object));
 
-  insert = g_hash_table_lookup (player->registered_classes, name);
-  if (insert) {
-    JS_RemoveRoot (player->jscx, insert);
-    g_free (insert);
+  if (object)
+    g_hash_table_insert (player->registered_classes, (gpointer) name, object);
+  else
     g_hash_table_remove (player->registered_classes, name);
-  }
-
-  if (val != JSVAL_NULL) {
-    insert = g_new (jsval, 1);
-    *insert = val;
-    if (!JS_AddRoot (player->jscx, insert)) {
-      g_free (insert);
-      return;
-    }
-    g_hash_table_insert (player->registered_classes, g_strdup (name), insert);
-  }
 }
 
 /** PUBLIC API ***/
@@ -1207,7 +1218,6 @@ swfdec_init (void)
       swfdec_debug_set_level (level);
     }
   }
-  swfdec_js_init (0);
 }
 
 /**
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index f4de1a1..7dcf8dc 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -20,11 +20,10 @@
 #ifndef _SWFDEC_PLAYER_INTERNAL_H_
 #define _SWFDEC_PLAYER_INTERNAL_H_
 
-#include <glib-object.h>
 #include <libswfdec/swfdec_player.h>
+#include <libswfdec/swfdec_as_context.h>
 #include <libswfdec/swfdec_rect.h>
 #include <libswfdec/swfdec_ringbuffer.h>
-#include <libswfdec/js/jspubtd.h>
 
 G_BEGIN_DECLS
 
@@ -39,7 +38,7 @@ struct _SwfdecTimeout {
 
 struct _SwfdecPlayer
 {
-  GObject		object;
+  SwfdecAsContext	context;
 
   /* global properties */
   guint		rate;			/* divide by 256 to get iterations per second */
@@ -51,12 +50,10 @@ struct _SwfdecPlayer
   SwfdecColor		bgcolor;		/* background color */
   SwfdecLoader *	loader;			/* initial loader */
 
-  /* javascript */
-  JSContext *		jscx;			/* global Javascript context */
-  JSObject *		jsobj;			/* the global object */
-  guint		interval_id;		/* id returned from setInterval call */
+  /* ActionScript */
+  guint			interval_id;		/* id returned from setInterval call */
   GList *		intervals;		/* all currently running intervals */
-  GHashTable *		registered_classes;	/* name => jsval* to constructor */
+  GHashTable *		registered_classes;	/* name => SwfdecAsObject constructor */
   SwfdecListener *	mouse_listener;		/* emitting mouse events */
   SwfdecListener *	key_listener;		/* emitting keyboard events */
 
@@ -92,7 +89,7 @@ struct _SwfdecPlayer
 
 struct _SwfdecPlayerClass
 {
-  GObjectClass		object_class;
+  SwfdecAsContextClass	context_class;
 
   void			(* advance)		(SwfdecPlayer *		player,
 						 guint			msecs,
@@ -117,11 +114,11 @@ void		swfdec_player_lock		(SwfdecPlayer 
 void		swfdec_player_unlock		(SwfdecPlayer *		player);
 void		swfdec_player_perform_actions	(SwfdecPlayer *		player);
 
-jsval		swfdec_player_get_export_class	(SwfdecPlayer *		player,
+SwfdecAsObject *swfdec_player_get_export_class	(SwfdecPlayer *		player,
 						 const char *		name);
 void		swfdec_player_set_export_class	(SwfdecPlayer *		player,
 						 const char *		name,
-						 jsval			val);
+						 SwfdecAsObject *	object);
 
 void		swfdec_player_invalidate	(SwfdecPlayer *		player,
 						 const SwfdecRect *	rect);
diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c
index 36282d7..8b22055 100644
--- a/libswfdec/swfdec_root_movie.c
+++ b/libswfdec/swfdec_root_movie.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "swfdec_root_movie.h"
+#include "swfdec_as_object.h"
 #include "swfdec_character.h"
 #include "swfdec_debug.h"
 #include "swfdec_decoder.h"
@@ -35,7 +36,6 @@
 #include "swfdec_root_sprite.h"
 #include "swfdec_script.h"
 #include "swfdec_swf_decoder.h"
-#include "js/jsapi.h"
 
 
 static void swfdec_root_movie_loader_target_init (SwfdecLoaderTargetInterface *iface);
@@ -79,14 +79,6 @@ swfdec_root_movie_loader_target_set_deco
 static gboolean
 swfdec_root_movie_loader_target_do_init (SwfdecLoaderTarget *target)
 {
-  SwfdecRootMovie *movie = SWFDEC_ROOT_MOVIE (target);
-
-  if (movie->player->roots->next == 0) { 
-    /* if we're the only child */
-    /* FIXME: check case sensitivity wrt embedding movies of different version */
-    JS_SetContextCaseSensitive (movie->player->jscx,
-	SWFDEC_SWF_DECODER (movie->decoder)->version > 6);
-  }
   return TRUE;
 }
 
@@ -243,7 +235,7 @@ swfdec_root_movie_perform_root_actions (
     SwfdecSpriteAction *action = &g_array_index (array, SwfdecSpriteAction, i);
     switch (action->type) {
       case SWFDEC_ROOT_ACTION_INIT_SCRIPT:
-	swfdec_script_execute (action->data, SWFDEC_SCRIPTABLE (root));
+	swfdec_as_object_run (SWFDEC_AS_OBJECT (root), action->data);
 	break;
       case SWFDEC_ROOT_ACTION_EXPORT:
 	{
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 60b107a..a537953 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -25,13 +25,11 @@
 #include "swfdec_as_context.h"
 #include "swfdec_debug.h"
 #include "swfdec_debugger.h"
-#include "swfdec_scriptable.h"
 
 #include <errno.h>
 #include <math.h>
 #include <string.h>
 #include "swfdec_decoder.h"
-#include "swfdec_js.h"
 #include "swfdec_movie.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_root_movie.h"
diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index 1c6a43f..04e7ff4 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -477,11 +477,12 @@ swfdec_spriteseg_remove_object_2 (Swfdec
 }
 
 static SwfdecMovie *
-swfdec_sprite_create_movie (SwfdecGraphic *graphic)
+swfdec_sprite_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
   SwfdecSpriteMovie *ret = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, NULL);
 
   ret->sprite = SWFDEC_SPRITE (graphic);
+  *size = sizeof (SwfdecSpriteMovie);
 
   return SWFDEC_MOVIE (ret);
 }
diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index a114315..d4210f5 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -22,10 +22,10 @@
 #endif
 
 #include "swfdec_sprite_movie.h"
+#include "swfdec_as_object.h"
 #include "swfdec_audio_event.h"
 #include "swfdec_audio_stream.h"
 #include "swfdec_debug.h"
-#include "swfdec_js.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_ringbuffer.h"
 #include "swfdec_root_movie.h"
@@ -66,7 +66,7 @@ swfdec_sprite_movie_remove_child (Swfdec
 static void
 swfdec_sprite_movie_run_script (gpointer movie, gpointer data)
 {
-  swfdec_script_execute (data, SWFDEC_SCRIPTABLE (movie));
+  swfdec_as_object_run (movie, data);
 }
 
 static void
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index 97f6965..bfe89db 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -34,7 +34,6 @@
 #include "swfdec_bits.h"
 #include "swfdec_cached.h"
 #include "swfdec_debug.h"
-#include "swfdec_js.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_root_sprite.h"
 
diff --git a/libswfdec/swfdec_video.c b/libswfdec/swfdec_video.c
index a044606..86911e0 100644
--- a/libswfdec/swfdec_video.c
+++ b/libswfdec/swfdec_video.c
@@ -146,7 +146,7 @@ swfdec_video_input_new (SwfdecVideo *vid
 G_DEFINE_TYPE (SwfdecVideo, swfdec_video, SWFDEC_TYPE_GRAPHIC)
 
 static SwfdecMovie *
-swfdec_video_create_movie (SwfdecGraphic *graphic)
+swfdec_video_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
   SwfdecVideo *video = SWFDEC_VIDEO (graphic);
   SwfdecVideoMovie *movie = g_object_new (SWFDEC_TYPE_VIDEO_MOVIE, NULL);
@@ -156,6 +156,7 @@ swfdec_video_create_movie (SwfdecGraphic
   g_object_ref (graphic);
   if (input)
     swfdec_video_movie_set_input (movie, input);
+  *size = sizeof (SwfdecVideoMovie);
   return SWFDEC_MOVIE (movie);
 }
 
diff --git a/libswfdec/swfdec_video_movie.c b/libswfdec/swfdec_video_movie.c
index cf74a92..ff1769f 100644
--- a/libswfdec/swfdec_video_movie.c
+++ b/libswfdec/swfdec_video_movie.c
@@ -94,18 +94,14 @@ swfdec_video_movie_iterate_end (SwfdecMo
   return TRUE;
 }
 
-extern const JSClass video_class;
 static void
 swfdec_video_movie_class_init (SwfdecVideoMovieClass * g_class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (g_class);
-  SwfdecScriptableClass *scriptable_class = SWFDEC_SCRIPTABLE_CLASS (g_class);
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
 
   object_class->dispose = swfdec_video_movie_dispose;
 
-  scriptable_class->jsclass = &video_class;
-
   movie_class->update_extents = swfdec_video_movie_update_extents;
   movie_class->render = swfdec_video_movie_render;
   movie_class->iterate_end = swfdec_video_movie_iterate_end;
diff --git a/libswfdec/swfdec_xml.c b/libswfdec/swfdec_xml.c
index 366bf60..c931c6b 100644
--- a/libswfdec/swfdec_xml.c
+++ b/libswfdec/swfdec_xml.c
@@ -27,42 +27,27 @@
 #include "swfdec_loader_internal.h"
 #include "swfdec_loadertarget.h"
 #include "swfdec_player_internal.h"
-#include "js/jsapi.h"
-#include "js/jsinterp.h"
 
 /*** SWFDEC_LOADER_TARGET ***/
 
 static SwfdecPlayer *
 swfdec_xml_loader_target_get_player (SwfdecLoaderTarget *target)
 {
-  SwfdecXml *xml = SWFDEC_XML (target);
-
-  return xml->player;
+  return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (target)->context);
 }
 
 static void
 swfdec_xml_ondata (SwfdecXml *xml)
 {
-  JSContext *cx = SWFDEC_SCRIPTABLE (xml)->jscx;
-  JSObject *obj = SWFDEC_SCRIPTABLE (xml)->jsobj;
-  jsval val, fun;
-  JSString *string;
+  SwfdecAsValue val;
 
-  if (!JS_GetProperty (cx, obj, "onData", &fun))
-    return;
-  if (fun == JSVAL_VOID)
-    return;
   if (xml->text) {
-    string = JS_NewStringCopyZ (cx, xml->text);
-    if (string == NULL) {
-      SWFDEC_ERROR ("Could not convert text to JS string");
-      return;
-    }
-    val = STRING_TO_JSVAL (string);
+    SWFDEC_AS_VALUE_SET_STRING (&val,
+	swfdec_as_context_get_string (SWFDEC_AS_OBJECT (xml)->context, xml->text));
   } else {
-    val = JSVAL_VOID;
+    SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
   }
-  js_InternalCall (cx, obj, fun, 1, &val, &fun);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (xml), SWFDEC_AS_STR_ON_DATA, 1, &val);
 }
 
 static void
@@ -119,7 +104,7 @@ swfdec_xml_loader_target_init (SwfdecLoa
 
 /*** SWFDEC_XML ***/
 
-G_DEFINE_TYPE_WITH_CODE (SwfdecXml, swfdec_xml, SWFDEC_TYPE_SCRIPTABLE,
+G_DEFINE_TYPE_WITH_CODE (SwfdecXml, swfdec_xml, SWFDEC_TYPE_AS_OBJECT,
     G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_LOADER_TARGET, swfdec_xml_loader_target_init))
 
 static void
@@ -143,16 +128,12 @@ swfdec_xml_dispose (GObject *object)
   G_OBJECT_CLASS (swfdec_xml_parent_class)->dispose (object);
 }
 
-extern const JSClass xml_class;
 static void
 swfdec_xml_class_init (SwfdecXmlClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecScriptableClass *scriptable_class = SWFDEC_SCRIPTABLE_CLASS (klass);
 
   object_class->dispose = swfdec_xml_dispose;
-
-  scriptable_class->jsclass = &xml_class;
 }
 
 static void
@@ -160,19 +141,17 @@ swfdec_xml_init (SwfdecXml *xml)
 {
 }
 
-SwfdecXml *
-swfdec_xml_new (SwfdecPlayer *player)
+SwfdecAsObject *
+swfdec_xml_new (SwfdecAsContext *context)
 {
-  SwfdecXml *xml;
-  SwfdecScriptable *script;
-
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  SwfdecAsObject *xml;
 
-  xml= g_object_new (SWFDEC_TYPE_XML, NULL);
-  xml->player = player;
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  script = SWFDEC_SCRIPTABLE (xml);
-  script->jscx = player->jscx;
+  if (!swfdec_as_context_use_mem (context, sizeof (SwfdecXml)))
+    return NULL;
+  xml = g_object_new (SWFDEC_TYPE_XML, NULL);
+  swfdec_as_object_add (xml, context, sizeof (SwfdecXml));
 
   return xml;
 }
@@ -184,7 +163,7 @@ swfdec_xml_load (SwfdecXml *xml, const c
   g_return_if_fail (url != NULL);
 
   swfdec_xml_reset (xml);
-  xml->loader = swfdec_player_load (xml->player, url);
+  xml->loader = swfdec_player_load (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (xml)->context), url);
   swfdec_loader_set_target (xml->loader, SWFDEC_LOADER_TARGET (xml));
   swfdec_loader_queue_parse (xml->loader);
 }
diff --git a/libswfdec/swfdec_xml.h b/libswfdec/swfdec_xml.h
index b2b3ea8..77b355a 100644
--- a/libswfdec/swfdec_xml.h
+++ b/libswfdec/swfdec_xml.h
@@ -20,7 +20,8 @@
 #ifndef _SWFDEC_XML_H_
 #define _SWFDEC_XML_H_
 
-#include <libswfdec/swfdec_scriptable.h>
+#include <libswfdec/swfdec.h>
+#include <libswfdec/swfdec_as_object.h>
 
 G_BEGIN_DECLS
 
@@ -36,23 +37,22 @@ typedef struct _SwfdecXmlClass SwfdecXml
 #define SWFDEC_XML_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_XML, SwfdecXmlClass))
 
 struct _SwfdecXml {
-  SwfdecScriptable	scriptable;
+  SwfdecAsObject	object;
 
   char *		text;		/* string that this XML displays */
-  SwfdecPlayer *	player;		/* player we're playing in */
   SwfdecLoader *	loader;		/* loader when loading or NULL */
 };
 
 struct _SwfdecXmlClass {
-  SwfdecScriptableClass	scriptable_class;
+  SwfdecAsObjectClass	object_class;
 };
 
 GType		swfdec_xml_get_type	(void);
 
-SwfdecXml *	swfdec_xml_new		(SwfdecPlayer *	player);
+SwfdecAsObject *swfdec_xml_new		(SwfdecAsContext *	context);
 
-void		swfdec_xml_load		(SwfdecXml *	xml,
-					 const char *	url);
+void		swfdec_xml_load		(SwfdecXml *		xml,
+					 const char *		url);
 
 
 G_END_DECLS
diff-tree 31b77da7d447857b2a0769833c11a06fe870586a (from parents)
Merge: e9bda1999fcb67c54febb83a8bc1be75e62c60be 7495e883f55098c1b6cb22873cb6ac2bd99052e7
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 10:33:42 2007 +0200

    Merge branch 'master' into as

diff-tree 7495e883f55098c1b6cb22873cb6ac2bd99052e7 (from 35b8ff9083919b168d2090d4ccf72aa5cec99538)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 10:06:59 2007 +0200

    get rid of the constant pool in swfdec_script_interpret, since we allocate it there

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 21c1fff..d8ce1ad 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -3022,6 +3022,10 @@ no_catch:
   /* Reset sp before freeing stack slots, because our caller may GC soon. */
   fp->sp = fp->spbase;
   fp->spbase = NULL;
+  if (fp->constant_pool) {
+    swfdec_constant_pool_free (fp->constant_pool);
+    fp->constant_pool = NULL;
+  }
   js_FreeRawStack(cx, mark);
   cx->interpLevel--;
   swfdec_script_unref (script);
@@ -3123,8 +3127,6 @@ swfdec_script_execute (SwfdecScript *scr
   ok = swfdec_script_interpret (script, cx, &frame.rval);
 
   js_FreeRawStack (cx, mark);
-  if (frame.constant_pool)
-    swfdec_constant_pool_free (frame.constant_pool);
 
   cx->fp = oldfp;
   if (oldfp) {
diff-tree 35b8ff9083919b168d2090d4ccf72aa5cec99538 (from 23af06e2fcd39f80bd13b10ee02d57eb7b0e9aee)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Mar 22 19:58:07 2007 +0000

    Free the glyph array along with the font.
    
    ==24359== 580 (260 direct, 320 indirect) bytes in 3 blocks are definitely lost in loss record 70 of 101
    ==24359==    at 0x4021620: malloc (vg_replace_malloc.c:149)
    ==24359==    by 0x4E7BCB5: g_malloc (gmem.c:131)
    ==24359==    by 0x4E8B887: g_slice_alloc (gslice.c:777)
    ==24359==    by 0x4E56E38: g_array_sized_new (garray.c:94)
    ==24359==    by 0x4E56F56: g_array_new (garray.c:86)
    ==24359==    by 0x4044B2D: swfdec_font_init (swfdec_font.c:61)
    ==24359==    by 0x4E35838: g_type_create_instance (gtype.c:1569)
    ==24359==    by 0x4E1C901: g_object_constructor (gobject.c:1041)
    ==24359==    by 0x4E1AC0A: g_object_newv (gobject.c:937)
    ==24359==    by 0x4E1B74E: g_object_new_valist (gobject.c:981)
    ==24359==    by 0x4E1B8FF: g_object_new (gobject.c:795)
    ==24359==    by 0x406CE47: swfdec_swf_decoder_create_character (swfdec_swf_decoder.c:385)
    
    Slightly misleading as the leak resolution wasn't high enough to distinguish
    between g_slice_allocs.

diff --git a/libswfdec/swfdec_font.c b/libswfdec/swfdec_font.c
index 6794e0f..1b032d8 100644
--- a/libswfdec/swfdec_font.c
+++ b/libswfdec/swfdec_font.c
@@ -37,14 +37,23 @@ swfdec_font_dispose (GObject *object)
   SwfdecFont * font = SWFDEC_FONT (object);
   guint i;
 
-  for (i = 0; i < font->glyphs->len; i++) {
-    g_object_unref (g_array_index (font->glyphs, SwfdecFontEntry, i).shape);
+  if (font->glyphs) {
+    for (i = 0; i < font->glyphs->len; i++) {
+      g_object_unref (g_array_index (font->glyphs, SwfdecFontEntry, i).shape);
+    }
+    g_array_free (font->glyphs, TRUE);
+    font->glyphs = NULL;
   }
-  if (font->desc)
+  if (font->desc) {
     pango_font_description_free (font->desc);
-  g_free (font->name);
+    font->desc = NULL;
+  }
+  if (font->name) {
+    g_free (font->name);
+    font->name = NULL;
+  }
 
-  G_OBJECT_CLASS (swfdec_font_parent_class)->dispose (G_OBJECT (font));
+  G_OBJECT_CLASS (swfdec_font_parent_class)->dispose (object);
 }
 
 static void
diff-tree 23af06e2fcd39f80bd13b10ee02d57eb7b0e9aee (from 9068d5785dee8a9575cbf88e8b8813a0a69d9d89)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Apr 3 09:44:35 2007 +0200

    Unref the cached value when disposing the SwfdecCached.

diff --git a/libswfdec/swfdec_cached.c b/libswfdec/swfdec_cached.c
index aa6a694..b7216e6 100644
--- a/libswfdec/swfdec_cached.c
+++ b/libswfdec/swfdec_cached.c
@@ -32,7 +32,7 @@ swfdec_cached_dispose (GObject *object)
 {
   SwfdecCached * cached = SWFDEC_CACHED (object);
 
-  swfdec_cached_unload (cached);
+  swfdec_cached_set_cache (cached, NULL);
 
   G_OBJECT_CLASS (swfdec_cached_parent_class)->dispose (object);
 }
@@ -54,7 +54,6 @@ 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)
diff-tree 9068d5785dee8a9575cbf88e8b8813a0a69d9d89 (from 079bedb48b51463f22ccd91ddf24a8a5a1f18618)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Mar 22 19:35:11 2007 +0000

    Free the path data when disposing the morph shape.
    
    ==18759== 2,048 bytes in 2 blocks are definitely lost in loss record 83 of 101
    ==18759==    at 0x402171B: realloc (vg_replace_malloc.c:306)
    	==18759==    by 0x4E7BB7A: g_realloc (gmem.c:168)
    	==18759==    by 0x40664FA: swfdec_path_ensure_size (swfdec_shape.c:72)
    	==18759==    by 0x4066B48: swfdec_path_append (swfdec_shape.c:128)
    	==18759==    by 0x4066C29: swfdec_shape_accumulate_one_polygon (swfdec_shape.c:472)
    	==18759==    by 0x4067159: swfdec_shape_accumulate_one_fill (swfdec_shape.c:529)
    	==18759==    by 0x4067583: swfdec_shape_initialize_from_sub_paths (swfdec_shape.c:580)
    	==18759==    by 0x40680B9: tag_define_morph_shape (swfdec_shape.c:995)
    	==18759==    by 0x406D5C2: swfdec_swf_decoder_parse (swfdec_swf_decoder.c:298)
    	==18759==    by 0x40507DE: swfdec_loader_target_parse_default (swfdec_loadertarget.c:109)
    	==18759==    by 0x4050ADA: swfdec_loader_target_parse (swfdec_loadertarget.c:160)
    	==18759==    by 0x404E858: swfdec_loader_parse (swfdec_loader.c:409)

diff --git a/libswfdec/swfdec_morphshape.c b/libswfdec/swfdec_morphshape.c
index 06e8a9d..623e790 100644
--- a/libswfdec/swfdec_morphshape.c
+++ b/libswfdec/swfdec_morphshape.c
@@ -52,9 +52,15 @@ swfdec_graphic_create_movie (SwfdecGraph
 static void
 swfdec_morph_shape_dispose (GObject *object)
 {
-  SwfdecMorphShape *shape = SWFDEC_MORPH_SHAPE (object);
+  SwfdecMorphShape *morph = SWFDEC_MORPH_SHAPE (object);
+  guint i;
 
-  g_array_free (shape->end_vecs, TRUE);
+  if (morph->end_vecs != NULL) {
+    for (i = 0; i < morph->end_vecs->len; i++)
+      g_free (g_array_index (morph->end_vecs, SwfdecShapeVec, i).path.data);
+    g_array_free (morph->end_vecs, TRUE);
+    morph->end_vecs = NULL;
+  }
 
   G_OBJECT_CLASS (swfdec_morph_shape_parent_class)->dispose (object);
 }
diff-tree 079bedb48b51463f22ccd91ddf24a8a5a1f18618 (from 0598ab8797606c967fb2087d9cfffd4be175e432)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Apr 3 09:38:33 2007 +0200

    Fix minor leak of function_name.

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 0aff14c..21c1fff 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1680,7 +1680,7 @@ swfdec_action_define_function (JSContext
   gboolean v2 = (action == 0x8e);
 
   swfdec_bits_init_data (&bits, data, len);
-  function_name = swfdec_bits_get_string (&bits);
+  function_name = swfdec_bits_skip_string (&bits);
   if (function_name == NULL) {
     SWFDEC_ERROR ("could not parse function name");
     return JS_FALSE;
diff-tree 0598ab8797606c967fb2087d9cfffd4be175e432 (from 06570fb5489008d491213428b25be15716f6e448)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 09:16:30 2007 +0200

    fix a leak which caused whole videos to be leaked
    
    You notice 5MB per leak at some point...

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 681e401..b0bcd4d 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -395,6 +395,7 @@ swfdec_net_stream_set_url (SwfdecNetStre
   /* FIXME: use the connection once connections are implemented */
   loader = swfdec_player_load (stream->player, url);
   swfdec_net_stream_set_loader (stream, loader);
+  g_object_unref (loader);
 }
 
 void
diff-tree 06570fb5489008d491213428b25be15716f6e448 (from c9974a9671427543b289eb19eb556d4b890aa8c1)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 09:03:14 2007 +0200

    fix a memleak

diff --git a/libswfdec/swfdec_video.c b/libswfdec/swfdec_video.c
index f163ffd..a044606 100644
--- a/libswfdec/swfdec_video.c
+++ b/libswfdec/swfdec_video.c
@@ -119,16 +119,19 @@ swfdec_video_input_disconnect (SwfdecVid
 static SwfdecVideoMovieInput *
 swfdec_video_input_new (SwfdecVideo *video)
 {
-  SwfdecVideoInput *input = g_new0 (SwfdecVideoInput, 1);
-
+  SwfdecVideoInput *input;
+  
   if (video->n_frames == 0)
     return NULL;
   if (video->codec == NULL)
     return NULL;
+  input = g_new0 (SwfdecVideoInput, 1);
   if (video->codec)
     input->decoder = swfdec_video_codec_init (video->codec);
-  if (input->decoder == NULL)
+  if (input->decoder == NULL) {
+    g_free (input);
     return NULL;
+  }
   input->input.connect = swfdec_video_input_connect;
   input->input.iterate = swfdec_video_input_iterate;
   input->input.disconnect = swfdec_video_input_disconnect;
diff-tree c9974a9671427543b289eb19eb556d4b890aa8c1 (from 2bd12763b607d0729b0c97b7900599220d4f479c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 09:01:47 2007 +0200

    include the file name in error messages

diff --git a/libswfdec-gtk/swfdec_gtk_loader.c b/libswfdec-gtk/swfdec_gtk_loader.c
index 643fb3e..4b1e57f 100644
--- a/libswfdec-gtk/swfdec_gtk_loader.c
+++ b/libswfdec-gtk/swfdec_gtk_loader.c
@@ -105,7 +105,10 @@ swfdec_gtk_loader_read_cb (GnomeVFSAsync
     gtk->handle = NULL;
     return;
   } else if (result != GNOME_VFS_OK) {
-    swfdec_loader_error (loader, gnome_vfs_result_to_string (result));
+    char *err = g_strdup_printf ("%s: %s", loader->url,
+	gnome_vfs_result_to_string (result));
+    swfdec_loader_error (loader, err);
+    g_free (err);
     swfdec_buffer_unref (gtk->current_buffer);
     gtk->current_buffer = NULL;
     gnome_vfs_async_cancel (gtk->handle);
@@ -141,7 +144,10 @@ swfdec_gtk_loader_open_cb (GnomeVFSAsync
   SwfdecLoader *loader = loaderp;
 
   if (result != GNOME_VFS_OK) {
-    swfdec_loader_error (loader, gnome_vfs_result_to_string (result));
+    char *err = g_strdup_printf ("%s: %s", loader->url,
+	gnome_vfs_result_to_string (result));
+    swfdec_loader_error (loader, err);
+    g_free (err);
     gnome_vfs_async_cancel (gtk->handle);
     gtk->handle = NULL;
     return;
diff-tree 2bd12763b607d0729b0c97b7900599220d4f479c (from b3030fd82079172d16451d6c265077cc21a60802)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 09:01:23 2007 +0200

    Do not ref the player anymore
    
    Using a refcount was a good idea when SwfdecSource was seperate. Now it's
    used from the player itself, so it'll get into a refcount loop.
    We use weak references instead, so it's theoretically possible to use the
    source outside of a player. It'll remove itself when the player goes away.

diff --git a/libswfdec-gtk/swfdec_source.c b/libswfdec-gtk/swfdec_source.c
index f001de3..10d0f0e 100644
--- a/libswfdec-gtk/swfdec_source.c
+++ b/libswfdec-gtk/swfdec_source.c
@@ -34,7 +34,7 @@ my_time_val_difference (const GTimeVal *
 typedef struct _SwfdecIterateSource SwfdecIterateSource;
 struct _SwfdecIterateSource {
   GSource		source;
-  SwfdecPlayer *	player;
+  SwfdecPlayer *	player;		/* player we manage or NULL if player was deleted */
   double		speed;		/* inverse playback speed (so 0.5 means double speed) */
   gulong		notify;		/* set for iterate notifications */
   GTimeVal		last;		/* last time */
@@ -47,6 +47,7 @@ swfdec_iterate_get_msecs_to_next_event (
   GTimeVal now;
   glong diff;
 
+  g_assert (source->player);
   diff = swfdec_player_get_next_event (source->player);
   if (diff == 0)
     return G_MAXLONG;
@@ -62,7 +63,13 @@ swfdec_iterate_get_msecs_to_next_event (
 static gboolean
 swfdec_iterate_prepare (GSource *source, gint *timeout)
 {
-  glong diff = swfdec_iterate_get_msecs_to_next_event (source);
+  glong diff;
+  
+  diff = swfdec_iterate_get_msecs_to_next_event (source);
+  if (((SwfdecIterateSource *) source)->player == NULL) {
+    *timeout = 0;
+    return TRUE;
+  }
 
   if (diff == G_MAXLONG) {
     *timeout = -1;
@@ -79,8 +86,11 @@ swfdec_iterate_prepare (GSource *source,
 static gboolean
 swfdec_iterate_check (GSource *source)
 {
-  glong diff = swfdec_iterate_get_msecs_to_next_event (source);
-
+  glong diff;
+  
+  if (((SwfdecIterateSource *) source)->player == NULL)
+    return 0;
+  diff = swfdec_iterate_get_msecs_to_next_event (source);
   return diff < 0;
 }
 
@@ -88,8 +98,11 @@ static gboolean
 swfdec_iterate_dispatch (GSource *source_, GSourceFunc callback, gpointer user_data)
 {
   SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
-  glong diff = swfdec_iterate_get_msecs_to_next_event (source_);
-
+  glong diff;
+  
+  if (source->player == NULL)
+    return FALSE;
+  diff = swfdec_iterate_get_msecs_to_next_event (source_);
   if (diff > 0)
     return TRUE;
   diff = swfdec_player_get_next_event (source->player) - diff;
@@ -105,7 +118,9 @@ swfdec_iterate_finalize (GSource *source
   if (source->notify) {
     g_signal_handler_disconnect (source->player, source->notify);
   }
-  g_object_unref (source->player);
+  if (source->player) {
+    g_object_remove_weak_pointer (G_OBJECT (source->player), (gpointer *) &source->player);
+  }
 }
 
 GSourceFuncs swfdec_iterate_funcs = {
@@ -132,7 +147,8 @@ swfdec_iterate_source_new (SwfdecPlayer 
 
   source = (SwfdecIterateSource *) g_source_new (&swfdec_iterate_funcs, 
       sizeof (SwfdecIterateSource));
-  source->player = g_object_ref (player);
+  source->player = player;
+  g_object_add_weak_pointer (G_OBJECT (source->player), (gpointer *) &source->player);
   source->speed = 1.0 / speed;
   source->notify = g_signal_connect (player, "advance",
       G_CALLBACK (swfdec_iterate_source_advance_cb), source);
diff-tree b3030fd82079172d16451d6c265077cc21a60802 (from ea7b64b68489721b867fef1edf55c809de2e2b8a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Apr 3 09:00:34 2007 +0200

    Do not ref the player anymore
    
    Using a refcount was a good idea when SwfdecPlayback was seperate. Now it's
    used from the player itself, so it'll get into a refcount loop.

diff --git a/libswfdec-gtk/swfdec_playback_alsa.c b/libswfdec-gtk/swfdec_playback_alsa.c
index b6a2f1a..ee4da3e 100644
--- a/libswfdec-gtk/swfdec_playback_alsa.c
+++ b/libswfdec-gtk/swfdec_playback_alsa.c
@@ -318,7 +318,7 @@ swfdec_playback_open (SwfdecPlayer *play
   g_return_val_if_fail (context != NULL, NULL);
 
   sound = g_new0 (SwfdecPlayback, 1);
-  sound->player = g_object_ref (player);
+  sound->player = player;
   g_signal_connect (player, "advance", G_CALLBACK (advance_before), sound);
   g_signal_connect (player, "audio-added", G_CALLBACK (audio_added), sound);
   g_signal_connect (player, "audio-removed", G_CALLBACK (audio_removed), sound);
@@ -346,7 +346,6 @@ swfdec_playback_close (SwfdecPlayback *s
   REMOVE_HANDLER (sound->player, advance_before, sound);
   REMOVE_HANDLER (sound->player, audio_added, sound);
   REMOVE_HANDLER (sound->player, audio_removed, sound);
-  g_object_unref (sound->player);
   g_main_context_unref (sound->context);
   g_free (sound);
 }
diff-tree ea7b64b68489721b867fef1edf55c809de2e2b8a (from cba7ba2518e522d3f695d41a7f4c8dc4d1d19da8)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 2 17:38:29 2007 +0200

    this debugging message is not that important

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 99363f9..681e401 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -225,7 +225,7 @@ swfdec_net_stream_loader_target_parse (S
     return;
   }
   if (!loader->eof && swfdec_buffer_queue_get_depth (loader->queue) == 0) {
-    SWFDEC_WARNING ("nothing to parse?!");
+    SWFDEC_INFO ("nothing to do");
     return;
   }
   if (stream->flvdecoder == NULL) {
diff-tree cba7ba2518e522d3f695d41a7f4c8dc4d1d19da8 (from 7d592c21a8605361c3e63aca138f3e359cdbab50)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 2 13:28:39 2007 +0200

    update docs

diff --git a/configure.ac b/configure.ac
index 3550a5c..fdf2a31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -226,13 +226,13 @@ AM_CONDITIONAL(HAVE_GNOMEVFS, [test "x$H
 AC_SUBST(GLOBAL_CFLAGS)
 AC_SUBST(GLOBAL_CFLAGS)
 
-SWFDEC_CFLAGS="-I\$(top_srcdir) $GLIB_CFLAGS"
-SWFDEC_LIBS="\$(top_builddir)/libswfdec/libswfdec-$SWFDEC_MAJORMINOR.la $GLIB_LIBS -lz"
+SWFDEC_CFLAGS="-I\$(top_srcdir) $GLIB_CFLAGS $CAIRO_CFLAGS"
+SWFDEC_LIBS="\$(top_builddir)/libswfdec/libswfdec-$SWFDEC_MAJORMINOR.la $GLIB_LIBS $CAIRO_LIBS -lz"
 AC_SUBST(SWFDEC_LIBS)
 AC_SUBST(SWFDEC_CFLAGS)
 
-SWFDEC_GTK_CFLAGS="$SWFDEC_CFLAGS"
-SWFDEC_GTK_LIBS="\$(top_builddir)/libswfdec-gtk/libswfdec-gtk-$SWFDEC_MAJORMINOR.la $SWFDEC_LIBS"
+SWFDEC_GTK_CFLAGS="$SWFDEC_CFLAGS $GTK_CFLAGS"
+SWFDEC_GTK_LIBS="\$(top_builddir)/libswfdec-gtk/libswfdec-gtk-$SWFDEC_MAJORMINOR.la $SWFDEC_LIBS $GTK_LIBS"
 AC_SUBST(SWFDEC_GTK_LIBS)
 AC_SUBST(SWFDEC_GTK_CFLAGS)
 
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 0b037de..4855ce8 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -109,6 +109,7 @@ IGNORE_HFILES= \
 	swfdec_xml.h
 
 EXTRA_HFILES = \
+	../libswfdec-gtk/swfdec_gtk_loader.h \
 	../libswfdec-gtk/swfdec_gtk_player.h \
 	../libswfdec-gtk/swfdec_gtk_widget.h
 
@@ -131,7 +132,7 @@ expand_content_files=
 # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
 INCLUDES=$(SWFDEC_GTK_CFLAGS) $(CAIRO_CFLAGS)
-GTKDOC_LIBS=$(SWFDEC_GTK_LIBS)
+GTKDOC_LIBS=$(SWFDEC_GTK_LIBS) 
 
 # This includes the standard gtk-doc make rules, copied by gtkdocize.
 include $(top_srcdir)/gtk-doc.make
diff --git a/doc/swfdec-docs.sgml b/doc/swfdec-docs.sgml
index e5b1d71..aa1c339 100644
--- a/doc/swfdec-docs.sgml
+++ b/doc/swfdec-docs.sgml
@@ -10,6 +10,7 @@
     <title>Swfdec Gtk library</title>
     <xi:include href="xml/SwfdecGtkPlayer.xml"/>
     <xi:include href="xml/SwfdecGtkWidget.xml"/>
+    <xi:include href="xml/SwfdecGtkLoader.xml"/>
   </chapter>
   <chapter>
     <title>Swfdec library</title>
diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt
index 3d270af..e0454c7 100644
--- a/doc/swfdec-sections.txt
+++ b/doc/swfdec-sections.txt
@@ -118,7 +118,7 @@ swfdec_mouse_cursor_get_type
 <TITLE>SwfdecGtkPlayer</TITLE>
 SwfdecGtkPlayer
 swfdec_gtk_player_new
-swfdec_gtk_player_new_from_file
+swfdec_gtk_player_new_from_uri
 swfdec_gtk_player_get_playing
 swfdec_gtk_player_set_playing
 swfdec_gtk_player_get_speed
@@ -162,3 +162,19 @@ SWFDEC_IS_GTK_WIDGET
 SWFDEC_IS_GTK_WIDGET_CLASS
 SWFDEC_TYPE_GTK_WIDGET
 </SECTION>
+
+<SECTION>
+<FILE>SwfdecGtkLoader</FILE>
+<TITLE>SwfdecGtkLoader</TITLE>
+SwfdecGtkLoader
+swfdec_gtk_loader_new
+<SUBSECTION Standard>
+swfdec_gtk_loader_get_type
+SwfdecGtkLoaderClass
+SWFDEC_GTK_LOADER
+SWFDEC_GTK_LOADER_CLASS
+SWFDEC_GTK_LOADER_GET_CLASS
+SWFDEC_IS_GTK_LOADER
+SWFDEC_IS_GTK_LOADER_CLASS
+SWFDEC_TYPE_GTK_LOADER
+</SECTION>
diff --git a/doc/swfdec.types b/doc/swfdec.types
index dbd39e4..9b70671 100644
--- a/doc/swfdec.types
+++ b/doc/swfdec.types
@@ -1,8 +1,10 @@
 #include <libswfdec/swfdec.h>
+#include <libswfdec-gtk/swfdec-gtk.h>
 
 swfdec_player_get_type
 swfdec_audio_get_type
 swfdec_loader_get_type
+swfdec_gtk_loader_get_type
 swfdec_gtk_player_get_type
 swfdec_gtk_widget_get_type
 
diff --git a/libswfdec-gtk/swfdec_gtk_loader.c b/libswfdec-gtk/swfdec_gtk_loader.c
index 9267e86..643fb3e 100644
--- a/libswfdec-gtk/swfdec_gtk_loader.c
+++ b/libswfdec-gtk/swfdec_gtk_loader.c
@@ -23,6 +23,28 @@
 
 #include "swfdec_gtk_loader.h"
 
+/*** GTK-DOC ***/
+
+/**
+ * SECTION:SwfdecGtkLoader
+ * @title: SwfdecGtkLoader
+ * @short_description: advanced loader able to load network ressources
+ * @see_also: #SwfdecLoader
+ *
+ * #SwfdecGtkLoader is a #SwfdecLoader that is intended as an easy way to be 
+ * access ressources that are not stored in files, such as http. It can 
+ * however be compiled with varying support for different protocols, so don't
+ * rely on support for a particular protocol being available. If you need this,
+ * code your own SwfdecLoader subclass.
+ */
+
+/**
+ * SwfdecGtkLoader:
+ *
+ * This is the object used to represent a loader. Since it may use varying 
+ * backends, it is completely private.
+ */
+
 #ifndef HAVE_GNOMEVFS
 
 #include <libswfdec/swfdec_loader_internal.h>
diff-tree 7d592c21a8605361c3e63aca138f3e359cdbab50 (from parents)
Merge: a7488cbdfbdc0e33215e8e401c4199c143fa88d6 f516f0186bef8f00810f200034d63776bfab9271
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 2 12:41:14 2007 +0200

    Merge branch 'master' of ssh://company@git.freedesktop.org/git/swfdec

diff-tree a7488cbdfbdc0e33215e8e401c4199c143fa88d6 (from a6d61c0101f96f031463545c96383b3ebfeafe63)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 2 12:36:58 2007 +0200

    Add a loader that loads other stuff than files (in particular http)
    
    It's currently using gnome-vfs but gnome-vfs somehow doesn't like to give me
    the file size. So I'll most likely switch to something else soon.

diff --git a/configure.ac b/configure.ac
index 65be1fc..aef0a9a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -204,6 +204,25 @@ else
 fi
 AM_CONDITIONAL(HAVE_FFMPEG, [test "x$HAVE_FFMPEG" = xyes])
 
+AC_ARG_ENABLE(gnome-vfs,
+	AS_HELP_STRING([--enable-gnome-vfs],
+			[enable gnome-vfs support for swfdec-gtk (default=yes)])],
+	enable_gnomevfs=$enableval,
+	enable_gnomevfs="yes")
+
+if test "$enable_gnomevfs" = "yes"; then
+	PKG_CHECK_MODULES(GNOMEVFS, gnome-vfs-2.0 >= 2.14.0, HAVE_GNOMEVFS=yes, HAVE_GNOMEVFS=no)
+	if test "x$HAVE_GNOMEVFS" = xyes; then
+	  AC_DEFINE(HAVE_GNOMEVFS, 1, [Define if gnome-vfs is enabled])
+	else
+	  AC_MSG_ERROR([Couldn't find gnome-vfs-2.0.])
+	fi
+else
+	AC_MSG_WARN([*** gnome-vfs support was not enabled. ***])
+fi
+AM_CONDITIONAL(HAVE_GNOMEVFS, [test "x$HAVE_GNOMEVFS" = xyes])
+
+AC_SUBST(GLOBAL_CFLAGS)
 AC_SUBST(GLOBAL_CFLAGS)
 
 SWFDEC_CFLAGS="-I\$(top_srcdir) $GLIB_CFLAGS"
diff --git a/libswfdec-gtk/Makefile.am b/libswfdec-gtk/Makefile.am
index eb16f88..b2dfb72 100644
--- a/libswfdec-gtk/Makefile.am
+++ b/libswfdec-gtk/Makefile.am
@@ -13,6 +13,7 @@ lib_LTLIBRARIES = libswfdec-gtk- at SWFDEC_
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
 	swfdec_playback.c \
 	swfdec_source.c \
+	swfdec_gtk_loader.c \
 	swfdec_gtk_player.c \
 	swfdec_gtk_widget.c
 
@@ -21,15 +22,16 @@ noinst_HEADERS = \
 	swfdec_source.h
 
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
-	$(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) $(AUDIO_CFLAGS) \
+	$(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) $(AUDIO_CFLAGS) $(GNOMEVFS_CFLAGS) \
 	-DG_LOG_DOMAIN=\"Swfdec-Gtk\" -DXP_UNIX
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
 	-version-info $(SWFDEC_LIBVERSION) \
 	-export-symbols-regex '^(swfdec_.*)' \
-	$(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
+	$(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS) $(GNOMEVFS_LIBS)
 libswfdec_ at SWFDEC_MAJORMINOR@includedir = $(includedir)/swfdec- at SWFDEC_MAJORMINOR@/libswfdec-gtk
 libswfdec_ at SWFDEC_MAJORMINOR@include_HEADERS = \
 	swfdec-gtk.h \
+	swfdec_gtk_loader.h \
 	swfdec_gtk_player.h \
 	swfdec_gtk_widget.h
 
diff --git a/libswfdec-gtk/swfdec-gtk.h b/libswfdec-gtk/swfdec-gtk.h
index c9a0ac8..5615fa0 100644
--- a/libswfdec-gtk/swfdec-gtk.h
+++ b/libswfdec-gtk/swfdec-gtk.h
@@ -20,6 +20,7 @@
 #ifndef __SWFDEC_GTK_H__
 #define __SWFDEC_GTK_H__
 
+#include <libswfdec-gtk/swfdec_gtk_loader.h>
 #include <libswfdec-gtk/swfdec_gtk_player.h>
 #include <libswfdec-gtk/swfdec_gtk_widget.h>
 
diff --git a/libswfdec-gtk/swfdec_gtk_loader.c b/libswfdec-gtk/swfdec_gtk_loader.c
new file mode 100644
index 0000000..9267e86
--- /dev/null
+++ b/libswfdec-gtk/swfdec_gtk_loader.c
@@ -0,0 +1,215 @@
+/* Swfdec
+ * Copyright (C) 2006 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
+ * 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_gtk_loader.h"
+
+#ifndef HAVE_GNOMEVFS
+
+#include <libswfdec/swfdec_loader_internal.h>
+
+GType
+swfdec_gtk_loader_get_type (void)
+{
+  return SWFDEC_TYPE_FILE_LOADER;
+}
+
+SwfdecLoader *
+swfdec_gtk_loader_new (const char *uri)
+{
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  return swfdec_loader_new_from_file (uri);
+}
+
+
+#else /* HAVE_GNOMEVFS */
+
+/* size of buffer we read */
+#define BUFFER_SIZE 4096
+
+#include <libgnomevfs/gnome-vfs.h>
+
+struct _SwfdecGtkLoader
+{
+  SwfdecLoader		loader;
+
+  GnomeVFSURI *		guri;		/* GnomeVFS URI used for resolving */
+  GnomeVFSAsyncHandle *	handle;		/* handle to file or NULL when done */
+  SwfdecBuffer *	current_buffer;	/* current buffer we're reading into */
+};
+
+struct _SwfdecGtkLoaderClass {
+  SwfdecLoaderClass	loader_class;
+};
+
+/*** SwfdecGtkLoader ***/
+
+G_DEFINE_TYPE (SwfdecGtkLoader, swfdec_gtk_loader, SWFDEC_TYPE_LOADER)
+
+static void swfdec_gtk_loader_start_read (SwfdecGtkLoader *gtk);
+static void
+swfdec_gtk_loader_read_cb (GnomeVFSAsyncHandle *handle, GnomeVFSResult result,
+    gpointer buffer, GnomeVFSFileSize bytes_requested, GnomeVFSFileSize bytes_read, 
+    gpointer loaderp)
+{
+  SwfdecGtkLoader *gtk = loaderp;
+  SwfdecLoader *loader = loaderp;
+
+  if (result == GNOME_VFS_ERROR_EOF) {
+    swfdec_loader_eof (loader);
+    swfdec_buffer_unref (gtk->current_buffer);
+    gtk->current_buffer = NULL;
+    gnome_vfs_async_cancel (gtk->handle);
+    gtk->handle = NULL;
+    return;
+  } else if (result != GNOME_VFS_OK) {
+    swfdec_loader_error (loader, gnome_vfs_result_to_string (result));
+    swfdec_buffer_unref (gtk->current_buffer);
+    gtk->current_buffer = NULL;
+    gnome_vfs_async_cancel (gtk->handle);
+    gtk->handle = NULL;
+    return;
+  }
+  if (bytes_read) {
+    gtk->current_buffer->length = bytes_read;
+    swfdec_loader_push (loader, gtk->current_buffer);
+  } else {
+    swfdec_buffer_unref (gtk->current_buffer);
+  }
+  gtk->current_buffer = NULL;
+  swfdec_gtk_loader_start_read (gtk);
+}
+
+static void
+swfdec_gtk_loader_start_read (SwfdecGtkLoader *gtk)
+{
+  g_assert (gtk->current_buffer == NULL);
+  g_assert (gtk->handle != NULL);
+
+  gtk->current_buffer = swfdec_buffer_new_and_alloc (BUFFER_SIZE);
+  gnome_vfs_async_read (gtk->handle, gtk->current_buffer->data,
+      gtk->current_buffer->length, swfdec_gtk_loader_read_cb, gtk);
+}
+
+static void
+swfdec_gtk_loader_open_cb (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, 
+    gpointer loaderp)
+{
+  SwfdecGtkLoader *gtk = loaderp;
+  SwfdecLoader *loader = loaderp;
+
+  if (result != GNOME_VFS_OK) {
+    swfdec_loader_error (loader, gnome_vfs_result_to_string (result));
+    gnome_vfs_async_cancel (gtk->handle);
+    gtk->handle = NULL;
+    return;
+  }
+  swfdec_gtk_loader_start_read (gtk);
+}
+
+static SwfdecLoader *
+swfdec_gtk_loader_new_from_uri (GnomeVFSURI *uri)
+{
+  SwfdecGtkLoader *gtk;
+
+  g_assert (uri);
+  gtk = g_object_new (SWFDEC_TYPE_GTK_LOADER, NULL);
+  gtk->guri = uri;
+  gnome_vfs_async_open_uri (&gtk->handle, uri, GNOME_VFS_OPEN_READ, 
+      GNOME_VFS_PRIORITY_DEFAULT, swfdec_gtk_loader_open_cb, gtk);
+  SWFDEC_LOADER (gtk)->url = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD);
+  return SWFDEC_LOADER (gtk);
+}
+
+static void
+swfdec_gtk_loader_dispose (GObject *object)
+{
+  SwfdecGtkLoader *gtk = SWFDEC_GTK_LOADER (object);
+
+  if (gtk->current_buffer) {
+    swfdec_buffer_unref (gtk->current_buffer);
+    gtk->current_buffer = NULL;
+  }
+  if (gtk->handle) {
+    gnome_vfs_async_cancel (gtk->handle);
+    gtk->handle = NULL;
+  }
+  if (gtk->guri) {
+    gnome_vfs_uri_unref (gtk->guri);
+    gtk->guri = NULL;
+  }
+
+  G_OBJECT_CLASS (swfdec_gtk_loader_parent_class)->dispose (object);
+}
+
+static SwfdecLoader *
+swfdec_gtk_loader_load (SwfdecLoader *loader, const char *url)
+{
+  SwfdecGtkLoader *gtk = SWFDEC_GTK_LOADER (loader);
+  GnomeVFSURI *parent, *new;
+
+  /* FIXME: security! */
+  parent = gnome_vfs_uri_get_parent (gtk->guri);
+  new = gnome_vfs_uri_resolve_relative (parent, url);
+  gnome_vfs_uri_unref (parent);
+  return swfdec_gtk_loader_new_from_uri (new);
+}
+
+static void
+swfdec_gtk_loader_class_init (SwfdecGtkLoaderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecLoaderClass *loader_class = SWFDEC_LOADER_CLASS (klass);
+
+  object_class->dispose = swfdec_gtk_loader_dispose;
+
+  loader_class->load = swfdec_gtk_loader_load;
+}
+
+static void
+swfdec_gtk_loader_init (SwfdecGtkLoader *gtk_loader)
+{
+}
+
+/**
+ * swfdec_gtk_loader_new:
+ * @uri: The location of the file to open
+ *
+ * Creates a new loader for the given URI using gnome-vfs (or using the local
+ * file backend, if compiled without gnome-vfs support).
+ *
+ * Returns: a new #SwfdecLoader using gnome-vfs.
+ **/
+SwfdecLoader *
+swfdec_gtk_loader_new (const char *uri)
+{
+  GnomeVFSURI *guri;
+
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  gnome_vfs_init ();
+  guri = gnome_vfs_uri_new (uri);
+  return swfdec_gtk_loader_new_from_uri (guri);
+}
+
+#endif /* HAVE_GNOMEVFS */
diff --git a/libswfdec-gtk/swfdec_gtk_loader.h b/libswfdec-gtk/swfdec_gtk_loader.h
new file mode 100644
index 0000000..09a3558
--- /dev/null
+++ b/libswfdec-gtk/swfdec_gtk_loader.h
@@ -0,0 +1,44 @@
+/* Swfdec
+ * Copyright (C) 2006 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
+ * 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_GTK_LOADER_H_
+#define _SWFDEC_GTK_LOADER_H_
+
+#include <libswfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecGtkLoader SwfdecGtkLoader;
+typedef struct _SwfdecGtkLoaderClass SwfdecGtkLoaderClass;
+
+#define SWFDEC_TYPE_GTK_LOADER                    (swfdec_gtk_loader_get_type())
+#define SWFDEC_IS_GTK_LOADER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GTK_LOADER))
+#define SWFDEC_IS_GTK_LOADER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GTK_LOADER))
+#define SWFDEC_GTK_LOADER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GTK_LOADER, SwfdecGtkLoader))
+#define SWFDEC_GTK_LOADER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GTK_LOADER, SwfdecGtkLoaderClass))
+#define SWFDEC_GTK_LOADER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_GTK_LOADER, SwfdecGtkLoaderClass))
+
+GType		swfdec_gtk_loader_get_type   	(void);
+
+SwfdecLoader *	swfdec_gtk_loader_new	  	(const char *	uri);
+					 
+
+G_END_DECLS
+#endif
diff --git a/libswfdec-gtk/swfdec_gtk_player.c b/libswfdec-gtk/swfdec_gtk_player.c
index 58edd40..06a71c5 100644
--- a/libswfdec-gtk/swfdec_gtk_player.c
+++ b/libswfdec-gtk/swfdec_gtk_player.c
@@ -22,6 +22,7 @@
 #endif
 
 #include <libswfdec/swfdec_player_internal.h>
+#include "libswfdec-gtk/swfdec_gtk_loader.h"
 #include "libswfdec-gtk/swfdec_gtk_player.h"
 #include "libswfdec-gtk/swfdec_playback.h"
 #include "libswfdec-gtk/swfdec_source.h"
@@ -190,14 +191,14 @@ swfdec_gtk_player_new (void)
  * Returns: a new player.
  **/
 SwfdecPlayer *
-swfdec_gtk_player_new_from_file (const char *uri)
+swfdec_gtk_player_new_from_uri (const char *uri)
 {
   SwfdecLoader *loader;
   SwfdecPlayer *player;
 
   g_return_val_if_fail (uri != NULL, NULL);
 
-  loader = swfdec_loader_new_new_from_file (uri);
+  loader = swfdec_gtk_loader_new (uri);
   player = swfdec_gtk_player_new ();
   swfdec_player_set_loader (player, loader);
 
diff --git a/libswfdec-gtk/swfdec_gtk_player.h b/libswfdec-gtk/swfdec_gtk_player.h
index 50bce84..b040fe9 100644
--- a/libswfdec-gtk/swfdec_gtk_player.h
+++ b/libswfdec-gtk/swfdec_gtk_player.h
@@ -37,14 +37,16 @@ typedef struct _SwfdecGtkPlayerClass Swf
 GType 		swfdec_gtk_player_get_type    	(void);
 
 SwfdecPlayer *	swfdec_gtk_player_new	      	(void);
-SwfdecPlayer *	swfdec_gtk_player_new_from_file	(const char *		filename);
+SwfdecPlayer *	swfdec_gtk_player_new_from_uri	(const char *		uri);
 
 void		swfdec_gtk_player_set_playing 	(SwfdecGtkPlayer *	player,
 						 gboolean		playing);
 gboolean	swfdec_gtk_player_get_playing 	(SwfdecGtkPlayer *	player);
-void		swfdec_gtk_player_set_audio_enabled	(SwfdecGtkPlayer *	player,
+void		swfdec_gtk_player_set_audio_enabled	
+						(SwfdecGtkPlayer *	player,
 						 gboolean		enabled);
-gboolean	swfdec_gtk_player_get_audio_enabled 	(SwfdecGtkPlayer *	player);
+gboolean	swfdec_gtk_player_get_audio_enabled
+						(SwfdecGtkPlayer *	player);
 void		swfdec_gtk_player_set_speed	(SwfdecGtkPlayer *	player,
 						 double			speed);
 double		swfdec_gtk_player_get_speed 	(SwfdecGtkPlayer *	player);
diff-tree a6d61c0101f96f031463545c96383b3ebfeafe63 (from 493905baa1c07054276adb078f086e7ca4acc26b)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 2 12:04:05 2007 +0200

    Change the semantics of swfdec_loader_new_from_file
    
    This function will now always return a loader (no NULL with error anymore),
    but will set the loader's error property instead.

diff --git a/libswfdec-gtk/swfdec_gtk_player.c b/libswfdec-gtk/swfdec_gtk_player.c
index 766f92d..58edd40 100644
--- a/libswfdec-gtk/swfdec_gtk_player.c
+++ b/libswfdec-gtk/swfdec_gtk_player.c
@@ -177,27 +177,27 @@ swfdec_gtk_player_new (void)
 }
 
 /**
- * swfdec_gtk_player_new_from_file:
- * @filename: name of the file to play
- * @error: return location for error or %NULL
+ * swfdec_gtk_player_new_from_uri:
+ * @uri: URI to play
  *
- * Tries to create a player to play back the given file. If the file does not
- * exist or another error occurs, %NULL is returned.
+ * Create a player to play back the given URI. If compiled with gnome-vfs
+ * support, it will use gnome-vfs to resolve the given URI. Note that there
+ * is no way to figure out if the referenced URI really references a file that
+ * Swfdec can play back. If you need this, you should use #SwfdecGtkLoader
+ * directly and use its error property.
  * This function calls swfdec_init () for you if it wasn't called before.
  *
- * Returns: a new player or %NULL on error.
+ * Returns: a new player.
  **/
 SwfdecPlayer *
-swfdec_gtk_player_new_from_file (const char *filename, GError **error)
+swfdec_gtk_player_new_from_file (const char *uri)
 {
   SwfdecLoader *loader;
   SwfdecPlayer *player;
 
-  g_return_val_if_fail (filename != NULL, NULL);
+  g_return_val_if_fail (uri != NULL, NULL);
 
-  loader = swfdec_loader_new_from_file (filename, error);
-  if (loader == NULL)
-    return NULL;
+  loader = swfdec_loader_new_new_from_file (uri);
   player = swfdec_gtk_player_new ();
   swfdec_player_set_loader (player, loader);
 
diff --git a/libswfdec-gtk/swfdec_gtk_player.h b/libswfdec-gtk/swfdec_gtk_player.h
index 715259b..50bce84 100644
--- a/libswfdec-gtk/swfdec_gtk_player.h
+++ b/libswfdec-gtk/swfdec_gtk_player.h
@@ -37,8 +37,7 @@ typedef struct _SwfdecGtkPlayerClass Swf
 GType 		swfdec_gtk_player_get_type    	(void);
 
 SwfdecPlayer *	swfdec_gtk_player_new	      	(void);
-SwfdecPlayer *	swfdec_gtk_player_new_from_file	(const char *		filename,
-			      	      		 GError **		error);
+SwfdecPlayer *	swfdec_gtk_player_new_from_file	(const char *		filename);
 
 void		swfdec_gtk_player_set_playing 	(SwfdecGtkPlayer *	player,
 						 gboolean		playing);
diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 81d536c..35a74c7 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -181,28 +181,6 @@ swfdec_loader_init (SwfdecLoader *loader
 
 /*** SwfdecFileLoader ***/
 
-typedef struct _SwfdecFileLoader SwfdecFileLoader;
-typedef struct _SwfdecFileLoaderClass SwfdecFileLoaderClass;
-
-#define SWFDEC_TYPE_FILE_LOADER                    (swfdec_file_loader_get_type())
-#define SWFDEC_IS_FILE_LOADER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_FILE_LOADER))
-#define SWFDEC_IS_FILE_LOADER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_FILE_LOADER))
-#define SWFDEC_FILE_LOADER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_FILE_LOADER, SwfdecFileLoader))
-#define SWFDEC_FILE_LOADER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_FILE_LOADER, SwfdecFileLoaderClass))
-#define SWFDEC_FILE_LOADER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_FILE_LOADER, SwfdecFileLoaderClass))
-
-struct _SwfdecFileLoader
-{
-  SwfdecLoader		loader;
-
-  char *		dir;		/* base directory for load operations */
-};
-
-struct _SwfdecFileLoaderClass
-{
-  SwfdecLoaderClass   	loader_class;
-};
-
 G_DEFINE_TYPE (SwfdecFileLoader, swfdec_file_loader, SWFDEC_TYPE_LOADER)
 
 static void
@@ -316,23 +294,22 @@ swfdec_loader_queue_parse (SwfdecLoader 
 /**
  * swfdec_loader_new_from_file:
  * @filename: name of the file to load
- * @error: return loacation for an error or NULL
  *
- * Creates a new loader for local files.
+ * Creates a new loader for local files. If an error occurred, the loader will
+ * be in error.
  *
- * Returns: a new loader on success or NULL on failure
+ * Returns: a new loader
  **/
 SwfdecLoader *
-swfdec_loader_new_from_file (const char *filename, GError ** error)
+swfdec_loader_new_from_file (const char *filename)
 {
   SwfdecBuffer *buf;
   SwfdecLoader *loader;
+  GError *error = NULL;
 
   g_return_val_if_fail (filename != NULL, NULL);
 
-  buf = swfdec_buffer_new_from_file (filename, error);
-  if (buf == NULL)
-    return NULL;
+  buf = swfdec_buffer_new_from_file (filename, &error);
 
   loader = g_object_new (SWFDEC_TYPE_FILE_LOADER, NULL);
   if (g_path_is_absolute (filename)) {
@@ -343,9 +320,14 @@ swfdec_loader_new_from_file (const char 
     g_free (cur);
   }
   SWFDEC_FILE_LOADER (loader)->dir = g_path_get_dirname (loader->url);
-  swfdec_loader_set_size (loader, buf->length);
-  swfdec_loader_push (loader, buf);
-  swfdec_loader_eof (loader);
+  if (buf == NULL) {
+    swfdec_loader_error (loader, error->message);
+    g_error_free (error);
+  } else {
+    swfdec_loader_set_size (loader, buf->length);
+    swfdec_loader_push (loader, buf);
+    swfdec_loader_eof (loader);
+  }
   return loader;
 }
 
diff --git a/libswfdec/swfdec_loader.h b/libswfdec/swfdec_loader.h
index 482c810..b64c9a4 100644
--- a/libswfdec/swfdec_loader.h
+++ b/libswfdec/swfdec_loader.h
@@ -68,8 +68,7 @@ struct _SwfdecLoaderClass
 
 GType		swfdec_loader_get_type		(void);
 
-SwfdecLoader *	swfdec_loader_new_from_file	(const char * 	filename,
-						 GError **	error);
+SwfdecLoader *	swfdec_loader_new_from_file	(const char *	 	filename);
 
 void		swfdec_loader_push		(SwfdecLoader *		loader,
 						 SwfdecBuffer *		buffer);
diff --git a/libswfdec/swfdec_loader_internal.h b/libswfdec/swfdec_loader_internal.h
index d47a1ed..303088a 100644
--- a/libswfdec/swfdec_loader_internal.h
+++ b/libswfdec/swfdec_loader_internal.h
@@ -25,6 +25,28 @@
 
 G_BEGIN_DECLS
 
+typedef struct _SwfdecFileLoader SwfdecFileLoader;
+typedef struct _SwfdecFileLoaderClass SwfdecFileLoaderClass;
+
+#define SWFDEC_TYPE_FILE_LOADER                    (swfdec_file_loader_get_type())
+#define SWFDEC_IS_FILE_LOADER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_FILE_LOADER))
+#define SWFDEC_IS_FILE_LOADER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_FILE_LOADER))
+#define SWFDEC_FILE_LOADER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_FILE_LOADER, SwfdecFileLoader))
+#define SWFDEC_FILE_LOADER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_FILE_LOADER, SwfdecFileLoaderClass))
+#define SWFDEC_FILE_LOADER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_FILE_LOADER, SwfdecFileLoaderClass))
+
+struct _SwfdecFileLoader
+{
+  SwfdecLoader		loader;
+
+  char *		dir;		/* base directory for load operations */
+};
+
+struct _SwfdecFileLoaderClass
+{
+  SwfdecLoaderClass   	loader_class;
+};
+
 
 SwfdecLoader *		swfdec_loader_load		(SwfdecLoader *		loader,
 							 const char *		url);
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index b9bf7e9..f0c360d 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1155,25 +1155,23 @@ swfdec_player_set_loader_with_variables 
 /**
  * swfdec_player_new_from_file:
  * @filename: name of the file to play
- * @error: return location for error or NULL
  *
- * Tries to create a player to play back the given file. If the file does not
- * exist or another error occurs, NULL is returned.
+ * Creates a player to play back the given file. If the file does not
+ * exist or another error occurs, the player will be in an error state and not
+ * be initialized.
  * This function calls swfdec_init () for you if it wasn't called before.
  *
- * Returns: a new player or NULL on error.
+ * Returns: a new player
  **/
 SwfdecPlayer *
-swfdec_player_new_from_file (const char *filename, GError **error)
+swfdec_player_new_from_file (const char *filename)
 {
   SwfdecLoader *loader;
   SwfdecPlayer *player;
 
   g_return_val_if_fail (filename != NULL, NULL);
 
-  loader = swfdec_loader_new_from_file (filename, error);
-  if (loader == NULL)
-    return NULL;
+  loader = swfdec_loader_new_from_file (filename);
   player = swfdec_player_new ();
   swfdec_player_set_loader (player, loader);
 
diff --git a/libswfdec/swfdec_player.h b/libswfdec/swfdec_player.h
index 0c6f70c..0bbf3d9 100644
--- a/libswfdec/swfdec_player.h
+++ b/libswfdec/swfdec_player.h
@@ -48,8 +48,7 @@ void		swfdec_init			(void);
 GType		swfdec_player_get_type		(void);
 
 SwfdecPlayer *	swfdec_player_new		(void);
-SwfdecPlayer *	swfdec_player_new_from_file	(const char *	filename,
-						 GError **	error);
+SwfdecPlayer *	swfdec_player_new_from_file	(const char *	filename);
 void		swfdec_player_set_loader	(SwfdecPlayer *	player,
 						 SwfdecLoader *	loader);
 void		swfdec_player_set_loader_with_variables 
diff --git a/player/swfdebug.c b/player/swfdebug.c
index af7f7dc..8b2e9f2 100644
--- a/player/swfdebug.c
+++ b/player/swfdebug.c
@@ -408,10 +408,10 @@ main (int argc, char *argv[])
     return 1;
   }
 
-  loader = swfdec_loader_new_from_file (argv[1], &error);
-  if (loader == NULL) {
-    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], error->message);
-    g_error_free (error);
+  loader = swfdec_loader_new_from_file (argv[1]);
+  if (loader->error) {
+    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], loader->error);
+    g_object_unref (loader);
     return 1;
   }
   player = swfdec_debugger_new ();
diff --git a/player/swfplay.c b/player/swfplay.c
index 81bbd3c..78c5c48 100644
--- a/player/swfplay.c
+++ b/player/swfplay.c
@@ -109,10 +109,10 @@ main (int argc, char *argv[])
     return 1;
   }
 
-  loader = swfdec_loader_new_from_file (argv[1], &error);
-  if (loader == NULL) {
-    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], error->message);
-    g_error_free (error);
+  loader = swfdec_gtk_loader_new (argv[1]);
+  if (loader->error) {
+    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], loader->error);
+    g_object_unref (loader);
     return 1;
   }
   player = swfdec_gtk_player_new ();
@@ -123,13 +123,6 @@ main (int argc, char *argv[])
     loader = swfdec_slow_loader_new (loader, delay);
 
   swfdec_player_set_loader_with_variables (player, loader, variables);
-  /* FIXME add smarter "not my file" detection */
-  if (!swfdec_player_is_initialized (player) && delay == 0) {
-    g_printerr ("File \"%s\" is not a file Swfdec can play\n", argv[1]);
-    g_object_unref (player);
-    player = NULL;
-    return 1;
-  }
 
   if (no_sound)
     swfdec_gtk_player_set_audio_enabled (SWFDEC_GTK_PLAYER (player), FALSE);
diff --git a/test/dump.c b/test/dump.c
index e248729..9c0475e 100644
--- a/test/dump.c
+++ b/test/dump.c
@@ -382,10 +382,10 @@ main (int argc, char *argv[])
 	fn = argv[1];
   }
 
-  player = swfdec_player_new_from_file (argv[1], &error);
-  if (player == NULL) {
-    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], error->message);
-    g_error_free (error);
+  player = swfdec_player_new_from_file (argv[1]);
+  if (player->loader->error) {
+    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], player->loader->error);
+    g_object_unref (player);
     return 1;
   }
   s = (SwfdecSwfDecoder *) SWFDEC_ROOT_MOVIE (player->roots->data)->decoder;
diff --git a/test/image/image.c b/test/image/image.c
index 29b96a3..4113304 100644
--- a/test/image/image.c
+++ b/test/image/image.c
@@ -155,16 +155,16 @@ run_test (const char *filename)
   SwfdecLoader *loader;
   SwfdecPlayer *player = NULL;
   guint i, msecs;
-  GError *error = NULL;
   int w, h;
   cairo_surface_t *surface;
   cairo_t *cr;
 
   g_print ("Testing %s:\n", filename);
 
-  loader = swfdec_loader_new_from_file (filename, &error);
-  if (loader == NULL) {
-    g_print ("  ERROR: %s\n", error->message);
+  loader = swfdec_loader_new_from_file (filename);
+  if (loader->error) {
+    g_print ("  ERROR: %s\n", loader->error);
+    g_object_unref (loader);
     goto error;
   }
   player = swfdec_player_new ();
@@ -193,8 +193,6 @@ run_test (const char *filename)
   return TRUE;
 
 error:
-  if (error)
-    g_error_free (error);
   if (player)
     g_object_unref (player);
   return FALSE;
diff --git a/test/parse.c b/test/parse.c
index d56c22c..6fa7234 100644
--- a/test/parse.c
+++ b/test/parse.c
@@ -30,7 +30,6 @@ main (int argc, char *argv[])
 {
   char *fn = "it.swf";
   SwfdecPlayer *player;
-  GError *error = NULL;
 
   swfdec_init ();
 
@@ -38,13 +37,8 @@ main (int argc, char *argv[])
 	fn = argv[1];
   }
 
-  player = swfdec_player_new_from_file (argv[1], &error);
-  if (player == NULL) {
-    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], error->message);
-    g_error_free (error);
-    return 1;
-  }
-  if (swfdec_player_get_rate (player) == 0) {
+  player = swfdec_player_new_from_file (argv[1]);
+  if (!swfdec_player_is_initialized (player)) {
     g_printerr ("Error parsing file \"%s\"\n", argv[1]);
     g_object_unref (player);
     player = NULL;
diff --git a/test/sound/sound.c b/test/sound/sound.c
index f42149f..4cf348a 100644
--- a/test/sound/sound.c
+++ b/test/sound/sound.c
@@ -184,6 +184,7 @@ run_test (const char *filename)
   dir = g_dir_open (dirname, 0, &error);
   if (!dir) {
     g_print ("  ERROR: %s\n", error->message);
+    g_error_free (error);
     return FALSE;
   }
   while ((name = g_dir_read_name (dir))) {
@@ -195,9 +196,10 @@ run_test (const char *filename)
   }
   g_dir_close (dir);
 
-  loader = swfdec_loader_new_from_file (filename, &error);
-  if (loader == NULL) {
-    g_print ("  ERROR: %s\n", error->message);
+  loader = swfdec_loader_new_from_file (filename);
+  if (loader->error) {
+    g_print ("  ERROR: %s\n", loader->error);
+    g_object_unref (loader);
     goto error;
   }
   player = swfdec_player_new ();
@@ -233,8 +235,6 @@ run_test (const char *filename)
   }
 
 error:
-  if (error)
-    g_error_free (error);
   if (player)
     g_object_unref (player);
   g_list_foreach (data.files, (GFunc) g_free, NULL);
diff --git a/test/swfdec-extract.c b/test/swfdec-extract.c
index da0964b..5ac1f8b 100644
--- a/test/swfdec-extract.c
+++ b/test/swfdec-extract.c
@@ -229,7 +229,6 @@ main (int argc, char *argv[])
   SwfdecCharacter *character;
   int ret = 0;
   SwfdecPlayer *player;
-  GError *error = NULL;
   glong id;
 
   swfdec_init ();
@@ -239,13 +238,8 @@ main (int argc, char *argv[])
     return 0;
   }
 
-  player = swfdec_player_new_from_file (argv[1], &error);
-  if (player == NULL) {
-    g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], error->message);
-    g_error_free (error);
-    return 1;
-  }
-  if (swfdec_player_get_rate (player) == 0) {
+  player = swfdec_player_new_from_file (argv[1]);
+  if (!SWFDEC_IS_ROOT_MOVIE (player->roots->data)) {
     g_printerr ("Error parsing file \"%s\"\n", argv[1]);
     g_object_unref (player);
     player = NULL;
diff --git a/test/trace/trace.c b/test/trace/trace.c
index 9a5a841..2c7ced7 100644
--- a/test/trace/trace.c
+++ b/test/trace/trace.c
@@ -18,14 +18,14 @@ run_test (const char *filename)
   SwfdecPlayer *player;
   SwfdecBuffer *buffer;
   guint time_left;
-  GError *error = NULL;
   char *str;
   GString *string;
+  GError *error = NULL;
 
   g_print ("Testing %s:\n", filename);
-  loader = swfdec_loader_new_from_file (filename, &error);
-  if (loader == NULL) {
-    g_print ("  ERROR: %s\n", error->message);
+  loader = swfdec_loader_new_from_file (filename);
+  if (loader->error) {
+    g_print ("  ERROR: %s\n", loader->error);
     return FALSE;
   }
   string = g_string_new ("");
@@ -69,6 +69,7 @@ run_test (const char *filename)
       if (!g_spawn_sync (NULL, command, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
 	  NULL, NULL, NULL, &error)) {
 	g_printerr ("  Couldn't spawn diff to compare the results: %s\n", error->message);
+	g_error_free (error);
       }
     }
     g_string_free (string, TRUE);


More information about the Swfdec mailing list