[Swfdec] 9 commits - doc/swfdec-sections.txt libswfdec/swfdec_as_frame.c libswfdec/swfdec_loader.c libswfdec/swfdec_loader.h libswfdec/swfdec_loader_internal.h libswfdec/swfdec_loadertarget.c libswfdec/swfdec_loadertarget.h libswfdec/swfdec_movie.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_swf_instance.c libswfdec/swfdec_url.c libswfdec/swfdec_xml.c player/swfdec_slow_loader.c

Benjamin Otte company at kemper.freedesktop.org
Wed Aug 1 08:08:58 PDT 2007


 doc/swfdec-sections.txt            |    5 +
 libswfdec/swfdec_as_frame.c        |   10 ++
 libswfdec/swfdec_loader.c          |  173 ++++++++++++++++++++++---------------
 libswfdec/swfdec_loader.h          |    8 +
 libswfdec/swfdec_loader_internal.h |   12 +-
 libswfdec/swfdec_loadertarget.c    |   52 ++++++++++-
 libswfdec/swfdec_loadertarget.h    |   17 +++
 libswfdec/swfdec_movie.c           |    1 
 libswfdec/swfdec_net_stream.c      |   96 ++++++++++++--------
 libswfdec/swfdec_player.c          |   94 +++++++++++++++++++-
 libswfdec/swfdec_player_internal.h |   11 ++
 libswfdec/swfdec_swf_instance.c    |   19 ++--
 libswfdec/swfdec_url.c             |    2 
 libswfdec/swfdec_xml.c             |   71 ++++++++-------
 player/swfdec_slow_loader.c        |   15 ++-
 15 files changed, 420 insertions(+), 166 deletions(-)

New commits:
diff-tree e24deaade92d1c0b55dd2fda9c422a9759e2aa18 (from 2253157314bf1e420b56212989d09b6c50d46e9c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 17:06:53 2007 +0200

    document swfdec_as_frame_init_arguments()

diff --git a/libswfdec/swfdec_as_frame.c b/libswfdec/swfdec_as_frame.c
index 612ed70..4608b0a 100644
--- a/libswfdec/swfdec_as_frame.c
+++ b/libswfdec/swfdec_as_frame.c
@@ -62,6 +62,16 @@
  * allocated on the stack. All of its members are private.
  */
 
+/**
+ * swfdec_as_stack_iterator_init_arguments:
+ * @iter: iterator to be initialized
+ * @frame: the frame to initialize from
+ *
+ * Initializes a stack iterator to walk the arguments passed to the given @frame. See
+ * swfdec_as_stack_iterator_init() about suggested iterator usage.
+ *
+ * Returns: The value of the first argument
+ **/
 SwfdecAsValue *
 swfdec_as_stack_iterator_init_arguments (SwfdecAsStackIterator *iter, SwfdecAsFrame *frame)
 {
diff-tree 2253157314bf1e420b56212989d09b6c50d46e9c (from 8c33c1d42b579e7897fd0353e6e549543d289fa7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 17:02:59 2007 +0200

    fix up docs build

diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt
index ccb76d4..a250b3a 100644
--- a/doc/swfdec-sections.txt
+++ b/doc/swfdec-sections.txt
@@ -19,9 +19,11 @@ SWFDEC_AUDIO_GET_CLASS
 <TITLE>SwfdecLoader</TITLE>
 SwfdecLoader
 swfdec_loader_new_from_file
+swfdec_loader_open
 swfdec_loader_push
 swfdec_loader_eof
 swfdec_loader_error
+swfdec_loader_get_url
 swfdec_loader_set_size
 swfdec_loader_get_size
 swfdec_loader_get_loaded
@@ -52,6 +54,7 @@ swfdec_url_get_url
 swfdec_url_new
 swfdec_url_new_relative
 <SUBSECTION Standard>
+SWFDEC_TYPE_URL
 swfdec_url_get_type
 </SECTION>
 
@@ -116,7 +119,9 @@ swfdec_buffer_queue_pull
 swfdec_buffer_queue_pull_buffer
 swfdec_buffer_queue_peek
 <SUBSECTION Standard>
+SWFDEC_TYPE_BUFFER
 swfdec_buffer_get_type
+SWFDEC_TYPE_BUFFER_QUEUE
 swfdec_buffer_queue_get_type
 </SECTION>
 
diff-tree 8c33c1d42b579e7897fd0353e6e549543d289fa7 (from d0e4e10c1aa96552bcf2aa96af5949650870926b)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 16:54:05 2007 +0200

    make it compile (it doesn't work yet)

diff --git a/player/swfdec_slow_loader.c b/player/swfdec_slow_loader.c
index c568316..603627a 100644
--- a/player/swfdec_slow_loader.c
+++ b/player/swfdec_slow_loader.c
@@ -81,12 +81,16 @@ swfdec_slow_loader_tick (gpointer data)
     swfdec_loader_error (SWFDEC_LOADER (slow), slow->loader->error);
     slow->timeout_id = 0;
     return FALSE;
-  } else if (slow->loader->eof) {
-    swfdec_loader_eof (SWFDEC_LOADER (slow));
-    slow->timeout_id = 0;
-    return FALSE;
   } else {
-    return TRUE;
+    gboolean eof;
+    g_object_get (slow->loader, "eof", &eof, NULL);
+    if (eof) {
+      swfdec_loader_eof (SWFDEC_LOADER (slow));
+      slow->timeout_id = 0;
+      return FALSE;
+    } else {
+      return TRUE;
+    }
   }
 }
 
@@ -103,6 +107,7 @@ swfdec_slow_loader_initialize (SwfdecSlo
   if (size)
     swfdec_loader_set_size (SWFDEC_LOADER (slow), size);
   slow->timeout_id = g_timeout_add (slow->tick_time, swfdec_slow_loader_tick, slow);
+  swfdec_loader_open (SWFDEC_LOADER (slow), 0);
 }
 
 static void
diff-tree d0e4e10c1aa96552bcf2aa96af5949650870926b (from 5b36ea83a867d29e554cd2cfc1170f056c0fa52f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 16:34:36 2007 +0200

    remove hack for loader actions

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index b4df554..ab9d34a 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -633,8 +633,6 @@ swfdec_player_dispose (GObject *object)
   while (player->roots)
     swfdec_movie_destroy (player->roots->data);
 
-  swfdec_player_remove_all_actions (player, player); /* HACK to allow non-removable actions */
-
   /* we do this here so references to GC'd objects get freed */
   G_OBJECT_CLASS (swfdec_player_parent_class)->dispose (object);
 
diff-tree 5b36ea83a867d29e554cd2cfc1170f056c0fa52f (from de8205950a51b5bf5ad7645fb67eb9b9c21a0b4e)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 16:33:57 2007 +0200

    step 2 in loading reorg: SwfdecLoaderTarget
    
    SwfdecLoaderTarget now has 3 vfuncs: open, parse, eof and error.
    They are queued to be called whenever they were called on the loader.

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 285ffc2..cddbe10 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -244,11 +244,27 @@ swfdec_file_loader_init (SwfdecFileLoade
 static void
 swfdec_loader_perform_open (gpointer loaderp, gpointer unused)
 {
-  SWFDEC_FIXME ("add vfunc for open to SwfdecLoaderTarget");
+  SwfdecLoader *loader = loaderp;
+
+  swfdec_loader_target_open (loader->target, loader, loader->open_status);
+}
+
+static void
+swfdec_loader_perform_eof (gpointer loaderp, gpointer unused)
+{
+  SwfdecLoader *loader = loaderp;
+
+  swfdec_loader_target_eof (loader->target, loader);
+}
+
+static void
+swfdec_loader_perform_error (gpointer loaderp, gpointer unused)
+{
+  SwfdecLoader *loader = loaderp;
+
+  swfdec_loader_target_error (loader->target, loader);
 }
 
-#define swfdec_loader_perform_error swfdec_loader_perform_push
-#define swfdec_loader_perform_eof swfdec_loader_perform_push
 static void
 swfdec_loader_perform_push (gpointer loaderp, gpointer unused)
 {
diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c
index aa939b7..a6723b1 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -76,6 +76,21 @@ swfdec_loader_target_get_player (SwfdecL
 }
 
 void
+swfdec_loader_target_open (SwfdecLoaderTarget *target, SwfdecLoader *loader, guint status)
+{
+  SwfdecLoaderTargetInterface *iface;
+  
+  g_return_if_fail (SWFDEC_IS_LOADER_TARGET (target));
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+
+  SWFDEC_LOG ("opening %p (state %u)", loader, loader->state);
+
+  iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
+  if (iface->open)
+    iface->open (target, loader, status);
+}
+
+void
 swfdec_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *loader)
 {
   SwfdecLoaderTargetInterface *iface;
@@ -86,7 +101,37 @@ swfdec_loader_target_parse (SwfdecLoader
   SWFDEC_LOG ("parsing %p (state %u)", loader, loader->state);
 
   iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
-  g_return_if_fail (iface->parse != NULL);
-  iface->parse (target, loader);
+  if (iface->parse)
+    iface->parse (target, loader);
+}
+
+void
+swfdec_loader_target_eof (SwfdecLoaderTarget *target, SwfdecLoader *loader)
+{
+  SwfdecLoaderTargetInterface *iface;
+  
+  g_return_if_fail (SWFDEC_IS_LOADER_TARGET (target));
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+
+  SWFDEC_LOG ("eof on %p (state %u)", loader, loader->state);
+
+  iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
+  if (iface->eof)
+    iface->eof (target, loader);
+}
+
+void
+swfdec_loader_target_error (SwfdecLoaderTarget *target, SwfdecLoader *loader)
+{
+  SwfdecLoaderTargetInterface *iface;
+  
+  g_return_if_fail (SWFDEC_IS_LOADER_TARGET (target));
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+
+  SWFDEC_LOG ("error on %p (state %u)", loader, loader->state);
+
+  iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
+  if (iface->error)
+    iface->error (target, loader);
 }
 
diff --git a/libswfdec/swfdec_loadertarget.h b/libswfdec/swfdec_loadertarget.h
index 2d99869..81178c5 100644
--- a/libswfdec/swfdec_loadertarget.h
+++ b/libswfdec/swfdec_loadertarget.h
@@ -36,17 +36,32 @@ typedef struct _SwfdecLoaderTargetInterf
 struct _SwfdecLoaderTargetInterface {
   GTypeInterface	parent;
 
-  /* mandatory vfuncs */
+  /* mandatory vfunc */
   SwfdecPlayer *	(* get_player)      	(SwfdecLoaderTarget *	target);
+  /* optional vfuncs */
+  void			(* open)		(SwfdecLoaderTarget *   target,
+						 SwfdecLoader *		loader,
+						 guint			status);
   void			(* parse)		(SwfdecLoaderTarget *   target,
 						 SwfdecLoader *		loader);
+  void			(* eof)			(SwfdecLoaderTarget *   target,
+						 SwfdecLoader *		loader);
+  void			(* error)		(SwfdecLoaderTarget *   target,
+						 SwfdecLoader *		loader);
 };
 
 GType		swfdec_loader_target_get_type		(void) G_GNUC_CONST;
 
 SwfdecPlayer *	swfdec_loader_target_get_player		(SwfdecLoaderTarget *	target);
+void		swfdec_loader_target_open		(SwfdecLoaderTarget *	target,
+							 SwfdecLoader *		loader,
+							 guint			status);
 void		swfdec_loader_target_parse		(SwfdecLoaderTarget *	target,
 							 SwfdecLoader *		loader);
+void		swfdec_loader_target_eof		(SwfdecLoaderTarget *	target,
+							 SwfdecLoader *		loader);
+void		swfdec_loader_target_error		(SwfdecLoaderTarget *	target,
+							 SwfdecLoader *		loader);
 
 G_END_DECLS
 
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 2734ec6..6f266b7 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -193,6 +193,37 @@ swfdec_net_stream_loader_target_get_play
 }
 
 static void
+swfdec_net_stream_loader_target_error (SwfdecLoaderTarget *target, 
+    SwfdecLoader *loader)
+{
+  SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);
+
+  if (stream->flvdecoder == NULL)
+    swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Play_StreamNotFound,
+	SWFDEC_AS_STR_error);
+}
+
+static void
+swfdec_net_stream_loader_target_recheck (SwfdecNetStream *stream)
+{
+  if (stream->buffering) {
+    guint first, last;
+    if (swfdec_flv_decoder_get_video_info (stream->flvdecoder, &first, &last)) {
+      guint current = MAX (first, stream->current_time);
+      if (current + stream->buffer_time <= last) {
+	swfdec_net_stream_video_goto (stream, current);
+	stream->buffering = FALSE;
+	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?");
+    }
+  }
+  swfdec_net_stream_update_playing (stream);
+}
+
+static void
 swfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target, 
     SwfdecLoader *loader)
 {
@@ -200,12 +231,6 @@ swfdec_net_stream_loader_target_parse (S
   SwfdecDecoderClass *klass;
   gboolean recheck = FALSE;
   
-  if (loader->error) {
-    if (stream->flvdecoder == NULL)
-      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Play_StreamNotFound,
-	  SWFDEC_AS_STR_error);
-    return;
-  }
   if (loader->state != SWFDEC_LOADER_STATE_EOF && swfdec_buffer_queue_get_depth (loader->queue) == 0) {
     SWFDEC_INFO ("nothing to do");
     return;
@@ -246,45 +271,37 @@ swfdec_net_stream_loader_target_parse (S
     }
   }
 out:
-  if (loader->state == SWFDEC_LOADER_STATE_EOF) {
-    guint first, last;
-    swfdec_flv_decoder_eof (stream->flvdecoder);
-    recheck = TRUE;
-    swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Buffer_Flush,
+  if (recheck)
+    swfdec_net_stream_loader_target_recheck (stream);
+}
+
+static void
+swfdec_net_stream_loader_target_eof (SwfdecLoaderTarget *target, 
+    SwfdecLoader *loader)
+{
+  SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);
+  guint first, last;
+
+  swfdec_flv_decoder_eof (stream->flvdecoder);
+  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, SWFDEC_AS_STR_NetStream_Buffer_Full,
 	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, SWFDEC_AS_STR_NetStream_Buffer_Full,
-	  SWFDEC_AS_STR_status);
-    }
-  }
-  if (recheck) {
-    if (stream->buffering) {
-      guint first, last;
-      if (swfdec_flv_decoder_get_video_info (stream->flvdecoder, &first, &last)) {
-	guint current = MAX (first, stream->current_time);
-	if (current + stream->buffer_time <= last) {
-	  swfdec_net_stream_video_goto (stream, current);
-	  stream->buffering = FALSE;
-	  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?");
-      }
-    }
-    swfdec_net_stream_update_playing (stream);
   }
+  swfdec_net_stream_loader_target_recheck (stream);
 }
 
-
 static void
 swfdec_net_stream_loader_target_init (SwfdecLoaderTargetInterface *iface)
 {
   iface->get_player = swfdec_net_stream_loader_target_get_player;
   iface->parse = swfdec_net_stream_loader_target_parse;
+  iface->eof = swfdec_net_stream_loader_target_eof;
+  iface->error = swfdec_net_stream_loader_target_error;
 }
 
 /*** SWFDEC VIDEO MOVIE INPUT ***/
diff --git a/libswfdec/swfdec_swf_instance.c b/libswfdec/swfdec_swf_instance.c
index e21baf8..7f82971 100644
--- a/libswfdec/swfdec_swf_instance.c
+++ b/libswfdec/swfdec_swf_instance.c
@@ -79,8 +79,6 @@ swfdec_swf_instance_loader_target_parse 
   SwfdecDecoder *dec = instance->decoder;
   SwfdecDecoderClass *klass;
 
-  if (loader->error)
-    return;
   if (dec == NULL) {
     if (!swfdec_decoder_can_detect (loader->queue))
       return;
diff --git a/libswfdec/swfdec_xml.c b/libswfdec/swfdec_xml.c
index 1db087e..c418ca4 100644
--- a/libswfdec/swfdec_xml.c
+++ b/libswfdec/swfdec_xml.c
@@ -52,43 +52,49 @@ swfdec_xml_ondata (SwfdecXml *xml)
 }
 
 static void
-swfdec_xml_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *loader)
+swfdec_xml_loader_target_error (SwfdecLoaderTarget *target, SwfdecLoader *loader)
 {
   SwfdecXml *xml = SWFDEC_XML (target);
 
-  if (xml->loader != loader || loader->state <= SWFDEC_LOADER_STATE_READING)
-    return;
+  /* break reference to the loader */
+  swfdec_loader_set_target (loader, NULL);
+  xml->loader = NULL;
+  g_object_unref (loader);
+  /* emit onData */
+  swfdec_xml_ondata (xml);
+}
+
+static void
+swfdec_xml_loader_target_eof (SwfdecLoaderTarget *target, SwfdecLoader *loader)
+{
+  SwfdecXml *xml = SWFDEC_XML (target);
+  guint size;
 
   /* get the text from the loader */
-  if (loader->state == SWFDEC_LOADER_STATE_ERROR) {
-    /* nothing to do here */
-  } else {
-    guint size;
-    g_assert (loader->state == SWFDEC_LOADER_STATE_EOF);
-    swfdec_loader_set_data_type (loader, SWFDEC_LOADER_DATA_TEXT);
-    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);
+  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 */
+  swfdec_loader_set_target (loader, NULL);
   xml->loader = NULL;
   g_object_unref (loader);
   /* emit onData */
@@ -99,7 +105,8 @@ 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;
+  iface->eof = swfdec_xml_loader_target_eof;
+  iface->error = swfdec_xml_loader_target_error;
 }
 
 /*** SWFDEC_XML ***/
@@ -166,4 +173,5 @@ swfdec_xml_load (SwfdecXml *xml, const c
   swfdec_xml_reset (xml);
   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_set_data_type (xml->loader, SWFDEC_LOADER_DATA_TEXT);
 }
diff-tree de8205950a51b5bf5ad7645fb67eb9b9c21a0b4e (from 262fa2409436f429658cf14f03169bf0ebf277bf)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 15:59:45 2007 +0200

    s/g_print/SWFDEC_DEBUG/

diff --git a/libswfdec/swfdec_url.c b/libswfdec/swfdec_url.c
index d1ec4ec..47b7142 100644
--- a/libswfdec/swfdec_url.c
+++ b/libswfdec/swfdec_url.c
@@ -80,7 +80,7 @@ swfdec_url_new (const char *string)
 
   g_return_val_if_fail (string != NULL, NULL);
 
-  g_print ("%s\n", string);
+  SWFDEC_DEBUG ("new url: %s", string);
   url = g_slice_new0 (SwfdecURL);
   url->url = g_strdup (string);
   s = strstr (string, "://");
diff-tree 262fa2409436f429658cf14f03169bf0ebf277bf (from 49edc7f46d99b2f9da859511a0272dd63268c24d)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 15:59:06 2007 +0200

    first step in loader handling reord
    
    Loaders don't execute their code immediately now but instead call
    swfdec_player_add_external_action() to queue actions for later.

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 3ee70e4..285ffc2 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -105,7 +105,7 @@ swfdec_loader_get_property (GObject *obj
       g_value_set_string (value, loader->error);
       break;
     case PROP_EOF:
-      g_value_set_boolean (value, loader->eof);
+      g_value_set_boolean (value, loader->state == SWFDEC_LOADER_STATE_EOF);
       break;
     case PROP_DATA_TYPE:
       g_value_set_enum (value, loader->data_type);
@@ -132,10 +132,6 @@ swfdec_loader_set_property (GObject *obj
     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;
     case PROP_SIZE:
       if (loader->size == 0 && g_value_get_ulong (value) > 0)
 	swfdec_loader_set_size (loader, g_value_get_ulong (value));
@@ -224,6 +220,7 @@ swfdec_file_loader_load (SwfdecLoader *l
     g_error_free (error);
   } else {
     swfdec_loader_set_size (loader, buffer->length);
+    swfdec_loader_open (loader, 0);
     swfdec_loader_push (loader, buffer);
     swfdec_loader_eof (loader);
   }
@@ -244,6 +241,22 @@ swfdec_file_loader_init (SwfdecFileLoade
 
 /*** INTERNAL API ***/
 
+static void
+swfdec_loader_perform_open (gpointer loaderp, gpointer unused)
+{
+  SWFDEC_FIXME ("add vfunc for open to SwfdecLoaderTarget");
+}
+
+#define swfdec_loader_perform_error swfdec_loader_perform_push
+#define swfdec_loader_perform_eof swfdec_loader_perform_push
+static void
+swfdec_loader_perform_push (gpointer loaderp, gpointer unused)
+{
+  SwfdecLoader *loader = loaderp;
+
+  swfdec_loader_target_parse (loader->target, loader);
+}
+
 SwfdecLoader *
 swfdec_loader_load (SwfdecLoader *loader, const char *url,
     SwfdecLoaderRequest request, const char *data, gsize data_len)
@@ -276,29 +289,40 @@ swfdec_loader_set_target (SwfdecLoader *
   loader->target = target;
   if (target) {
     loader->player = swfdec_loader_target_get_player (target);
+    switch (loader->state) {
+      case SWFDEC_LOADER_STATE_NEW:
+	break;
+      case SWFDEC_LOADER_STATE_OPEN:
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_open, NULL);
+	break;
+      case SWFDEC_LOADER_STATE_READING:
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_open, NULL);
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_push, NULL);
+	break;
+      case SWFDEC_LOADER_STATE_EOF:
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_open, NULL);
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_push, NULL);
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_eof, NULL);
+	break;
+      case SWFDEC_LOADER_STATE_ERROR:
+	swfdec_player_add_external_action (loader->player, loader,
+	    swfdec_loader_perform_error, NULL);
+	break;
+      default:
+	g_assert_not_reached ();
+	break;
+    }
   } else {
     loader->player = NULL;
   }
 }
 
-static void
-swfdec_loader_do_parse (gpointer empty, gpointer loaderp)
-{
-  SwfdecLoader *loader = SWFDEC_LOADER (loaderp);
-
-  swfdec_loader_target_parse (loader->target, loader);
-}
-
-void
-swfdec_loader_queue_parse (SwfdecLoader *loader)
-{
-  g_return_if_fail (SWFDEC_IS_LOADER (loader));
-  g_return_if_fail (loader->target != NULL);
-
-  /* HACK: using player as action object makes them get auto-removed */
-  swfdec_player_add_action (loader->player, loader->player, swfdec_loader_do_parse, loader);
-}
-
 /** PUBLIC API ***/
 
 /**
@@ -346,6 +370,7 @@ swfdec_loader_new_from_file (const char 
     g_error_free (error);
   } else {
     swfdec_loader_set_size (loader, buf->length);
+    swfdec_loader_open (loader, 0);
     swfdec_loader_push (loader, buf);
     swfdec_loader_eof (loader);
   }
@@ -372,40 +397,33 @@ swfdec_loader_error (SwfdecLoader *loade
     return;
   }
 
-  if (loader->target) {
-    swfdec_player_lock (loader->player);
-    swfdec_loader_error_locked (loader, error);
-    swfdec_player_perform_actions (loader->player);
-    swfdec_player_unlock (loader->player);
-  } else {
-    swfdec_loader_error_locked (loader, error);
-  }
-}
-
-void
-swfdec_loader_error_locked (SwfdecLoader *loader, const char *error)
-{
-  if (loader->error)
-    return;
-
-  SWFDEC_WARNING ("error in %s %p: %s", G_OBJECT_TYPE_NAME (loader), loader, error);
+  loader->state = SWFDEC_LOADER_STATE_ERROR;
   loader->error = g_strdup (error);
-  g_object_notify (G_OBJECT (loader), "error");
   if (loader->target)
-    swfdec_loader_target_parse (loader->target, loader);
+    swfdec_player_add_external_action (loader->player, loader,
+	swfdec_loader_perform_error, NULL);
 }
 
+/**
+ * swfdec_loader_open:
+ * @loader: a #SwfdecLoader
+ * @status: HTTP state code when opening the connection or 0 if unknown or not
+ *          a HTTP connection.
+ *
+ * Call this function when your loader opened the resulting file. For HTTP this
+ * is when having received the headers. You must call this function before 
+ * swfdec_laoder_push() can be called.
+ **/
 void
-swfdec_loader_parse (SwfdecLoader *loader)
+swfdec_loader_open (SwfdecLoader *loader, guint status)
 {
-  if (loader->target == NULL ||
-      loader->error)
-    return;
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+  g_return_if_fail (loader->state == SWFDEC_LOADER_STATE_NEW);
 
-  swfdec_player_lock (loader->player);
-  swfdec_loader_target_parse (loader->target, loader);
-  swfdec_player_perform_actions (loader->player);
-  swfdec_player_unlock (loader->player);
+  loader->state = SWFDEC_LOADER_STATE_OPEN;
+  loader->open_status = status;
+  if (loader->player)
+    swfdec_player_add_external_action (loader->player, loader, swfdec_loader_perform_open, NULL);
 }
 
 /**
@@ -414,40 +432,46 @@ swfdec_loader_parse (SwfdecLoader *loade
  * @buffer: new data to make available. The loader takes the reference
  *          to the buffer.
  *
- * Makes the data in @buffer available to @loader and processes it.
+ * Makes the data in @buffer available to @loader and processes it. The @loader
+ * must be open.
  **/
 void
 swfdec_loader_push (SwfdecLoader *loader, SwfdecBuffer *buffer)
 {
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
-  g_return_if_fail (loader->eof == FALSE);
+  g_return_if_fail (loader->state == SWFDEC_LOADER_STATE_OPEN || loader->state == SWFDEC_LOADER_STATE_READING);
   g_return_if_fail (buffer != NULL);
 
   swfdec_buffer_queue_push (loader->queue, buffer);
   g_object_notify (G_OBJECT (loader), "loaded");
-  swfdec_loader_parse (loader);
+  loader->state = SWFDEC_LOADER_STATE_READING;
+  if (loader->player)
+    swfdec_player_add_external_action (loader->player, loader,
+	swfdec_loader_perform_push, NULL);
 }
 
 /**
  * swfdec_loader_eof:
  * @loader: a #SwfdecLoader
  *
- * Indicates to @loader that no more data will follow.
+ * Indicates to @loader that no more data will follow. The loader must be open.
  **/
 void
 swfdec_loader_eof (SwfdecLoader *loader)
 {
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
-  g_return_if_fail (loader->eof == FALSE);
+  g_return_if_fail (loader->state == SWFDEC_LOADER_STATE_OPEN || loader->state == SWFDEC_LOADER_STATE_READING);
 
-  loader->eof = TRUE;
   if (loader->size == 0) {
     gulong bytes = swfdec_loader_get_loaded (loader);
     if (bytes)
       swfdec_loader_set_size (loader, bytes);
   }
   g_object_notify (G_OBJECT (loader), "eof");
-  swfdec_loader_parse (loader);
+  loader->state = SWFDEC_LOADER_STATE_EOF;
+  if (loader->player)
+    swfdec_player_add_external_action (loader->player, loader,
+	swfdec_loader_perform_eof, NULL);
 }
 
 /**
diff --git a/libswfdec/swfdec_loader.h b/libswfdec/swfdec_loader.h
index 4ccc1fb..6bed2d2 100644
--- a/libswfdec/swfdec_loader.h
+++ b/libswfdec/swfdec_loader.h
@@ -56,10 +56,11 @@ struct _SwfdecLoader
   GObject		object;
 
   /*< private >*/
+  guint			state;		/* SwfdecLoaderState the loader is currently in */
   SwfdecURL *		url;		/* the URL for this loader in UTF-8 - must be set on creation */
+  guint			open_status;	/* HTTP status when opening or 0 if unknown */
   gulong		size;		/* number of bytes in stream or 0 if unknown */
-  gboolean		eof;		/* if we're in EOF already */
-  char *		error;		/* if there's an error (from parsing the loader) */
+  char *		error;		/* error message if in error state or NULL */
   gpointer		target;		/* SwfdecLoaderTarget that gets notified about loading progress */
   gpointer		player;		/* SwfdecPlayer belonging to target or %NULL */
   SwfdecBufferQueue *	queue;		/* SwfdecBufferQueue managing the input buffers */
@@ -81,6 +82,8 @@ GType		swfdec_loader_get_type		(void);
 
 SwfdecLoader *	swfdec_loader_new_from_file	(const char *	 	filename);
 
+void		swfdec_loader_open		(SwfdecLoader *		loader,
+						 guint			status);
 void		swfdec_loader_push		(SwfdecLoader *		loader,
 						 SwfdecBuffer *		buffer);
 void		swfdec_loader_eof		(SwfdecLoader *		loader);
diff --git a/libswfdec/swfdec_loader_internal.h b/libswfdec/swfdec_loader_internal.h
index 0b1840f..a6a477f 100644
--- a/libswfdec/swfdec_loader_internal.h
+++ b/libswfdec/swfdec_loader_internal.h
@@ -25,6 +25,14 @@
 
 G_BEGIN_DECLS
 
+typedef enum {
+  SWFDEC_LOADER_STATE_NEW = 0,		/* loader is new and has not been opened yet */
+  SWFDEC_LOADER_STATE_OPEN,		/* loader is opened and has got the HTTP headers */
+  SWFDEC_LOADER_STATE_READING,		/* loader has read some bytes of data and is still reading */
+  SWFDEC_LOADER_STATE_EOF,		/* swfdec_loader_eof() has been called */
+  SWFDEC_LOADER_STATE_ERROR		/* loader is in error state */
+} SwfdecLoaderState;
+
 typedef struct _SwfdecFileLoader SwfdecFileLoader;
 typedef struct _SwfdecFileLoaderClass SwfdecFileLoaderClass;
 
@@ -52,14 +60,10 @@ SwfdecLoader *		swfdec_loader_load		(Swf
 							 SwfdecLoaderRequest	request,
 							 const char *		data,
 							 gsize			data_len);
-void			swfdec_loader_parse		(SwfdecLoader *		loader);
-void			swfdec_loader_queue_parse	(SwfdecLoader *		loader);
 void			swfdec_loader_set_target	(SwfdecLoader *		loader,
 							 SwfdecLoaderTarget *	target);
 void			swfdec_loader_set_data_type	(SwfdecLoader *		loader,
 							 SwfdecLoaderDataType	type);
-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 f702f99..aa939b7 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -83,8 +83,7 @@ swfdec_loader_target_parse (SwfdecLoader
   g_return_if_fail (SWFDEC_IS_LOADER_TARGET (target));
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
 
-  SWFDEC_LOG ("parsing %p%s%s", loader,
-      loader->error ? " ERROR" : "", loader->eof ? " EOF" : "");
+  SWFDEC_LOG ("parsing %p (state %u)", loader, loader->state);
 
   iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target);
   g_return_if_fail (iface->parse != NULL);
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 3a2980d..a696967 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -1113,7 +1113,6 @@ swfdec_movie_load (SwfdecMovie *movie, c
 	    request, data, data_len);
 	g_assert (loader);
 	swfdec_player_add_level_from_loader (player, depth, loader, NULL);
-	swfdec_loader_queue_parse (loader);
       }
     } else {
       SWFDEC_ERROR ("%s does not specify a valid level", target);
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 9addf77..2734ec6 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -206,7 +206,7 @@ swfdec_net_stream_loader_target_parse (S
 	  SWFDEC_AS_STR_error);
     return;
   }
-  if (!loader->eof && swfdec_buffer_queue_get_depth (loader->queue) == 0) {
+  if (loader->state != SWFDEC_LOADER_STATE_EOF && swfdec_buffer_queue_get_depth (loader->queue) == 0) {
     SWFDEC_INFO ("nothing to do");
     return;
   }
@@ -246,7 +246,7 @@ swfdec_net_stream_loader_target_parse (S
     }
   }
 out:
-  if (loader->eof) {
+  if (loader->state == SWFDEC_LOADER_STATE_EOF) {
     guint first, last;
     swfdec_flv_decoder_eof (stream->flvdecoder);
     recheck = TRUE;
@@ -462,7 +462,6 @@ swfdec_net_stream_set_loader (SwfdecNetS
   if (loader) {
     g_object_ref (loader);
     swfdec_loader_set_target (loader, SWFDEC_LOADER_TARGET (stream));
-    swfdec_loader_queue_parse (loader);
   }
   swfdec_net_stream_set_playing (stream, TRUE);
 }
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index ef998f7..b4df554 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -650,6 +650,8 @@ swfdec_player_dispose (GObject *object)
   swfdec_ring_buffer_free (player->actions);
   g_assert (player->movies == NULL);
   g_assert (player->audio == NULL);
+  if (player->external_timeout.callback)
+    swfdec_player_remove_timeout (player, &player->external_timeout);
   if (player->rate) {
     swfdec_player_remove_timeout (player, &player->iterate_timeout);
   }
@@ -950,6 +952,7 @@ swfdec_player_do_advance (SwfdecPlayer *
   
   swfdec_player_lock (player);
   swfdec_player_perform_external_actions (player);
+  swfdec_player_perform_actions (player);
   target_time = player->time + SWFDEC_MSECS_TO_TICKS (msecs);
   SWFDEC_DEBUG ("advancing %u msecs (%u audio frames)", msecs, audio_samples);
 
@@ -1522,10 +1525,13 @@ swfdec_player_set_loader_with_variables 
   g_return_if_fail (player->roots == NULL);
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
 
+  swfdec_player_lock (player);
   player->loader = loader;
   g_object_ref (loader);
   swfdec_player_add_level_from_loader (player, 0, loader, variables);
-  swfdec_loader_parse (loader);
+  swfdec_player_perform_external_actions (player);
+  swfdec_player_perform_actions (player);
+  swfdec_player_unlock (player);
 }
 
 /**
diff --git a/libswfdec/swfdec_swf_instance.c b/libswfdec/swfdec_swf_instance.c
index e79ed95..e21baf8 100644
--- a/libswfdec/swfdec_swf_instance.c
+++ b/libswfdec/swfdec_swf_instance.c
@@ -86,7 +86,8 @@ swfdec_swf_instance_loader_target_parse 
       return;
     dec = swfdec_decoder_new (player, loader->queue);
     if (dec == NULL) {
-      swfdec_loader_error_locked (loader, "Unknown format");
+      SWFDEC_ERROR ("no decoder found");
+      swfdec_loader_set_target (loader, NULL);
       return;
     }
 
@@ -99,7 +100,7 @@ swfdec_swf_instance_loader_target_parse 
     } else {
       SWFDEC_FIXME ("implement handling of %s", G_OBJECT_TYPE_NAME (dec));
       g_object_unref (dec);
-      swfdec_loader_error_locked (loader, "Unknown format");
+      swfdec_loader_set_target (loader, NULL);
       return;
     }
     /* HACK for flv playback */
@@ -114,7 +115,8 @@ swfdec_swf_instance_loader_target_parse 
     SwfdecStatus status = klass->parse (dec);
     switch (status) {
       case SWFDEC_STATUS_ERROR:
-	swfdec_loader_error_locked (loader, "parsing error");
+	SWFDEC_ERROR ("parsing error");
+	swfdec_loader_set_target (loader, NULL);
 	return;
       case SWFDEC_STATUS_OK:
 	break;
diff --git a/libswfdec/swfdec_xml.c b/libswfdec/swfdec_xml.c
index a5b9e62..1db087e 100644
--- a/libswfdec/swfdec_xml.c
+++ b/libswfdec/swfdec_xml.c
@@ -56,16 +56,15 @@ swfdec_xml_loader_target_parse (SwfdecLo
 {
   SwfdecXml *xml = SWFDEC_XML (target);
 
-  if (xml->loader != loader ||
-      (!loader->eof && !loader->error))
+  if (xml->loader != loader || loader->state <= SWFDEC_LOADER_STATE_READING)
     return;
 
   /* get the text from the loader */
-  if (loader->error) {
+  if (loader->state == SWFDEC_LOADER_STATE_ERROR) {
     /* nothing to do here */
   } else {
     guint size;
-    g_assert (loader->eof);
+    g_assert (loader->state == SWFDEC_LOADER_STATE_EOF);
     swfdec_loader_set_data_type (loader, SWFDEC_LOADER_DATA_TEXT);
     size = swfdec_buffer_queue_get_depth (loader->queue);
     xml->text = g_try_malloc (size + 1);
@@ -167,5 +166,4 @@ swfdec_xml_load (SwfdecXml *xml, const c
   swfdec_xml_reset (xml);
   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-tree 49edc7f46d99b2f9da859511a0272dd63268c24d (from 2cbd14d42891bafe6319ca535c8dd0a9b0ac838e)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 04:06:52 2007 +0200

    refactor loader handling
    
    - require unsetting of target before disposing loader
    - make loader keep track of its player (so it can add actions there)

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 65081d5..3ee70e4 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -151,6 +151,8 @@ swfdec_loader_dispose (GObject *object)
 {
   SwfdecLoader *loader = SWFDEC_LOADER (object);
 
+  /* targets are supposed to keep a reference around */
+  g_assert (loader->target == NULL);
   swfdec_buffer_queue_unref (loader->queue);
   swfdec_url_free (loader->url);
   g_free (loader->error);
@@ -268,7 +270,15 @@ swfdec_loader_set_target (SwfdecLoader *
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
   g_return_if_fail (target == NULL || SWFDEC_IS_LOADER_TARGET (target));
 
+  if (loader->target) {
+    swfdec_player_remove_all_external_actions (loader->player, loader);
+  }
   loader->target = target;
+  if (target) {
+    loader->player = swfdec_loader_target_get_player (target);
+  } else {
+    loader->player = NULL;
+  }
 }
 
 static void
@@ -282,14 +292,11 @@ swfdec_loader_do_parse (gpointer empty, 
 void
 swfdec_loader_queue_parse (SwfdecLoader *loader)
 {
-  SwfdecPlayer *player;
-
   g_return_if_fail (SWFDEC_IS_LOADER (loader));
   g_return_if_fail (loader->target != NULL);
 
-  player = swfdec_loader_target_get_player (loader->target);
   /* HACK: using player as action object makes them get auto-removed */
-  swfdec_player_add_action (player, player, swfdec_loader_do_parse, loader);
+  swfdec_player_add_action (loader->player, loader->player, swfdec_loader_do_parse, loader);
 }
 
 /** PUBLIC API ***/
@@ -357,8 +364,6 @@ swfdec_loader_new_from_file (const char 
 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);
 
@@ -368,11 +373,10 @@ swfdec_loader_error (SwfdecLoader *loade
   }
 
   if (loader->target) {
-    player = swfdec_loader_target_get_player (loader->target);
-    swfdec_player_lock (player);
+    swfdec_player_lock (loader->player);
     swfdec_loader_error_locked (loader, error);
-    swfdec_player_perform_actions (player);
-    swfdec_player_unlock (player);
+    swfdec_player_perform_actions (loader->player);
+    swfdec_player_unlock (loader->player);
   } else {
     swfdec_loader_error_locked (loader, error);
   }
@@ -394,17 +398,14 @@ swfdec_loader_error_locked (SwfdecLoader
 void
 swfdec_loader_parse (SwfdecLoader *loader)
 {
-  SwfdecPlayer *player;
-
   if (loader->target == NULL ||
       loader->error)
     return;
 
-  player = swfdec_loader_target_get_player (loader->target);
-  swfdec_player_lock (player);
+  swfdec_player_lock (loader->player);
   swfdec_loader_target_parse (loader->target, loader);
-  swfdec_player_perform_actions (player);
-  swfdec_player_unlock (player);
+  swfdec_player_perform_actions (loader->player);
+  swfdec_player_unlock (loader->player);
 }
 
 /**
diff --git a/libswfdec/swfdec_loader.h b/libswfdec/swfdec_loader.h
index 9cc0a4e..4ccc1fb 100644
--- a/libswfdec/swfdec_loader.h
+++ b/libswfdec/swfdec_loader.h
@@ -61,6 +61,7 @@ struct _SwfdecLoader
   gboolean		eof;		/* if we're in EOF already */
   char *		error;		/* if there's an error (from parsing the loader) */
   gpointer		target;		/* SwfdecLoaderTarget that gets notified about loading progress */
+  gpointer		player;		/* SwfdecPlayer belonging to target or %NULL */
   SwfdecBufferQueue *	queue;		/* SwfdecBufferQueue managing the input buffers */
   SwfdecLoaderDataType	data_type;	/* type this stream is in (identified by swfdec) */
 };
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 2f993c3..9addf77 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -449,8 +449,10 @@ swfdec_net_stream_set_loader (SwfdecNetS
   g_return_if_fail (SWFDEC_IS_NET_STREAM (stream));
   g_return_if_fail (loader == NULL || SWFDEC_IS_LOADER (loader));
 
-  if (stream->loader)
+  if (stream->loader) {
+    swfdec_loader_set_target (stream->loader, NULL);
     g_object_unref (stream->loader);
+  }
   if (stream->flvdecoder) {
     g_object_unref (stream->flvdecoder);
     stream->flvdecoder = NULL;
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 15caea0..ef998f7 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -323,7 +323,7 @@ swfdec_player_perform_external_actions (
 
   /* we need to query the number of current actions so newly added ones aren't
    * executed in here */
-  for (i = swfdec_ring_buffer_get_size (player->external_actions); i > 0; i--) {
+  for (i = swfdec_ring_buffer_get_n_elements (player->external_actions); i > 0; i--) {
     action = swfdec_ring_buffer_pop (player->external_actions);
     g_assert (action != NULL);
     /* skip removed actions */
diff --git a/libswfdec/swfdec_swf_instance.c b/libswfdec/swfdec_swf_instance.c
index b45ef43..e79ed95 100644
--- a/libswfdec/swfdec_swf_instance.c
+++ b/libswfdec/swfdec_swf_instance.c
@@ -149,6 +149,7 @@ swfdec_swf_instance_dispose (GObject *ob
 {
   SwfdecSwfInstance *instance = SWFDEC_SWF_INSTANCE (object);
 
+  swfdec_loader_set_target (instance->loader, NULL);
   g_object_unref (instance->loader);
   if (instance->decoder) {
     g_object_unref (instance->decoder);
@@ -186,12 +187,14 @@ swfdec_swf_instance_new (SwfdecSpriteMov
 
   mov = SWFDEC_MOVIE (movie);
   swf = g_object_new (SWFDEC_TYPE_SWF_INSTANCE, NULL);
-  swf->loader = g_object_ref (loader);
-  swfdec_loader_set_target (loader, SWFDEC_LOADER_TARGET (swf));
+  /* set important variables */
+  swf->movie = movie;
   if (mov->swf)
     g_object_unref (mov->swf);
   mov->swf = swf;
-  swf->movie = movie;
+  /* set loader (that depends on those vars) */
+  swf->loader = g_object_ref (loader);
+  swfdec_loader_set_target (loader, SWFDEC_LOADER_TARGET (swf));
 
   return swf;
 }
diff --git a/libswfdec/swfdec_xml.c b/libswfdec/swfdec_xml.c
index 404ec38..a5b9e62 100644
--- a/libswfdec/swfdec_xml.c
+++ b/libswfdec/swfdec_xml.c
@@ -112,6 +112,7 @@ static void
 swfdec_xml_reset (SwfdecXml *xml)
 {
   if (xml->loader) {
+    swfdec_loader_set_target (xml->loader, NULL);
     g_object_unref (xml->loader);
     xml->loader = NULL;
   }
diff-tree 2cbd14d42891bafe6319ca535c8dd0a9b0ac838e (from e9b685648bc358610b38344ba67897401670f46c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 1 03:48:41 2007 +0200

    add support for "external actions"
    
    external actions are supposed to be actions that are initiated by outside
    happenings, such as resizing or data being pushed to the player. By queueing
    them inside the player instead of executing them immediately, we can get
    around infinite loops (loading error causing a new load causing a loading
    error causing...) as well as having a lot less entry points to the script
    engine. This makes it easier to call functions from callbacks, in particular
    from within debugger breakpoints.

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index f0e448f..15caea0 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -315,6 +315,88 @@ swfdec_player_do_action (SwfdecPlayer *p
   return TRUE;
 }
 
+static void
+swfdec_player_perform_external_actions (SwfdecPlayer *player)
+{
+  SwfdecPlayerAction *action;
+  guint i;
+
+  /* we need to query the number of current actions so newly added ones aren't
+   * executed in here */
+  for (i = swfdec_ring_buffer_get_size (player->external_actions); i > 0; i--) {
+    action = swfdec_ring_buffer_pop (player->external_actions);
+    g_assert (action != NULL);
+    /* skip removed actions */
+    if (action->object == NULL) 
+      continue;
+    action->func (action->object, action->data);
+  }
+
+  if (player->external_timeout.callback) {
+    swfdec_player_remove_timeout (player, &player->external_timeout);
+    player->external_timeout.callback = NULL;
+  }
+}
+
+static void
+swfdec_player_trigger_external_actions (SwfdecTimeout *advance)
+{
+  SwfdecPlayer *player = SWFDEC_PLAYER ((guint8 *) advance - G_STRUCT_OFFSET (SwfdecPlayer, external_timeout));
+
+  player->external_timeout.callback = NULL;
+  swfdec_player_perform_external_actions (player);
+}
+
+void
+swfdec_player_add_external_action (SwfdecPlayer *player, gpointer object, 
+    SwfdecActionFunc action_func, gpointer action_data)
+{
+  SwfdecPlayerAction *action;
+
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (action_func != NULL);
+
+  SWFDEC_LOG ("adding external action %p %p %p", object, action_func, action_data);
+  action = swfdec_ring_buffer_push (player->external_actions);
+  if (action == NULL) {
+    /* FIXME: limit number of actions to not get inf loops due to scripts? */
+    swfdec_ring_buffer_set_size (player->actions,
+	swfdec_ring_buffer_get_size (player->actions) + 16);
+    action = swfdec_ring_buffer_push (player->actions);
+    g_assert (action);
+  }
+  action->object = object;
+  action->func = action_func;
+  action->data = action_data;
+  if (!player->external_timeout.callback) {
+    /* trigger execution in 100 ms */
+    player->external_timeout.timestamp = player->time + SWFDEC_MSECS_TO_TICKS (100);
+    player->external_timeout.callback = swfdec_player_trigger_external_actions;
+    swfdec_player_add_timeout (player, &player->external_timeout);
+  }
+}
+
+void
+swfdec_player_remove_all_external_actions (SwfdecPlayer *player, gpointer object)
+{
+  SwfdecPlayerAction *action;
+  guint i;
+
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+  g_return_if_fail (object != NULL);
+
+  for (i = 0; i < swfdec_ring_buffer_get_n_elements (player->external_actions); i++) {
+    action = swfdec_ring_buffer_peek_nth (player->external_actions, i);
+
+    if (action->object == object) {
+      SWFDEC_LOG ("removing external action %p %p %p", 
+	  action->object, action->func, action->data);
+      action->object = NULL;
+    }
+  }
+}
+
 /*** SwfdecPlayer ***/
 
 enum {
@@ -867,6 +949,7 @@ swfdec_player_do_advance (SwfdecPlayer *
   guint frames_now;
   
   swfdec_player_lock (player);
+  swfdec_player_perform_external_actions (player);
   target_time = player->time + SWFDEC_MSECS_TO_TICKS (msecs);
   SWFDEC_DEBUG ("advancing %u msecs (%u audio frames)", msecs, audio_samples);
 
@@ -1161,6 +1244,7 @@ swfdec_player_init (SwfdecPlayer *player
   player->registered_classes = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   player->actions = swfdec_ring_buffer_new_for_type (SwfdecPlayerAction, 16);
+  player->external_actions = swfdec_ring_buffer_new_for_type (SwfdecPlayerAction, 8);
   player->cache = swfdec_cache_new (50 * 1024 * 1024); /* 100 MB */
   player->bgcolor = SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF);
 
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index 84946ff..cc9a384 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -106,6 +106,8 @@ struct _SwfdecPlayer
   /* iterating */
   GList *		movies;			/* list of all moveis that want to be iterated */
   SwfdecRingBuffer *	actions;		/* all actions we've queued up so far */
+  SwfdecRingBuffer *	external_actions;     	/* external actions we've queued up, like resize or loader stuff */
+  SwfdecTimeout		external_timeout;      	/* callback for iterating */
   GQueue *		init_queue;		/* all movies that require an init event */
   GQueue *		construct_queue;      	/* all movies that require an construct event */
 };
@@ -150,12 +152,21 @@ void		swfdec_player_add_timeout	(SwfdecP
 						 SwfdecTimeout *	timeout);
 void		swfdec_player_remove_timeout	(SwfdecPlayer *		player,
 						 SwfdecTimeout *	timeout);
+void		swfdec_player_add_external_action
+						(SwfdecPlayer *		player,
+						 gpointer		object,
+						 SwfdecActionFunc   	action_func,
+						 gpointer		action_data);
+void		swfdec_player_remove_all_external_actions
+						(SwfdecPlayer *      	player,
+						 gpointer		object);
 void		swfdec_player_add_action	(SwfdecPlayer *		player,
 						 gpointer		object,
 						 SwfdecActionFunc   	action_func,
 						 gpointer		action_data);
 void		swfdec_player_remove_all_actions (SwfdecPlayer *      	player,
 						 gpointer		object);
+
 void		swfdec_player_set_drag_movie	(SwfdecPlayer *		player,
 						 SwfdecMovie *		drag,
 						 gboolean		center,


More information about the Swfdec mailing list