[Swfdec] 11 commits - libswfdec/Makefile.am libswfdec/swfdec_connection.c libswfdec/swfdec_connection.h libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_js.c libswfdec/swfdec_js_connection.c libswfdec/swfdec_js.h libswfdec/swfdec_js_net_stream.c libswfdec/swfdec_js_xml.c libswfdec/swfdec_loader.c libswfdec/swfdec_loader.h libswfdec/swfdec_loader_internal.h libswfdec/swfdec_loadertarget.c libswfdec/swfdec_loadertarget.h libswfdec/swfdec_net_stream.c libswfdec/swfdec_net_stream.h libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_root_movie.c libswfdec/swfdec_scriptable.c libswfdec/swfdec_script.c libswfdec/swfdec_xml.c libswfdec/swfdec_xml.h test/trace

Benjamin Otte company at kemper.freedesktop.org
Thu Mar 1 02:36:29 PST 2007


 libswfdec/Makefile.am              |   11 +-
 libswfdec/swfdec_connection.c      |  119 +++++++++++++++++++++++
 libswfdec/swfdec_connection.h      |   57 +++++++++++
 libswfdec/swfdec_flv_decoder.c     |    4 
 libswfdec/swfdec_js.c              |    3 
 libswfdec/swfdec_js.h              |    3 
 libswfdec/swfdec_js_connection.c   |  109 +++++++++++++++++++++
 libswfdec/swfdec_js_net_stream.c   |   94 ++++++++++++++++++
 libswfdec/swfdec_js_xml.c          |  101 +++++++++++++++++++
 libswfdec/swfdec_loader.c          |  156 +++++++++++++++++-------------
 libswfdec/swfdec_loader.h          |    9 -
 libswfdec/swfdec_loader_internal.h |    5 
 libswfdec/swfdec_loadertarget.c    |   87 +++++++++++++++--
 libswfdec/swfdec_loadertarget.h    |    6 -
 libswfdec/swfdec_net_stream.c      |   25 ++++
 libswfdec/swfdec_net_stream.h      |    9 +
 libswfdec/swfdec_player.c          |   16 +++
 libswfdec/swfdec_player_internal.h |    3 
 libswfdec/swfdec_root_movie.c      |    2 
 libswfdec/swfdec_script.c          |    7 +
 libswfdec/swfdec_scriptable.c      |    9 +
 libswfdec/swfdec_xml.c             |  187 +++++++++++++++++++++++++++++++++++++
 libswfdec/swfdec_xml.h             |   59 +++++++++++
 test/trace/Makefile.am             |    2 
 test/trace/netconnection.swf       |binary
 test/trace/netconnection.swf.trace |    6 +
 26 files changed, 993 insertions(+), 96 deletions(-)

New commits:
diff-tree 66e63dc1d746e5b3d5bffd3b780a028aa6b995be (from 9ea16e8cfcae227f0742865e8f47be32392036c5)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Mar 1 11:36:17 2007 +0100

    add NetStream stub

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 0c8564c..68cdbbf 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -52,6 +52,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_js_global.c \
 	swfdec_js_mouse.c \
 	swfdec_js_movie.c \
+	swfdec_js_net_stream.c \
 	swfdec_js_sound.c \
 	swfdec_js_xml.c \
 	swfdec_listener.c \
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 7fe7ae2..e26e33d 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -114,6 +114,7 @@ swfdec_js_init_player (SwfdecPlayer *pla
   swfdec_js_add_sound (player);
   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);
 }
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index fc16871..6c5b804 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -42,6 +42,7 @@ void		swfdec_js_add_connection	(SwfdecPl
 void		swfdec_js_add_globals		(SwfdecPlayer *		player);
 void		swfdec_js_add_mouse		(SwfdecPlayer *		player);
 void		swfdec_js_add_movieclip_class	(SwfdecPlayer *		player);
+void		swfdec_js_add_net_stream	(SwfdecPlayer *		player);
 void		swfdec_js_add_sound		(SwfdecPlayer *		player);
 void		swfdec_js_add_xml		(SwfdecPlayer *		player);
 
diff --git a/libswfdec/swfdec_js_net_stream.c b/libswfdec/swfdec_js_net_stream.c
new file mode 100644
index 0000000..7b53cfb
--- /dev/null
+++ b/libswfdec/swfdec_js_net_stream.c
@@ -0,0 +1,94 @@
+/* Swfdec
+ * 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_net_stream.h"
+#include "swfdec_debug.h"
+#include "swfdec_js.h"
+#include "swfdec_player_internal.h"
+
+static JSBool
+swfdec_js_net_stream_to_string (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  JSString *string;
+
+  string = JS_InternString (cx, "[object Object]");
+  if (string == NULL)
+    return JS_FALSE;
+
+  *rval = STRING_TO_JSVAL (string);
+  return JS_TRUE;
+}
+
+static JSFunctionSpec net_stream_methods[] = {
+  { "toString",		swfdec_js_net_stream_to_string,	0, 0, 0 },
+  {0,0,0,0,0}
+};
+
+static void
+swfdec_js_net_stream_finalize (JSContext *cx, JSObject *obj)
+{
+  SwfdecNetStream *stream;
+
+  stream = JS_GetPrivate (cx, obj);
+  if (stream) {
+    SWFDEC_SCRIPTABLE (stream)->jsobj = NULL;
+    g_object_unref (stream);
+  }
+}
+
+static JSClass net_stream_class = {
+    "NetStream", JSCLASS_HAS_PRIVATE,
+    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
+    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   swfdec_js_net_stream_finalize,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+swfdec_js_net_stream_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecNetStream *stream;
+  SwfdecConnection *conn;
+  
+  conn = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_CONNECTION);
+  if (conn == NULL) {
+    SWFDEC_WARNING ("no connection passed to NetStream ()");
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
+  stream = swfdec_net_stream_new (JS_GetContextPrivate (cx), conn);
+
+  JS_SetPrivate (cx, obj, stream);
+  SWFDEC_SCRIPTABLE (stream)->jsobj = obj;
+
+  *rval = OBJECT_TO_JSVAL (obj);
+  return JS_TRUE;
+}
+
+void
+swfdec_js_add_net_stream (SwfdecPlayer *player)
+{
+  JS_InitClass (player->jscx, player->jsobj, NULL,
+      &net_stream_class, swfdec_js_net_stream_new, 0, NULL, net_stream_methods,
+      NULL, NULL);
+}
+
diff-tree 9ea16e8cfcae227f0742865e8f47be32392036c5 (from b388b559727066550385b938933b85e443fde2c9)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Mar 1 11:35:50 2007 +0100

    Some changes to make API of NetStream more like AS NetStream
    
    - NetStream takes a connection on creation now.
    - connections are now created without a JSObject.

diff --git a/libswfdec/swfdec_connection.c b/libswfdec/swfdec_connection.c
index 2360804..8e423df 100644
--- a/libswfdec/swfdec_connection.c
+++ b/libswfdec/swfdec_connection.c
@@ -89,18 +89,16 @@ swfdec_connection_onstatus (SwfdecConnec
 }
 
 SwfdecConnection *
-swfdec_connection_new (JSContext *cx, JSObject *obj)
+swfdec_connection_new (JSContext *cx)
 {
   SwfdecConnection *conn;
   SwfdecScriptable *script;
 
   g_return_val_if_fail (cx != NULL, NULL);
-  g_return_val_if_fail (obj != NULL, NULL);
 
   conn = g_object_new (SWFDEC_TYPE_CONNECTION, NULL);
   script = SWFDEC_SCRIPTABLE (conn);
   script->jscx = cx;
-  script->jsobj = obj;
 
   return conn;
 }
diff --git a/libswfdec/swfdec_connection.h b/libswfdec/swfdec_connection.h
index 737a139..7219a89 100644
--- a/libswfdec/swfdec_connection.h
+++ b/libswfdec/swfdec_connection.h
@@ -47,8 +47,7 @@ struct _SwfdecConnectionClass {
 
 GType			swfdec_connection_get_type	(void);
 
-SwfdecConnection *	swfdec_connection_new		(JSContext *		cx,
-							 JSObject *		obj);
+SwfdecConnection *	swfdec_connection_new		(JSContext *		cx);
 
 void			swfdec_connection_connect	(SwfdecConnection *	conn,
 							 const char *		url);
diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index 00666bc..b5640f7 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -458,6 +458,7 @@ swfdec_flv_decoder_add_movie (SwfdecFlvD
   SwfdecContent *content = swfdec_content_new (0);
   SwfdecMovie *movie;
   SwfdecVideo *video;
+  SwfdecConnection *conn;
   SwfdecNetStream *stream;
 
   /* set up the video movie */
@@ -469,7 +470,8 @@ swfdec_flv_decoder_add_movie (SwfdecFlvD
   g_object_weak_ref (G_OBJECT (movie), (GWeakNotify) swfdec_content_free, content);
   g_object_weak_ref (G_OBJECT (movie), (GWeakNotify) g_object_unref, video);
   /* set up the playback stream */
-  stream = swfdec_net_stream_new (SWFDEC_ROOT_MOVIE (parent)->player);
+  conn = swfdec_connection_new (SWFDEC_ROOT_MOVIE (parent)->player->jscx);
+  stream = swfdec_net_stream_new (SWFDEC_ROOT_MOVIE (parent)->player, conn);
   swfdec_net_stream_set_loader (stream, SWFDEC_ROOT_MOVIE (parent)->loader);
   g_object_ref (SWFDEC_ROOT_MOVIE (parent)->decoder);
   if (!swfdec_loader_target_set_decoder (SWFDEC_LOADER_TARGET (stream), SWFDEC_ROOT_MOVIE (parent)->decoder)) {
diff --git a/libswfdec/swfdec_js_connection.c b/libswfdec/swfdec_js_connection.c
index 7e820f8..1ff1032 100644
--- a/libswfdec/swfdec_js_connection.c
+++ b/libswfdec/swfdec_js_connection.c
@@ -91,9 +91,10 @@ static JSClass connection_class = {
 static JSBool
 swfdec_js_connection_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
-  SwfdecConnection *conn = swfdec_connection_new (cx, obj);
+  SwfdecConnection *conn = swfdec_connection_new (cx);
 
   JS_SetPrivate (cx, obj, conn);
+  SWFDEC_SCRIPTABLE (conn)->jsobj = obj;
   *rval = OBJECT_TO_JSVAL (obj);
   return JS_TRUE;
 }
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index eee3f72..3fb4937 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -216,6 +216,8 @@ swfdec_net_stream_dispose (GObject *obje
   if (stream->decoder)
     swfdec_video_codec_finish (stream->codec, stream->decoder);
   swfdec_net_stream_set_loader (stream, NULL);
+  g_object_unref (stream->conn);
+  stream->conn = NULL;
 
   G_OBJECT_CLASS (swfdec_net_stream_parent_class)->dispose (object);
 }
@@ -236,16 +238,35 @@ swfdec_net_stream_init (SwfdecNetStream 
 }
 
 SwfdecNetStream *
-swfdec_net_stream_new (SwfdecPlayer *player)
+swfdec_net_stream_new (SwfdecPlayer *player, SwfdecConnection *conn)
 {
-  SwfdecNetStream *stream = g_object_new (SWFDEC_TYPE_NET_STREAM, NULL);
+  SwfdecNetStream *stream;
+  
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  g_return_val_if_fail (SWFDEC_IS_CONNECTION (conn), NULL);
 
+  stream = g_object_new (SWFDEC_TYPE_NET_STREAM, NULL);
   stream->player = player;
+  stream->conn = conn;
+  g_object_ref (conn);
 
   return stream;
 }
 
 void
+swfdec_net_stream_set_url (SwfdecNetStream *stream, const char *url)
+{
+  SwfdecLoader *loader;
+
+  g_return_if_fail (SWFDEC_IS_NET_STREAM (stream));
+  g_return_if_fail (url != NULL);
+
+  /* FIXME: use the connection once connections are implemented */
+  loader = swfdec_player_load (stream->player, url);
+  swfdec_net_stream_set_loader (stream, loader);
+}
+
+void
 swfdec_net_stream_set_loader (SwfdecNetStream *stream, SwfdecLoader *loader)
 {
   g_return_if_fail (SWFDEC_IS_NET_STREAM (stream));
diff --git a/libswfdec/swfdec_net_stream.h b/libswfdec/swfdec_net_stream.h
index cf5fd5a..012a11d 100644
--- a/libswfdec/swfdec_net_stream.h
+++ b/libswfdec/swfdec_net_stream.h
@@ -21,6 +21,7 @@
 #define _SWFDEC_NET_STREAM_H_
 
 #include <libswfdec/swfdec.h>
+#include <libswfdec/swfdec_connection.h>
 #include <libswfdec/swfdec_flv_decoder.h>
 #include <libswfdec/swfdec_player_internal.h>
 #include <libswfdec/swfdec_scriptable.h>
@@ -43,7 +44,8 @@ struct _SwfdecNetStream
   SwfdecScriptable	scriptable;
 
   SwfdecPlayer *	player;		/* the player we play in */
-  SwfdecLoader *	loader;		/* input connection */
+  SwfdecConnection *	conn;		/* connection used for opening streams */
+  SwfdecLoader *	loader;		/* input stream */
   SwfdecFlvDecoder *	flvdecoder;	/* flv decoder */
   gboolean		playing;	/* TRUE if this stream is playing */
   gboolean		error;		/* in error */
@@ -69,8 +71,11 @@ struct _SwfdecNetStreamClass
 
 GType			swfdec_net_stream_get_type	(void);
 
-SwfdecNetStream *	swfdec_net_stream_new		(SwfdecPlayer *		player);
+SwfdecNetStream *	swfdec_net_stream_new		(SwfdecPlayer *		player,
+							 SwfdecConnection *	conn);
 
+void			swfdec_net_stream_set_url	(SwfdecNetStream *	stream,
+							 const char *		url);
 void			swfdec_net_stream_set_loader	(SwfdecNetStream *	stream,
 							 SwfdecLoader *		loader);
 void			swfdec_net_stream_set_playing	(SwfdecNetStream *	stream,
diff-tree b388b559727066550385b938933b85e443fde2c9 (from 28e968cbba77ca5493a624527e58513f52e542ac)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Mar 1 11:33:13 2007 +0100

    Fix read-out-of-bounds when processing valid strings

diff --git a/libswfdec/swfdec_scriptable.c b/libswfdec/swfdec_scriptable.c
index f48c9be..772a7de 100644
--- a/libswfdec/swfdec_scriptable.c
+++ b/libswfdec/swfdec_scriptable.c
@@ -173,8 +173,11 @@ swfdec_scriptable_set_variables (SwfdecS
   g_return_if_fail (SWFDEC_IS_SCRIPTABLE (script));
   g_return_if_fail (variables != NULL);
 
+  SWFDEC_DEBUG ("setting variables on %p: %s", script, variables);
+  if (*variables == '\0')
+    return;
   object = swfdec_scriptable_get_object (script);
-  while (*variables) {
+  while (TRUE) {
     char *name, *value;
     JSString *string;
     jsval val;
@@ -183,7 +186,9 @@ swfdec_scriptable_set_variables (SwfdecS
       SWFDEC_WARNING ("variables invalid at \"%s\"", variables);
       break;
     }
-    if (*variables != '&' && *variables != '\0') {
+    if (*variables == '\0') {
+      break;
+    } else if (*variables != '&') {
       SWFDEC_WARNING ("variables not delimited with & at \"%s\"", variables);
       g_free (name);
       g_free (value);
diff-tree 28e968cbba77ca5493a624527e58513f52e542ac (from bdd525b89076158bfd947ed1eb0f48fcc24c55cb)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Mar 1 10:19:01 2007 +0100

    implement the downloading part of the XML object

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 7f5cfb7..0c8564c 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -53,6 +53,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_js_mouse.c \
 	swfdec_js_movie.c \
 	swfdec_js_sound.c \
+	swfdec_js_xml.c \
 	swfdec_listener.c \
 	swfdec_loader.c \
 	swfdec_loadertarget.c \
@@ -76,7 +77,8 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_tag.c \
 	swfdec_text.c \
 	swfdec_video.c \
-	swfdec_video_movie.c
+	swfdec_video_movie.c \
+	swfdec_xml.c
 
 libswfdec_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
 	$(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) \
@@ -92,7 +94,6 @@ public_headers = \
 	swfdec.h \
 	swfdec_audio.h \
 	swfdec_buffer.h \
-	swfdec_connection.h \
 	swfdec_loader.h \
 	swfdec_player.h
 
@@ -113,6 +114,7 @@ noinst_HEADERS = \
 	swfdec_character.h \
 	swfdec_codec.h \
 	swfdec_color.h \
+	swfdec_connection.h \
 	swfdec_debug.h \
 	swfdec_debugger.h \
 	swfdec_decoder.h \
@@ -149,7 +151,8 @@ noinst_HEADERS = \
 	swfdec_text.h \
 	swfdec_types.h \
 	swfdec_video.h \
-	swfdec_video_movie.h
+	swfdec_video_movie.h \
+	swfdec_xml.h
 
 EXTRA_DIST = swfdec_marshal.list
 
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 6c39088..7fe7ae2 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -112,6 +112,7 @@ swfdec_js_init_player (SwfdecPlayer *pla
   swfdec_js_add_movieclip_class (player);
   swfdec_js_add_color (player);
   swfdec_js_add_sound (player);
+  swfdec_js_add_xml (player);
   swfdec_js_add_connection (player);
   player->mouse_listener = swfdec_listener_new (player);
   player->key_listener = swfdec_listener_new (player);
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index 77b5e89..fc16871 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -43,6 +43,7 @@ void		swfdec_js_add_globals		(SwfdecPlay
 void		swfdec_js_add_mouse		(SwfdecPlayer *		player);
 void		swfdec_js_add_movieclip_class	(SwfdecPlayer *		player);
 void		swfdec_js_add_sound		(SwfdecPlayer *		player);
+void		swfdec_js_add_xml		(SwfdecPlayer *		player);
 
 void		swfdec_js_movie_add_property	(SwfdecMovie *		movie);
 void		swfdec_js_movie_remove_property	(SwfdecMovie *		movie);
diff --git a/libswfdec/swfdec_js_xml.c b/libswfdec/swfdec_js_xml.c
new file mode 100644
index 0000000..d6d0df5
--- /dev/null
+++ b/libswfdec/swfdec_js_xml.c
@@ -0,0 +1,101 @@
+/* Swfdec
+ * 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_xml.h"
+#include "swfdec_debug.h"
+#include "swfdec_js.h"
+#include "swfdec_player_internal.h"
+
+static JSBool
+swfdec_js_xml_load (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecXml *xml;
+  const char *url;
+
+  xml = JS_GetPrivate (cx, obj);
+  if (xml == NULL)
+    return JS_TRUE;
+  url = swfdec_js_to_string (cx, argv[0]);
+  if (url == NULL)
+    return JS_FALSE;
+  swfdec_xml_load (xml, url);
+  return JS_TRUE;
+}
+
+static JSBool
+swfdec_js_xml_to_string (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  JSString *string;
+
+  string = JS_InternString (cx, "[object Object]");
+  if (string == NULL)
+    return JS_FALSE;
+
+  *rval = STRING_TO_JSVAL (string);
+  return JS_TRUE;
+}
+
+static JSFunctionSpec xml_methods[] = {
+  { "load",		swfdec_js_xml_load,		1, 0, 0 },
+  { "toString",		swfdec_js_xml_to_string,	0, 0, 0 },
+  {0,0,0,0,0}
+};
+
+static void
+swfdec_js_xml_finalize (JSContext *cx, JSObject *obj)
+{
+  SwfdecXml *conn;
+
+  conn = JS_GetPrivate (cx, obj);
+  if (conn) {
+    SWFDEC_SCRIPTABLE (conn)->jsobj = NULL;
+    g_object_unref (conn);
+  }
+}
+
+static JSClass xml_class = {
+    "XML", JSCLASS_HAS_PRIVATE,
+    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
+    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   swfdec_js_xml_finalize,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+swfdec_js_xml_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecXml *xml = swfdec_xml_new (JS_GetContextPrivate (cx));
+
+  JS_SetPrivate (cx, obj, xml);
+  SWFDEC_SCRIPTABLE (xml)->jsobj = obj;
+  *rval = OBJECT_TO_JSVAL (obj);
+  return JS_TRUE;
+}
+
+void
+swfdec_js_add_xml (SwfdecPlayer *player)
+{
+  JS_InitClass (player->jscx, player->jsobj, NULL,
+      &xml_class, swfdec_js_xml_new, 0, NULL, xml_methods,
+      NULL, NULL);
+}
+
diff --git a/libswfdec/swfdec_xml.c b/libswfdec/swfdec_xml.c
new file mode 100644
index 0000000..1f05c7d
--- /dev/null
+++ b/libswfdec/swfdec_xml.c
@@ -0,0 +1,187 @@
+/* Swfdec
+ * 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 <string.h>
+#include "swfdec_xml.h"
+#include "swfdec_debug.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;
+}
+
+static void
+swfdec_xml_ondata (SwfdecXml *xml)
+{
+  JSContext *cx = SWFDEC_SCRIPTABLE (xml)->jscx;
+  JSObject *obj = SWFDEC_SCRIPTABLE (xml)->jsobj;
+  jsval val, fun;
+  JSString *string;
+
+  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);
+  } else {
+    val = JSVAL_VOID;
+  }
+  js_InternalCall (cx, obj, fun, 1, &val, &fun);
+}
+
+static void
+swfdec_xml_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *loader)
+{
+  SwfdecXml *xml = SWFDEC_XML (target);
+
+  if (xml->loader != loader ||
+      (!loader->eof && !loader->error))
+    return;
+
+  /* get the text from the loader */
+  if (loader->error) {
+    /* nothing to do here */
+  } else {
+    guint size;
+    g_assert (loader->eof);
+    size = swfdec_buffer_queue_get_depth (loader->queue);
+    xml->text = g_try_malloc (size + 1);
+    if (xml->text) {
+      SwfdecBuffer *buffer;
+      guint i = 0;
+      while ((buffer = swfdec_buffer_queue_pull_buffer (loader->queue))) {
+	memcpy (xml->text + i, buffer->data, buffer->length);
+	i += buffer->length;
+	swfdec_buffer_unref (buffer);
+      }
+      g_assert (i == size);
+      xml->text[size] = '\0';
+      /* FIXME: validate otherwise? */
+      if (!g_utf8_validate (xml->text, size, NULL)) {
+	SWFDEC_ERROR ("downloaded data is not valid utf-8");
+	g_free (xml->text);
+	xml->text = NULL;
+      }
+    } else {
+      SWFDEC_ERROR ("not enough memory to copy %u bytes", size);
+    }
+  }
+  /* break reference to the loader */
+  xml->loader = NULL;
+  g_object_unref (loader);
+  /* emit onData */
+  swfdec_xml_ondata (xml);
+}
+
+static void
+swfdec_xml_loader_target_init (SwfdecLoaderTargetInterface *iface)
+{
+  iface->get_player = swfdec_xml_loader_target_get_player;
+  iface->parse = swfdec_xml_loader_target_parse;
+}
+
+/*** SWFDEC_XML ***/
+
+G_DEFINE_TYPE_WITH_CODE (SwfdecXml, swfdec_xml, SWFDEC_TYPE_SCRIPTABLE,
+    G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_LOADER_TARGET, swfdec_xml_loader_target_init))
+
+static void
+swfdec_xml_reset (SwfdecXml *xml)
+{
+  if (xml->loader) {
+    g_object_unref (xml->loader);
+    xml->loader = NULL;
+  }
+  g_free (xml->text);
+  xml->text = NULL;
+}
+
+static void
+swfdec_xml_dispose (GObject *object)
+{
+  SwfdecXml *xml = SWFDEC_XML (object);
+
+  swfdec_xml_reset (xml);
+
+  G_OBJECT_CLASS (swfdec_xml_parent_class)->dispose (object);
+}
+
+static void
+swfdec_xml_class_init (SwfdecXmlClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = swfdec_xml_dispose;
+}
+
+static void
+swfdec_xml_init (SwfdecXml *xml)
+{
+}
+
+SwfdecXml *
+swfdec_xml_new (SwfdecPlayer *player)
+{
+  SwfdecXml *xml;
+  SwfdecScriptable *script;
+
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+
+  xml= g_object_new (SWFDEC_TYPE_XML, NULL);
+  xml->player = player;
+
+  script = SWFDEC_SCRIPTABLE (xml);
+  script->jscx = player->jscx;
+
+  return xml;
+}
+
+void
+swfdec_xml_load (SwfdecXml *xml, const char *url)
+{
+  g_return_if_fail (SWFDEC_IS_XML (xml));
+  g_return_if_fail (url != NULL);
+
+  swfdec_xml_reset (xml);
+  xml->loader = swfdec_player_load (xml->player, url);
+  if (xml->loader == NULL) {
+    swfdec_xml_ondata (xml);
+  } else {
+    swfdec_xml_loader_target_parse (SWFDEC_LOADER_TARGET (xml), xml->loader);
+  }
+}
diff --git a/libswfdec/swfdec_xml.h b/libswfdec/swfdec_xml.h
new file mode 100644
index 0000000..b2b3ea8
--- /dev/null
+++ b/libswfdec/swfdec_xml.h
@@ -0,0 +1,59 @@
+/* Swfdec
+ * 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_XML_H_
+#define _SWFDEC_XML_H_
+
+#include <libswfdec/swfdec_scriptable.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecXml SwfdecXml;
+typedef struct _SwfdecXmlClass SwfdecXmlClass;
+
+#define SWFDEC_TYPE_XML                    (swfdec_xml_get_type())
+#define SWFDEC_IS_XML(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_XML))
+#define SWFDEC_IS_XML_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_XML))
+#define SWFDEC_XML(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_XML, SwfdecXml))
+#define SWFDEC_XML_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_XML, SwfdecXmlClass))
+#define SWFDEC_XML_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_XML, SwfdecXmlClass))
+
+struct _SwfdecXml {
+  SwfdecScriptable	scriptable;
+
+  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;
+};
+
+GType		swfdec_xml_get_type	(void);
+
+SwfdecXml *	swfdec_xml_new		(SwfdecPlayer *	player);
+
+void		swfdec_xml_load		(SwfdecXml *	xml,
+					 const char *	url);
+
+
+G_END_DECLS
+#endif
diff-tree bdd525b89076158bfd947ed1eb0f48fcc24c55cb (from 93fbadb06ab7eed16312904ecae3994af890532b)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Mar 1 10:18:22 2007 +0100

    call the parse function after an error
    
    This gets around the need to connect to notify::error

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 828852a..32d0ca4 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -319,6 +319,7 @@ swfdec_loader_error_locked (SwfdecLoader
   SWFDEC_ERROR ("error in loader %p: %s", loader, error);
   loader->error = g_strdup (error);
   g_object_notify (G_OBJECT (loader), "error");
+  swfdec_loader_target_parse (loader->target, loader);
 }
 
 void
diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c
index 8fd629d..6af5504 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -78,6 +78,8 @@ swfdec_loader_target_parse_default (Swfd
   SwfdecDecoder *dec;
   SwfdecDecoderClass *klass;
 
+  if (loader->error)
+    return;
   dec = swfdec_loader_target_get_decoder (target);
   if (dec == NULL) {
     SwfdecPlayer *player;
diff-tree 93fbadb06ab7eed16312904ecae3994af890532b (from 767aca406c495f3eddbb0583cc0dc2e249d7fbf0)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Feb 28 21:10:10 2007 +0100

    implement swfdec_player_load
    
    Also keep the initial loader around. This may be interesting if we ever want
    to implement swfdec_player_reset() to restart from the beginning.
    The only feature missing for that is non-destructive reading from the loader.

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 76c93e7..6de320b 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -367,6 +367,10 @@ swfdec_player_dispose (GObject *object)
   }
   g_assert (player->timeouts == NULL);
   swfdec_cache_unref (player->cache);
+  if (player->loader) {
+    g_object_unref (player->loader);
+    player->loader = NULL;
+  }
 
   G_OBJECT_CLASS (swfdec_player_parent_class)->dispose (object);
 }
@@ -948,6 +952,16 @@ swfdec_player_remove_level (SwfdecPlayer
   SWFDEC_LOG ("no movie to remove at level %u", depth);
 }
 
+SwfdecLoader *
+swfdec_player_load (SwfdecPlayer *player, const char *url)
+{
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  g_return_val_if_fail (url != NULL, NULL);
+
+  g_assert (player->loader);
+  return swfdec_loader_load (player->loader, url);
+}
+
 void
 swfdec_player_launch (SwfdecPlayer *player, const char *url, const char *target)
 {
@@ -1057,6 +1071,8 @@ swfdec_player_set_loader_with_variables 
   g_return_if_fail (player->roots == NULL);
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
 
+  player->loader = loader;
+  g_object_ref (loader);
   movie = swfdec_player_add_level_from_loader (player, 0, loader, variables);
   swfdec_loader_parse (loader);
 }
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index 2e63b78..6d40273 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -49,6 +49,7 @@ struct _SwfdecPlayer
   SwfdecCache *		cache;			/* player cache */
   gboolean		bgcolor_set;		/* TRUE if the background color has been set */
   SwfdecColor		bgcolor;		/* background color */
+  SwfdecLoader *	loader;			/* initial loader */
 
   /* javascript */
   JSContext *		jscx;			/* global Javascript context */
@@ -139,6 +140,8 @@ SwfdecRootMovie *	swfdec_player_add_leve
 						 const char *		variables);
 void		swfdec_player_remove_level	(SwfdecPlayer *		player,
 						 guint			depth);
+SwfdecLoader *	swfdec_player_load		(SwfdecPlayer *         player,
+						 const char *		url);
 void		swfdec_player_launch		(SwfdecPlayer *         player,
 						 const char *		url,
 						 const char *		target);
diff-tree 767aca406c495f3eddbb0583cc0dc2e249d7fbf0 (from 107c424998f16d2d4a2dd2d8645a7cff46094714)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Feb 28 16:18:49 2007 +0100

    make swfdec_loader_error a properly exported function

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 3beff3e..828852a 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -110,6 +110,7 @@ swfdec_loader_dispose (GObject *object)
 
   swfdec_buffer_queue_free (loader->queue);
   g_free (loader->url);
+  g_free (loader->error);
 
   G_OBJECT_CLASS (swfdec_loader_parent_class)->dispose (object);
 }
@@ -281,9 +282,20 @@ swfdec_loader_new_from_file (const char 
   return loader;
 }
 
+/**
+ * swfdec_loader_error:
+ * @loader: a #SwfdecLoader
+ * @error: a string describing the error
+ *
+ * Moves the loader in the error state if it wasn't before. A loader that is in
+ * the error state will not process any more data. Also, internal error 
+ * handling scripts may be executed.
+ **/
 void
 swfdec_loader_error (SwfdecLoader *loader, const char *error)
 {
+  SwfdecPlayer *player;
+
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
   g_return_if_fail (error != NULL);
 
@@ -291,6 +303,20 @@ swfdec_loader_error (SwfdecLoader *loade
   if (loader->error)
     return;
 
+  player = swfdec_loader_target_get_player (loader->target);
+  swfdec_player_lock (player);
+  swfdec_loader_error_locked (loader, error);
+  swfdec_player_perform_actions (player);
+  swfdec_player_unlock (player);
+}
+
+void
+swfdec_loader_error_locked (SwfdecLoader *loader, const char *error)
+{
+  if (loader->error)
+    return;
+
+  SWFDEC_ERROR ("error in loader %p: %s", loader, error);
   loader->error = g_strdup (error);
   g_object_notify (G_OBJECT (loader), "error");
 }
diff --git a/libswfdec/swfdec_loader_internal.h b/libswfdec/swfdec_loader_internal.h
index c49f078..3c99959 100644
--- a/libswfdec/swfdec_loader_internal.h
+++ b/libswfdec/swfdec_loader_internal.h
@@ -31,6 +31,8 @@ SwfdecLoader *		swfdec_loader_load		(Swf
 void			swfdec_loader_parse		(SwfdecLoader *		loader);
 void			swfdec_loader_set_target	(SwfdecLoader *		loader,
 							 SwfdecLoaderTarget *	target);
+void	  		swfdec_loader_error_locked	(SwfdecLoader *		loader,
+							 const char *		error);
 
 gboolean		swfdec_urldecode_one		(const char *		string,
 							 char **		name,
diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c
index 218a156..8fd629d 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -22,6 +22,7 @@
 #endif
 
 #include "swfdec_loadertarget.h"
+#include "swfdec_loader_internal.h"
 
 static void
 swfdec_loader_target_base_init (gpointer g_class)
@@ -85,11 +86,11 @@ swfdec_loader_target_parse_default (Swfd
     player = swfdec_loader_target_get_player (target);
     dec = swfdec_decoder_new (player, loader->queue);
     if (dec == NULL) {
-      swfdec_loader_error (loader, "Unknown format");
+      swfdec_loader_error_locked (loader, "Unknown format");
       return;
     }
     if (!swfdec_loader_target_set_decoder (target, dec)) {
-      swfdec_loader_error (loader, "Internal error");
+      swfdec_loader_error_locked (loader, "Internal error");
       return;
     }
   }
@@ -99,7 +100,7 @@ swfdec_loader_target_parse_default (Swfd
     SwfdecStatus status = klass->parse (dec);
     switch (status) {
       case SWFDEC_STATUS_ERROR:
-	swfdec_loader_error (loader, "parsing error");
+	swfdec_loader_error_locked (loader, "parsing error");
 	return;
       case SWFDEC_STATUS_OK:
 	break;
@@ -107,7 +108,7 @@ swfdec_loader_target_parse_default (Swfd
 	return;
       case SWFDEC_STATUS_IMAGE:
 	if (!swfdec_loader_target_image (target)) {
-	  swfdec_loader_error (loader, "Internal error");
+	  swfdec_loader_error_locked (loader, "Internal error");
 	  return;
 	}
 	break;
@@ -115,7 +116,7 @@ swfdec_loader_target_parse_default (Swfd
 	g_assert (dec->width > 0);
 	g_assert (dec->height > 0);
 	if (!swfdec_loader_target_init (target)) {
-	  swfdec_loader_error (loader, "Internal error");
+	  swfdec_loader_error_locked (loader, "Internal error");
 	  return;
 	}
 	break;
diff-tree 107c424998f16d2d4a2dd2d8645a7cff46094714 (from 2345e9a94736cce68debbc3519c4c645b462e2ae)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Feb 28 15:09:42 2007 +0100

    rework Loader <=> LoaderTarget interaction
    
    These changes are preparing the use of loaders by the XML class.
    I also consider the overloaded SwfdecLoaderTarget interface pretty much
    deprecated in favour of the new parse method. I just need the will to
    implement it properly. :)

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 49d7642..3beff3e 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -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
@@ -56,23 +56,62 @@
 
 /*** SwfdecLoader ***/
 
+enum {
+  PROP_0,
+  PROP_ERROR,
+  PROP_EOF
+};
+
 G_DEFINE_ABSTRACT_TYPE (SwfdecLoader, swfdec_loader, G_TYPE_OBJECT)
 
 static void
-swfdec_loader_dispose (GObject *object)
+swfdec_loader_get_property (GObject *object, guint param_id, GValue *value, 
+    GParamSpec * pspec)
 {
   SwfdecLoader *loader = SWFDEC_LOADER (object);
+  
+  switch (param_id) {
+    case PROP_ERROR:
+      g_value_set_string (value, loader->error);
+      break;
+    case PROP_EOF:
+      g_value_set_boolean (value, loader->eof);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
 
-  swfdec_buffer_queue_free (loader->queue);
-  g_free (loader->url);
+static void
+swfdec_loader_set_property (GObject *object, guint param_id, const GValue *value,
+    GParamSpec *pspec)
+{
+  SwfdecLoader *loader = SWFDEC_LOADER (object);
 
-  G_OBJECT_CLASS (swfdec_loader_parent_class)->dispose (object);
+  switch (param_id) {
+    case PROP_ERROR:
+      swfdec_loader_error (loader, g_value_get_string (value));
+      break;
+    case PROP_EOF:
+      if (g_value_get_boolean (value) && !loader->eof)
+	swfdec_loader_eof (loader);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
 }
 
 static void
-swfdec_loader_do_error (SwfdecLoader *loader, const char *error)
+swfdec_loader_dispose (GObject *object)
 {
-  SWFDEC_ERROR ("Error from loader %p: %s", loader, error);
+  SwfdecLoader *loader = SWFDEC_LOADER (object);
+
+  swfdec_buffer_queue_free (loader->queue);
+  g_free (loader->url);
+
+  G_OBJECT_CLASS (swfdec_loader_parent_class)->dispose (object);
 }
 
 static void
@@ -81,8 +120,15 @@ swfdec_loader_class_init (SwfdecLoaderCl
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_loader_dispose;
+  object_class->get_property = swfdec_loader_get_property;
+  object_class->set_property = swfdec_loader_set_property;
 
-  klass->error = swfdec_loader_do_error;
+  g_object_class_install_property (object_class, PROP_ERROR,
+      g_param_spec_string ("error", "error", "NULL when no error or string describing error",
+	  NULL, G_PARAM_READABLE));
+  g_object_class_install_property (object_class, PROP_EOF,
+      g_param_spec_boolean ("eof", "eof", "TRUE when all data has been handed to the loader",
+	  FALSE, G_PARAM_READABLE));
 }
 
 static void
@@ -235,70 +281,18 @@ swfdec_loader_new_from_file (const char 
   return loader;
 }
 
-static void
-swfdec_loader_error (SwfdecLoader *loader, gboolean notify)
-{
-  loader->error = TRUE;
-  SWFDEC_INFO ("error in loader %p (%s)", loader, loader->url);
-  if (loader->target && notify)
-    swfdec_loader_target_error (loader->target);
-}
-
 void
-swfdec_loader_parse_internal (SwfdecLoader *loader)
+swfdec_loader_error (SwfdecLoader *loader, const char *error)
 {
-  SwfdecDecoder *dec;
-  SwfdecDecoderClass *klass;
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+  g_return_if_fail (error != NULL);
 
-  dec = swfdec_loader_target_get_decoder (loader->target);
-  if (dec == NULL) {
-    SwfdecPlayer *player;
-    if (!swfdec_decoder_can_detect (loader->queue))
-      return;
-    player = swfdec_loader_target_get_player (loader->target);
-    dec = swfdec_decoder_new (player, loader->queue);
-    if (dec == NULL) {
-      swfdec_loader_error (loader, TRUE);
-      return;
-    }
-    if (!swfdec_loader_target_set_decoder (loader->target, dec)) {
-      swfdec_loader_error (loader, FALSE);
-      return;
-    }
-  }
-  klass = SWFDEC_DECODER_GET_CLASS (dec);
-  g_return_if_fail (klass->parse);
-  while (TRUE) {
-    SwfdecStatus status = klass->parse (dec);
-    switch (status) {
-      case SWFDEC_STATUS_ERROR:
-	swfdec_loader_error (loader, TRUE);
-	return;
-      case SWFDEC_STATUS_OK:
-	break;
-      case SWFDEC_STATUS_NEEDBITS:
-	return;
-      case SWFDEC_STATUS_IMAGE:
-	if (!swfdec_loader_target_image (loader->target)) {
-	  swfdec_loader_error (loader, TRUE);
-	  return;
-	}
-	break;
-      case SWFDEC_STATUS_INIT:
-	g_assert (dec->width > 0);
-	g_assert (dec->height > 0);
-	if (!swfdec_loader_target_init (loader->target)) {
-	  swfdec_loader_error (loader, TRUE);
-	  return;
-	}
-	break;
-      case SWFDEC_STATUS_EOF:
-	return;
-      default:
-	g_assert_not_reached ();
-	return;
-    }
-  }
+  SWFDEC_ERROR ("error in loader %p: %s", loader, error);
+  if (loader->error)
+    return;
+
+  loader->error = g_strdup (error);
+  g_object_notify (G_OBJECT (loader), "error");
 }
 
 void
@@ -312,7 +306,7 @@ swfdec_loader_parse (SwfdecLoader *loade
 
   player = swfdec_loader_target_get_player (loader->target);
   swfdec_player_lock (player);
-  swfdec_loader_parse_internal (loader);
+  swfdec_loader_target_parse (loader->target, loader);
   swfdec_player_perform_actions (player);
   swfdec_player_unlock (player);
 }
@@ -349,6 +343,7 @@ swfdec_loader_eof (SwfdecLoader *loader)
   g_return_if_fail (loader->eof == FALSE);
 
   loader->eof = TRUE;
+  g_object_notify (G_OBJECT (loader), "eof");
   swfdec_loader_parse (loader);
 }
 
diff --git a/libswfdec/swfdec_loader.h b/libswfdec/swfdec_loader.h
index cf1d65a..87153b4 100644
--- a/libswfdec/swfdec_loader.h
+++ b/libswfdec/swfdec_loader.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
@@ -43,7 +43,7 @@ struct _SwfdecLoader
   char *		url;		/* the URL for this loader in UTF-8 - must be set on creation */
   /*< private >*/
   gboolean		eof;		/* if we're in EOF already */
-  gboolean		error;		/* if there's an error (from parsing the loader) */
+  char *		error;		/* if there's an error (from parsing the loader) */
   gpointer		target;		/* SwfdecLoaderTarget that gets notified about loading progress */
   SwfdecBufferQueue *	queue;		/* SwfdecBufferQueue managing the input buffers */
 };
@@ -55,9 +55,6 @@ struct _SwfdecLoaderClass
   /* FIXME: better error reporting? */
   SwfdecLoader *      	(* load)	(SwfdecLoader *			loader, 
 					 const char *			url);
-  /* FIXME: make this a GError? */
-  void			(* error)	(SwfdecLoader *			loader,
-					 const char *			error);
 };
 
 GType		swfdec_loader_get_type		(void);
@@ -68,6 +65,8 @@ SwfdecLoader *	swfdec_loader_new_from_fi
 void		swfdec_loader_push		(SwfdecLoader *		loader,
 						 SwfdecBuffer *		buffer);
 void		swfdec_loader_eof		(SwfdecLoader *		loader);
+void		swfdec_loader_error		(SwfdecLoader *		loader,
+						 const char *		error);
 char *  	swfdec_loader_get_filename	(SwfdecLoader *		loader);
 					 
 
diff --git a/libswfdec/swfdec_loader_internal.h b/libswfdec/swfdec_loader_internal.h
index 8f9a3db..c49f078 100644
--- a/libswfdec/swfdec_loader_internal.h
+++ b/libswfdec/swfdec_loader_internal.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
@@ -29,7 +29,6 @@ G_BEGIN_DECLS
 SwfdecLoader *		swfdec_loader_load		(SwfdecLoader *		loader,
 							 const char *		url);
 void			swfdec_loader_parse		(SwfdecLoader *		loader);
-void			swfdec_loader_parse_internal	(SwfdecLoader *		loader);
 void			swfdec_loader_set_target	(SwfdecLoader *		loader,
 							 SwfdecLoaderTarget *	target);
 
diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c
index 48b4090..218a156 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -71,28 +71,92 @@ swfdec_loader_target_get_player (SwfdecL
   return iface->get_player (target);
 }
 
-SwfdecDecoder *
-swfdec_loader_target_get_decoder (SwfdecLoaderTarget *target)
+void
+swfdec_loader_target_parse_default (SwfdecLoaderTarget *target, SwfdecLoader *loader)
+{
+  SwfdecDecoder *dec;
+  SwfdecDecoderClass *klass;
+
+  dec = swfdec_loader_target_get_decoder (target);
+  if (dec == NULL) {
+    SwfdecPlayer *player;
+    if (!swfdec_decoder_can_detect (loader->queue))
+      return;
+    player = swfdec_loader_target_get_player (target);
+    dec = swfdec_decoder_new (player, loader->queue);
+    if (dec == NULL) {
+      swfdec_loader_error (loader, "Unknown format");
+      return;
+    }
+    if (!swfdec_loader_target_set_decoder (target, dec)) {
+      swfdec_loader_error (loader, "Internal error");
+      return;
+    }
+  }
+  klass = SWFDEC_DECODER_GET_CLASS (dec);
+  g_return_if_fail (klass->parse);
+  while (TRUE) {
+    SwfdecStatus status = klass->parse (dec);
+    switch (status) {
+      case SWFDEC_STATUS_ERROR:
+	swfdec_loader_error (loader, "parsing error");
+	return;
+      case SWFDEC_STATUS_OK:
+	break;
+      case SWFDEC_STATUS_NEEDBITS:
+	return;
+      case SWFDEC_STATUS_IMAGE:
+	if (!swfdec_loader_target_image (target)) {
+	  swfdec_loader_error (loader, "Internal error");
+	  return;
+	}
+	break;
+      case SWFDEC_STATUS_INIT:
+	g_assert (dec->width > 0);
+	g_assert (dec->height > 0);
+	if (!swfdec_loader_target_init (target)) {
+	  swfdec_loader_error (loader, "Internal error");
+	  return;
+	}
+	break;
+      case SWFDEC_STATUS_EOF:
+	return;
+      default:
+	g_assert_not_reached ();
+	return;
+    }
+  }
+}
+
+void
+swfdec_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *loader)
 {
   SwfdecLoaderTargetInterface *iface;
   
-  g_return_val_if_fail (SWFDEC_IS_LOADER_TARGET (target), NULL);
+  g_return_if_fail (SWFDEC_IS_LOADER_TARGET (target));
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+
+  if (loader->error)
+    return;
 
   iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
-  g_assert (iface->get_decoder != NULL);
-  return iface->get_decoder (target);
+  if (iface->parse == NULL) {
+    swfdec_loader_target_parse_default (target, loader);
+  } else {
+    iface->parse (target, loader);
+  }
 }
 
-void
-swfdec_loader_target_error (SwfdecLoaderTarget *target)
+SwfdecDecoder *
+swfdec_loader_target_get_decoder (SwfdecLoaderTarget *target)
 {
   SwfdecLoaderTargetInterface *iface;
   
-  g_return_if_fail (SWFDEC_IS_LOADER_TARGET (target));
+  g_return_val_if_fail (SWFDEC_IS_LOADER_TARGET (target), NULL);
 
   iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
-  if (iface->error != NULL)
-    iface->error (target);
+  g_assert (iface->get_decoder != NULL);
+  return iface->get_decoder (target);
 }
 
 gboolean
diff --git a/libswfdec/swfdec_loadertarget.h b/libswfdec/swfdec_loadertarget.h
index fe26c5e..806ce82 100644
--- a/libswfdec/swfdec_loadertarget.h
+++ b/libswfdec/swfdec_loadertarget.h
@@ -38,11 +38,13 @@ struct _SwfdecLoaderTargetInterface {
 
   /* mandatory vfuncs */
   SwfdecPlayer *	(* get_player)      	(SwfdecLoaderTarget *	target);
+  void			(* parse)		(SwfdecLoaderTarget *   target,
+						 SwfdecLoader *		loader);
+  /* if default parser is used, you need the following - consider them deprecated */
   SwfdecDecoder *	(* get_decoder)		(SwfdecLoaderTarget *	target);
   gboolean		(* set_decoder)		(SwfdecLoaderTarget *	target,
 						 SwfdecDecoder *	decoder);
   /* optional vfuncs */
-  void			(* error)		(SwfdecLoaderTarget *	target);
   gboolean    		(* init)		(SwfdecLoaderTarget *	target);
   gboolean		(* image)		(SwfdecLoaderTarget *	target);
 };
@@ -50,6 +52,8 @@ struct _SwfdecLoaderTargetInterface {
 GType		swfdec_loader_target_get_type		(void) G_GNUC_CONST;
 
 SwfdecPlayer *	swfdec_loader_target_get_player		(SwfdecLoaderTarget *	target);
+void		swfdec_loader_target_parse		(SwfdecLoaderTarget *	target,
+							 SwfdecLoader *		loader);
 SwfdecDecoder *	swfdec_loader_target_get_decoder	(SwfdecLoaderTarget *	target);
 gboolean	swfdec_loader_target_set_decoder	(SwfdecLoaderTarget *	target,
 							 SwfdecDecoder *	decoder);
diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c
index 414838e..1b7c264 100644
--- a/libswfdec/swfdec_root_movie.c
+++ b/libswfdec/swfdec_root_movie.c
@@ -171,7 +171,7 @@ swfdec_root_movie_init (SwfdecRootMovie 
 void
 swfdec_root_movie_do_parse (gpointer movie, gpointer unused)
 {
-  swfdec_loader_parse_internal (SWFDEC_ROOT_MOVIE (movie)->loader);
+  swfdec_loader_target_parse (SWFDEC_LOADER_TARGET (movie), SWFDEC_ROOT_MOVIE (movie)->loader);
 }
 
 void
diff-tree 2345e9a94736cce68debbc3519c4c645b462e2ae (from a383a7e1a96e96c9718421b26d92e11ec9f69ea6)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Feb 28 12:40:29 2007 +0100

    add simple test for NetConnection

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index ea517f7..96d586f 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -82,6 +82,8 @@ EXTRA_DIST = \
 	name2.swf.trace \
 	names.swf \
 	names.swf.trace \
+	netconnection.swf \
+	netconnection.swf.trace \
 	number.swf \
 	number.swf.trace \
 	object-math-5.swf \
diff --git a/test/trace/netconnection.swf b/test/trace/netconnection.swf
new file mode 100755
index 0000000..cb822ac
Binary files /dev/null and b/test/trace/netconnection.swf differ
diff --git a/test/trace/netconnection.swf.trace b/test/trace/netconnection.swf.trace
new file mode 100755
index 0000000..296c2b7
--- /dev/null
+++ b/test/trace/netconnection.swf.trace
@@ -0,0 +1,6 @@
+test basic NetConnection functionality
+caliing connect on [object Object]...
+NetConnection.Connect.Success
+status
+undefined
+  done
diff-tree a383a7e1a96e96c9718421b26d92e11ec9f69ea6 (from 134c98d16a0ce78f6869f8ef41c276d334750dc6)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Feb 28 12:38:03 2007 +0100

    implement NetConnection object in a pretty stubbed form

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 1fd20c9..7f5cfb7 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -32,6 +32,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	$(CODECS) \
 	swfdec_codec_screen.c \
 	swfdec_color.c \
+	swfdec_connection.c \
 	swfdec_debug.c \
 	swfdec_debugger.c \
 	swfdec_decoder.c \
@@ -47,6 +48,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	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 \
@@ -90,6 +92,7 @@ public_headers = \
 	swfdec.h \
 	swfdec_audio.h \
 	swfdec_buffer.h \
+	swfdec_connection.h \
 	swfdec_loader.h \
 	swfdec_player.h
 
diff --git a/libswfdec/swfdec_connection.c b/libswfdec/swfdec_connection.c
new file mode 100644
index 0000000..2360804
--- /dev/null
+++ b/libswfdec/swfdec_connection.c
@@ -0,0 +1,121 @@
+/* Swfdec
+ * 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 <string.h>
+#include "swfdec_connection.h"
+#include "swfdec_debug.h"
+#include "js/jsapi.h"
+#include "js/jsinterp.h"
+
+/*** SwfdecConnection ***/
+
+G_DEFINE_TYPE (SwfdecConnection, swfdec_connection, SWFDEC_TYPE_SCRIPTABLE)
+
+static void
+swfdec_connection_dispose (GObject *object)
+{
+  SwfdecConnection *connection = SWFDEC_CONNECTION (object);
+
+  g_free (connection->url);
+  connection->url = NULL;
+
+  G_OBJECT_CLASS (swfdec_connection_parent_class)->dispose (object);
+}
+
+static void
+swfdec_connection_class_init (SwfdecConnectionClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = swfdec_connection_dispose;
+}
+
+static void
+swfdec_connection_init (SwfdecConnection *connection)
+{
+}
+
+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;
+
+  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))
+    return;
+  if (description) {
+    if ((string = JS_NewStringCopyZ (cx, level)) == NULL ||
+	(val = STRING_TO_JSVAL (string)) == 0 ||
+	!JS_SetProperty (cx, info, "description", &val))
+      return;
+  }
+  val = OBJECT_TO_JSVAL (info);
+  js_InternalCall (cx, obj, fun, 1, &val, &fun);
+}
+
+SwfdecConnection *
+swfdec_connection_new (JSContext *cx, JSObject *obj)
+{
+  SwfdecConnection *conn;
+  SwfdecScriptable *script;
+
+  g_return_val_if_fail (cx != NULL, NULL);
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  conn = g_object_new (SWFDEC_TYPE_CONNECTION, NULL);
+  script = SWFDEC_SCRIPTABLE (conn);
+  script->jscx = cx;
+  script->jsobj = obj;
+
+  return conn;
+}
+
+void
+swfdec_connection_connect (SwfdecConnection *conn, const char *url)
+{
+  g_return_if_fail (SWFDEC_IS_CONNECTION (conn));
+
+  g_free (conn->url);
+  conn->url = g_strdup (url);
+  if (url) {
+    SWFDEC_ERROR ("FIXME: using NetConnection with non-null URLs is not implemented");
+  }
+  swfdec_connection_onstatus (conn, "NetConnection.Connect.Success",
+      "status", NULL);
+}
+
diff --git a/libswfdec/swfdec_connection.h b/libswfdec/swfdec_connection.h
new file mode 100644
index 0000000..737a139
--- /dev/null
+++ b/libswfdec/swfdec_connection.h
@@ -0,0 +1,58 @@
+/* Swfdec
+ * 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_CONNECTION_H_
+#define _SWFDEC_CONNECTION_H_
+
+#include <libswfdec/swfdec_scriptable.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecConnection SwfdecConnection;
+typedef struct _SwfdecConnectionClass SwfdecConnectionClass;
+
+#define SWFDEC_TYPE_CONNECTION                    (swfdec_connection_get_type())
+#define SWFDEC_IS_CONNECTION(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_CONNECTION))
+#define SWFDEC_IS_CONNECTION_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_CONNECTION))
+#define SWFDEC_CONNECTION(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_CONNECTION, SwfdecConnection))
+#define SWFDEC_CONNECTION_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_CONNECTION, SwfdecConnectionClass))
+#define SWFDEC_CONNECTION_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_CONNECTION, SwfdecConnectionClass))
+
+struct _SwfdecConnection {
+  SwfdecScriptable	scriptable;
+
+  char *		url;		/* url for this connection or NULL for none */
+};
+
+struct _SwfdecConnectionClass {
+  SwfdecScriptableClass	scriptable_class;
+};
+
+GType			swfdec_connection_get_type	(void);
+
+SwfdecConnection *	swfdec_connection_new		(JSContext *		cx,
+							 JSObject *		obj);
+
+void			swfdec_connection_connect	(SwfdecConnection *	conn,
+							 const char *		url);
+
+
+G_END_DECLS
+#endif
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index b9313c1..6c39088 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -112,6 +112,7 @@ swfdec_js_init_player (SwfdecPlayer *pla
   swfdec_js_add_movieclip_class (player);
   swfdec_js_add_color (player);
   swfdec_js_add_sound (player);
+  swfdec_js_add_connection (player);
   player->mouse_listener = swfdec_listener_new (player);
   player->key_listener = swfdec_listener_new (player);
 }
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index 5e58152..77b5e89 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -38,6 +38,7 @@ gboolean	swfdec_js_run			(SwfdecPlayer *
 						 jsval *		rval);
 
 void		swfdec_js_add_color		(SwfdecPlayer *		player);
+void		swfdec_js_add_connection	(SwfdecPlayer *		player);
 void		swfdec_js_add_globals		(SwfdecPlayer *		player);
 void		swfdec_js_add_mouse		(SwfdecPlayer *		player);
 void		swfdec_js_add_movieclip_class	(SwfdecPlayer *		player);
diff --git a/libswfdec/swfdec_js_connection.c b/libswfdec/swfdec_js_connection.c
new file mode 100644
index 0000000..7e820f8
--- /dev/null
+++ b/libswfdec/swfdec_js_connection.c
@@ -0,0 +1,108 @@
+/* Swfdec
+ * 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_connection.h"
+#include "swfdec_debug.h"
+#include "swfdec_js.h"
+#include "swfdec_player_internal.h"
+
+static JSBool
+swfdec_js_connection_connect (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  const char *url;
+  SwfdecConnection *conn = SWFDEC_CONNECTION (JS_GetPrivate (cx, obj));
+
+  if (conn == NULL) {
+    SWFDEC_INFO ("connect called on prototype, ignoring");
+    return JS_TRUE;
+  }
+  if (JSVAL_IS_STRING (argv[0])) {
+    url = swfdec_js_to_string (cx, argv[0]);
+    if (url == NULL)
+      return JS_FALSE;
+  } else if (JSVAL_IS_NULL (argv[0])) {
+    url = NULL;
+  } else {
+    SWFDEC_INFO ("untested argument to NetConnection.connect: %lu", argv[0]);
+    url = NULL;
+  }
+  swfdec_connection_connect (conn, url);
+  return JS_TRUE;
+}
+
+static JSBool
+swfdec_js_connection_to_string (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  JSString *string;
+
+  string = JS_InternString (cx, "[object Object]");
+  if (string == NULL)
+    return JS_FALSE;
+
+  *rval = STRING_TO_JSVAL (string);
+  return JS_TRUE;
+}
+
+static JSFunctionSpec connection_methods[] = {
+  { "connect",		swfdec_js_connection_connect,	1, 0, 0 },
+  { "toString",		swfdec_js_connection_to_string,	0, 0, 0 },
+  {0,0,0,0,0}
+};
+
+static void
+swfdec_js_connection_finalize (JSContext *cx, JSObject *obj)
+{
+  SwfdecConnection *conn;
+
+  conn = JS_GetPrivate (cx, obj);
+  if (conn) {
+    SWFDEC_SCRIPTABLE (conn)->jsobj = NULL;
+    g_object_unref (conn);
+  }
+}
+
+static JSClass connection_class = {
+    "NetConnection", JSCLASS_HAS_PRIVATE,
+    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
+    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   swfdec_js_connection_finalize,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+swfdec_js_connection_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecConnection *conn = swfdec_connection_new (cx, obj);
+
+  JS_SetPrivate (cx, obj, conn);
+  *rval = OBJECT_TO_JSVAL (obj);
+  return JS_TRUE;
+}
+
+void
+swfdec_js_add_connection (SwfdecPlayer *player)
+{
+  JS_InitClass (player->jscx, player->jsobj, NULL,
+      &connection_class, swfdec_js_connection_new, 0, NULL, connection_methods,
+      NULL, NULL);
+}
+
diff-tree 134c98d16a0ce78f6869f8ef41c276d334750dc6 (from 66851d9bc67c5663464a4c9488235e3c233579a7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Feb 22 22:58:31 2007 +0100

    add debug warning about missing constructors

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index d688693..6e75785 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1391,9 +1391,11 @@ swfdec_action_new_object (JSContext *cx,
   JSObject *object;
   const JSClass *clasp;
   guint n_args;
+  const char *name;
 
   constructor = fp->sp[-1];
-  if (!swfdec_eval_jsval (cx, NULL, &constructor))
+  name = swfdec_eval_jsval (cx, NULL, &constructor);
+  if (name == NULL)
     return JS_FALSE;
   if (!JS_ValueToECMAUint32 (cx, fp->sp[-2], &n_args))
     return JS_FALSE;
@@ -1401,6 +1403,9 @@ swfdec_action_new_object (JSContext *cx,
     SWFDEC_ERROR ("not enough stack space");
     return JS_FALSE;
   }
+  if (constructor == JSVAL_VOID) {
+    SWFDEC_WARNING ("no constructor for %s", name);
+  }
   fp->sp[-1] = constructor;
 
   if (!JSVAL_IS_OBJECT (constructor) || JSVAL_IS_NULL (constructor))


More information about the Swfdec mailing list