[clutter-gst] video-texture: Initial support for download buffering



commit 3dd790bf657354c8e0d5846a6598efcfdfbb599e
Author: Damien Lespiau <damien lespiau intel com>
Date:   Mon Apr 4 16:43:15 2011 +0100

    video-texture: Initial support for download buffering
    
    This patch introduces new APIs to get and set the buffering mode. We
    still default to the old behaviour and people will have to opt in to use
    download buffering.
    
    VideoTexture sorts some details for you and exposes a download-buffering
    signal that is supposed to give the start and end of the current segment
    of downloaded data you're in. 'start' is always 0 for now.

 build/autotools/Makefile.am.marshal     |   52 +++++
 clutter-gst/.gitignore                  |    7 +-
 clutter-gst/Makefile.am                 |    7 +
 clutter-gst/clutter-gst-marshal.list    |    1 +
 clutter-gst/clutter-gst-video-texture.c |  315 +++++++++++++++++++++++++++++--
 clutter-gst/clutter-gst-video-texture.h |   50 ++++--
 configure.ac                            |    1 +
 doc/reference/clutter-gst-sections.txt  |    7 +-
 8 files changed, 409 insertions(+), 31 deletions(-)
---
diff --git a/build/autotools/Makefile.am.marshal b/build/autotools/Makefile.am.marshal
new file mode 100644
index 0000000..89d3222
--- /dev/null
+++ b/build/autotools/Makefile.am.marshal
@@ -0,0 +1,52 @@
+# Rules for generating marshal files using glib-genmarshal
+#
+# Define:
+# 	glib_marshal_list = marshal list file
+# 	glib_marshal_prefix = prefix for marshal functions
+#
+# before including Makefile.am.marshal. You will also need to have
+# the following targets already defined:
+#
+# 	CLEANFILES
+#	DISTCLEANFILES
+#	BUILT_SOURCES
+#	EXTRA_DIST
+#
+# Author: Emmanuele Bassi <ebassi linux intel com>
+
+# Basic sanity checks
+$(if $(GLIB_GENMARSHAL),,$(error Need to define GLIB_GENMARSHAL))
+
+$(if $(or $(glib_marshal_list), \
+          $(glib_marshal_prefix)),, \
+    $(error Need to define glib_marshal_list and glib_marshal_prefix))
+
+marshal_h = $(glib_marshal_list:.list=.h)
+marshal_c = $(glib_marshal_list:.list=.c)
+marshal_list = $(addprefix $(srcdir)/, $(glib_marshal_list))
+
+CLEANFILES += stamp-marshal
+DISTCLEANFILES += $(marshal_h) $(marshal_c)
+BUILT_SOURCES += $(marshal_h) $(marshal_c)
+EXTRA_DIST += $(marshal_list)
+
+stamp-marshal: $(marshal_list)
+	$(AM_V_GEN)$(GLIB_GENMARSHAL) \
+		--prefix=$(glib_marshal_prefix) \
+		--header \
+	$(marshal_list) > xgen-mh \
+	&& (cmp -s xgen-mh $(marshal_h) || cp -f xgen-mh $(marshal_h)) \
+	&& rm -f xgen-mh \
+	&& echo timestamp > $(@F)
+
+$(marshal_h): stamp-marshal
+	@true
+
+$(marshal_c): $(marshal_h)
+	$(AM_V_GEN)(echo "#include \"$(marshal_h)\"" ; \
+	$(GLIB_GENMARSHAL) \
+		--prefix=$(glib_marshal_prefix) \
+		--body \
+	$(marshal_list)) > xgen-mc \
+	&& cp xgen-mc $(marshal_c) \
+	&& rm -f xgen-mc
diff --git a/clutter-gst/.gitignore b/clutter-gst/.gitignore
index 6537c91..d9db007 100644
--- a/clutter-gst/.gitignore
+++ b/clutter-gst/.gitignore
@@ -1,4 +1,7 @@
-clutter-gst-version.h
-clutter-gst-enum-types.h
 clutter-gst-enum-types.c
+clutter-gst-enum-types.h
+clutter-gst-marshal.c
+clutter-gst-marshal.h
+clutter-gst-version.h
 stamp-enum-types
+stamp-marshal
diff --git a/clutter-gst/Makefile.am b/clutter-gst/Makefile.am
index 35bb60f..15e4122 100644
--- a/clutter-gst/Makefile.am
+++ b/clutter-gst/Makefile.am
@@ -15,6 +15,11 @@ glib_enum_c = clutter-gst-enum-types.c
 glib_enum_headers = $(source_h)
 include $(top_srcdir)/build/autotools/Makefile.am.enums
 
+# glib-genmarshal
+glib_marshal_list = clutter-gst-marshal.list
+glib_marshal_prefix = _clutter_gst_marshal
+include $(top_srcdir)/build/autotools/Makefile.am.marshal
+
 source_h = 					\
 	$(srcdir)/clutter-gst.h			\
 	$(srcdir)/clutter-gst-util.h		\
@@ -25,12 +30,14 @@ source_h = 					\
 
 source_priv_h =					\
 	$(srcdir)/clutter-gst-debug.h		\
+	$(srcdir)/clutter-gst-marshal.h		\
 	$(srcdir)/clutter-gst-private.h		\
 	$(srcdir)/clutter-gst-shaders.h		\
 	$(NULL)
 
 source_c = 					\
 	$(srcdir)/clutter-gst-debug.c		\
+	$(srcdir)/clutter-gst-marshal.c		\
 	$(srcdir)/clutter-gst-video-sink.c	\
 	$(srcdir)/clutter-gst-video-texture.c	\
         $(srcdir)/clutter-gst-util.c		\
diff --git a/clutter-gst/clutter-gst-marshal.list b/clutter-gst/clutter-gst-marshal.list
new file mode 100644
index 0000000..b9b8548
--- /dev/null
+++ b/clutter-gst/clutter-gst-marshal.list
@@ -0,0 +1 @@
+VOID:DOUBLE,DOUBLE
diff --git a/clutter-gst/clutter-gst-video-texture.c b/clutter-gst/clutter-gst-video-texture.c
index f60d34a..03d819e 100644
--- a/clutter-gst/clutter-gst-video-texture.c
+++ b/clutter-gst/clutter-gst-video-texture.c
@@ -48,11 +48,35 @@
 #include <gst/interfaces/streamvolume.h>
 
 #include "clutter-gst-debug.h"
-#include "clutter-gst-private.h"
 #include "clutter-gst-enum-types.h"
+#include "clutter-gst-marshal.h"
+#include "clutter-gst-private.h"
 #include "clutter-gst-video-sink.h"
 #include "clutter-gst-video-texture.h"
 
+/* Elements don't expose header files */
+typedef enum {
+  GST_PLAY_FLAG_VIDEO         = (1 << 0),
+  GST_PLAY_FLAG_AUDIO         = (1 << 1),
+  GST_PLAY_FLAG_TEXT          = (1 << 2),
+  GST_PLAY_FLAG_VIS           = (1 << 3),
+  GST_PLAY_FLAG_SOFT_VOLUME   = (1 << 4),
+  GST_PLAY_FLAG_NATIVE_AUDIO  = (1 << 5),
+  GST_PLAY_FLAG_NATIVE_VIDEO  = (1 << 6),
+  GST_PLAY_FLAG_DOWNLOAD      = (1 << 7),
+  GST_PLAY_FLAG_BUFFERING     = (1 << 8),
+  GST_PLAY_FLAG_DEINTERLACE   = (1 << 9)
+} GstPlayFlags;
+
+enum
+{
+  DOWNLOAD_BUFFERING,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
 struct _ClutterGstVideoTexturePrivate
 {
   GstElement *pipeline;
@@ -63,6 +87,12 @@ struct _ClutterGstVideoTexturePrivate
   guint in_seek : 1;
   guint is_idle : 1;
   guint is_changing_uri : 1;
+  guint in_download_buffering : 1;
+
+  /* when in progressive download, we use the buffer-fill property to signal
+   * that we have enough data to play the stream. This flag allows to send
+   * the notify that buffer-fill is 1.0 only once */
+  guint virtual_stream_buffer_signalled : 1;
 
   gdouble stacked_progress;
 
@@ -70,6 +100,7 @@ struct _ClutterGstVideoTexturePrivate
   GstState target_state;
 
   guint tick_timeout_id;
+  guint buffering_timeout_id;
 
   /* width / height (in pixels) of the frame data before applying the pixel
    * aspect ratio */
@@ -95,6 +126,8 @@ struct _ClutterGstVideoTexturePrivate
   CoglColor idle_color_unpre;
 
   GstSeekFlags seek_flags;    /* flags for the seek in set_progress(); */
+
+  GstElement *download_buffering_element;
 };
 
 enum {
@@ -116,8 +149,9 @@ enum {
   PROP_SEEK_FLAGS
 };
 
-
-#define TICK_TIMEOUT 0.5
+/* idle timeouts (in ms) */
+#define TICK_TIMEOUT        500
+#define BUFFERING_TIMEOUT   250
 
 static void clutter_media_init (ClutterMediaIface *iface);
 
@@ -147,6 +181,135 @@ gst_state_to_string (GstState state)
   return "Unknown state";
 }
 
+static void configure_buffering_timeout (ClutterGstVideoTexture *video_texture,
+                                         guint                   ms);
+static void
+clear_download_buffering (ClutterGstVideoTexture *video_texture)
+{
+  ClutterGstVideoTexturePrivate *priv = video_texture->priv;
+
+  if (priv->download_buffering_element)
+    {
+      g_object_unref (priv->download_buffering_element);
+      priv->download_buffering_element = NULL;
+    }
+  configure_buffering_timeout (video_texture, 0);
+  priv->in_download_buffering = FALSE;
+  priv->virtual_stream_buffer_signalled = 0;
+}
+
+static gboolean
+buffering_timeout (gpointer data)
+{
+  ClutterGstVideoTexture *video_texture = CLUTTER_GST_VIDEO_TEXTURE (data);
+  ClutterGstVideoTexturePrivate *priv = video_texture->priv;
+  gdouble start_d, stop_d, seconds_buffered;
+  gint64 start, stop, left;
+  GstState current_state;
+  GstElement *element;
+  GstQuery *query;
+  gboolean res;
+
+  element = priv->download_buffering_element;
+  if (element == NULL)
+    element = priv->pipeline;
+
+  /* queue2 only knows about _PERCENT and _BYTES */
+  query = gst_query_new_buffering (GST_FORMAT_PERCENT);
+  res = gst_element_query (element, query);
+
+  if (res == FALSE)
+    {
+      priv->buffering_timeout_id = 0;
+      clear_download_buffering (video_texture);
+      return FALSE;
+    }
+
+  /* signal the current range */
+  gst_query_parse_buffering_stats (query, NULL, NULL, NULL, &left);
+  gst_query_parse_buffering_range (query, NULL, &start, &stop, NULL);
+
+  CLUTTER_GST_NOTE (BUFFERING,
+                    "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT
+                    ", buffering left %" G_GINT64_FORMAT, start, stop, left);
+
+  start_d = (gdouble) start / GST_FORMAT_PERCENT_MAX;
+  stop_d = (gdouble) stop / GST_FORMAT_PERCENT_MAX;
+
+  g_signal_emit (video_texture,
+                 signals[DOWNLOAD_BUFFERING], 0, start_d, stop_d);
+
+  /* handle the "virtual stream buffer" and the associated pipeline state.
+   * We pause the pipeline until 2s of content is buffered. With the current
+   * implementation of queue2, start is always 0, so even when we seek in
+   * the stream the start position of the download-buffering signal is
+   * always 0.0. FIXME: look at gst_query_parse_nth_buffering_range () */
+  seconds_buffered = priv->duration * (stop_d - start_d);
+  priv->buffer_fill = seconds_buffered / 2.0;
+  priv->buffer_fill = CLAMP (priv->buffer_fill, 0.0, 1.0);
+
+  if (priv->buffer_fill != 1.0 || !priv->virtual_stream_buffer_signalled)
+    {
+      CLUTTER_GST_NOTE (BUFFERING, "buffer holds %0.2fs of data, buffer-fill "
+                        "is %.02f", seconds_buffered, priv->buffer_fill);
+
+      g_object_notify (G_OBJECT (video_texture), "buffer-fill");
+
+      if (priv->buffer_fill == 1.0)
+        priv->virtual_stream_buffer_signalled = 1;
+    }
+
+  gst_element_get_state (priv->pipeline, &current_state, NULL, 0);
+  if (priv->buffer_fill < 1.0)
+    {
+      if (current_state != GST_STATE_PAUSED)
+        {
+          CLUTTER_GST_NOTE (BUFFERING, "pausing the pipeline");
+          gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+        }
+    }
+  else
+    {
+      if (current_state != priv->target_state)
+        {
+          CLUTTER_GST_NOTE (BUFFERING, "restoring the pipeline");
+          gst_element_set_state (priv->pipeline, priv->target_state);
+        }
+    }
+
+  /* the file has finished downloading */
+  if (left == G_GINT64_CONSTANT (0))
+    {
+      priv->buffering_timeout_id = 0;
+
+      clear_download_buffering (video_texture);
+      gst_query_unref (query);
+      return FALSE;
+    }
+
+  gst_query_unref (query);
+  return TRUE;
+}
+
+static void
+configure_buffering_timeout (ClutterGstVideoTexture *video_texture,
+                             guint                   ms)
+{
+  ClutterGstVideoTexturePrivate *priv = video_texture->priv;
+
+  if (priv->buffering_timeout_id)
+    {
+      g_source_remove (priv->buffering_timeout_id);
+      priv->buffering_timeout_id = 0;
+    }
+
+  if (ms)
+    {
+      priv->buffering_timeout_id =
+        g_timeout_add (ms, buffering_timeout, video_texture);
+    }
+}
+
 /* Clutter 1.4 has this symbol, we don't want to depend on 1.4 just for that
  * just yet */
 static void
@@ -381,21 +544,37 @@ set_uri (ClutterGstVideoTexture *video_texture,
       if (priv->tick_timeout_id == 0)
         {
           priv->tick_timeout_id =
-            g_timeout_add (TICK_TIMEOUT * 1000, tick_timeout, self);
+            g_timeout_add (TICK_TIMEOUT, tick_timeout, self);
         }
 
       /* try to load subtitles based on the uri of the file */
       autoload_subtitle (video_texture, uri);
+
+      /* reset the states of download buffering */
+      clear_download_buffering (video_texture);
     }
   else
     {
       priv->uri = NULL;
 
-      if (priv->tick_timeout_id != 0)
+      if (priv->tick_timeout_id)
 	{
 	  g_source_remove (priv->tick_timeout_id);
 	  priv->tick_timeout_id = 0;
 	}
+
+      if (priv->buffering_timeout_id)
+        {
+          g_source_remove (priv->buffering_timeout_id);
+          priv->buffering_timeout_id = 0;
+        }
+
+      if (priv->download_buffering_element)
+        {
+          g_object_unref (priv->download_buffering_element);
+          priv->download_buffering_element = NULL;
+        }
+
     }
 
   priv->can_seek = FALSE;
@@ -464,7 +643,7 @@ set_playing (ClutterGstVideoTexture *video_texture,
   else
     {
       if (playing)
-	g_warning ("Unable to start playing: no URI is set");
+       g_warning ("Unable to start playing: no URI is set");
     }
 
   g_object_notify (G_OBJECT (video_texture), "playing");
@@ -508,6 +687,13 @@ set_progress (ClutterGstVideoTexture *video_texture,
 
   priv->target_progress = progress;
 
+  if (priv->in_download_buffering)
+    {
+      /* we clear the virtual_stream_buffer_signalled flag as it's likely we
+       * need to buffer again */
+      priv->virtual_stream_buffer_signalled = 0;
+    }
+
   if (priv->in_seek || priv->is_idle || priv->is_changing_uri)
     {
       /* We can't seek right now, let's save the position where we
@@ -916,19 +1102,15 @@ clutter_gst_video_texture_dispose (GObject *object)
   /* FIXME: flush an errors off bus ? */
   /* gst_bus_set_flushing (priv->bus, TRUE); */
 
+  /* start by doing the usual clean up when not wanting to play an URI */
+  set_uri (self, NULL);
+
   if (priv->pipeline)
     {
-      gst_element_set_state (priv->pipeline, GST_STATE_NULL);
       gst_object_unref (GST_OBJECT (priv->pipeline));
       priv->pipeline = NULL;
     }
 
-  if (priv->tick_timeout_id > 0)
-    {
-      g_source_remove (priv->tick_timeout_id);
-      priv->tick_timeout_id = 0;
-    }
-
   G_OBJECT_CLASS (clutter_gst_video_texture_parent_class)->dispose (object);
 }
 
@@ -1146,6 +1328,25 @@ clutter_gst_video_texture_class_init (ClutterGstVideoTextureClass *klass)
                               CLUTTER_GST_SEEK_FLAG_NONE,
                               CLUTTER_GST_PARAM_READWRITE);
   g_object_class_install_property (object_class, PROP_SEEK_FLAGS, pspec);
+
+  /**
+   * ClutterGstVideoTexture::download-buffering:
+   * @start: Start of the buffer (between 0.0 and 1.0)
+   * @stop: End of the buffer (between 0.0 and 1.0)
+   *
+   * When streaming, GStreamer can cache the data in a buffer on the disk,
+   * something called progressive download or download buffering. This signal
+   * is fired when this streaming mode.
+   */
+  signals[DOWNLOAD_BUFFERING] =
+    g_signal_new ("download-buffering",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterGstVideoTextureClass,
+                                   download_buffering),
+                  NULL, NULL,
+                  _clutter_gst_marshal_VOID__DOUBLE_DOUBLE,
+                  G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
 }
 
 static void
@@ -1196,6 +1397,9 @@ bus_message_buffering_cb (GstBus                 *bus,
 
   gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL);
 
+  if (mode != GST_BUFFERING_DOWNLOAD)
+    priv->in_download_buffering = FALSE;
+
   switch (mode)
     {
     case GST_BUFFERING_STREAM:
@@ -1230,6 +1434,30 @@ bus_message_buffering_cb (GstBus                 *bus,
       break;
 
     case GST_BUFFERING_DOWNLOAD:
+      /* we rate limit the messages from GStreamer for a usage in a UI (we
+       * don't want *that* many updates). This is done by installing an idle
+       * handler querying the buffer range and sending a signal from there */
+
+      if (priv->in_download_buffering)
+        break;
+
+      /* install the querying idle handler the first time we receive a download
+       * buffering message */
+      configure_buffering_timeout (video_texture, BUFFERING_TIMEOUT);
+
+      /* pause the stream. the idle timeout will set the target state when
+       * having received enough data. We'll use buffer_fill as a "virtual
+       * stream buffer" to signal the application we're buffering until we
+       * can play back from the downloaded stream. */
+      gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+      priv->buffer_fill = 0.0;
+      g_object_notify (G_OBJECT (video_texture), "buffer-fill");
+
+      priv->download_buffering_element = g_object_ref (message->src);
+      priv->in_download_buffering = TRUE;
+      priv->virtual_stream_buffer_signalled = 0;
+      break;
+
     case GST_BUFFERING_TIMESHIFT:
     case GST_BUFFERING_LIVE:
     default:
@@ -1458,6 +1686,7 @@ clutter_gst_video_texture_init (ClutterGstVideoTexture *video_texture)
   priv->is_idle = TRUE;
   priv->in_seek = FALSE;
   priv->is_changing_uri = FALSE;
+  priv->in_download_buffering = FALSE;
 
   priv->par_n = priv->par_d = 1;
 
@@ -1730,3 +1959,63 @@ clutter_gst_video_texture_set_seek_flags (ClutterGstVideoTexture *texture,
   else if (flags & CLUTTER_GST_SEEK_FLAG_ACCURATE)
     priv->seek_flags = GST_SEEK_FLAG_ACCURATE;
 }
+
+/**
+ * clutter_gst_video_texture_get_buffering_mode:
+ * @texture: a #ClutterGstVideoTexture
+ *
+ * Return value: a #ClutterGstBufferingMode
+ *
+ * Since: 1.4
+ */
+ClutterGstBufferingMode
+clutter_gst_video_texture_get_buffering_mode (ClutterGstVideoTexture *texture)
+{
+  ClutterGstVideoTexturePrivate *priv;
+  GstPlayFlags flags;
+
+  g_return_val_if_fail (CLUTTER_GST_IS_VIDEO_TEXTURE (texture),
+                        CLUTTER_GST_BUFFERING_MODE_STREAM);
+  priv = texture->priv;
+
+  g_object_get (G_OBJECT (priv->pipeline), "flags", &flags, NULL);
+  if (flags & GST_PLAY_FLAG_DOWNLOAD)
+    return CLUTTER_GST_BUFFERING_MODE_DOWNLOAD;
+
+  return CLUTTER_GST_BUFFERING_MODE_STREAM;
+}
+
+/**
+ * clutter_gst_video_texture_set_buffering_mode:
+ * @texture: a #ClutterGstVideoTexture
+ * @mode: a #ClutterGstBufferingMode
+ *
+ * Since: 1.4
+ */
+void
+clutter_gst_video_texture_set_buffering_mode (ClutterGstVideoTexture *texture,
+                                              ClutterGstBufferingMode mode)
+{
+  ClutterGstVideoTexturePrivate *priv;
+  GstPlayFlags flags;
+
+  g_return_if_fail (CLUTTER_GST_IS_VIDEO_TEXTURE (texture));
+  priv = texture->priv;
+
+  g_object_get (G_OBJECT (priv->pipeline), "flags", &flags, NULL);
+
+  switch (mode)
+    {
+    case CLUTTER_GST_BUFFERING_MODE_STREAM:
+      flags &= ~GST_PLAY_FLAG_DOWNLOAD;
+      break;
+    case CLUTTER_GST_BUFFERING_MODE_DOWNLOAD:
+      flags |= GST_PLAY_FLAG_DOWNLOAD;
+      break;
+    default:
+      g_warning ("Unexpected buffering mode %d", mode);
+      break;
+    }
+
+  g_object_set (G_OBJECT (priv->pipeline), "flags", flags, NULL);
+}
diff --git a/clutter-gst/clutter-gst-video-texture.h b/clutter-gst/clutter-gst-video-texture.h
index ae33319..05fc58b 100644
--- a/clutter-gst/clutter-gst-video-texture.h
+++ b/clutter-gst/clutter-gst-video-texture.h
@@ -76,6 +76,21 @@ typedef enum _ClutterGstSeekFlags
   CLUTTER_GST_SEEK_FLAG_ACCURATE = 1 << 0
 } ClutterGstSeekFlags;
 
+/**
+ * ClutterGstBufferingMode:
+ * @CLUTTER_GST_BUFFERING_MODE_STREAM: In-memory buffering
+ * @CLUTTER_GST_BUFFERING_MODE_DOWNLOAD: On-disk buffering
+ *
+ * Different buffering policies clutter-gst supports
+ *
+ * Since: 1.4
+ */
+typedef enum _ClutterGstBufferingMode
+{
+  CLUTTER_GST_BUFFERING_MODE_STREAM,
+  CLUTTER_GST_BUFFERING_MODE_DOWNLOAD
+} ClutterGstBufferingMode;
+
 typedef struct _ClutterGstVideoTexture        ClutterGstVideoTexture;
 typedef struct _ClutterGstVideoTextureClass   ClutterGstVideoTextureClass;
 typedef struct _ClutterGstVideoTexturePrivate ClutterGstVideoTexturePrivate;
@@ -106,7 +121,9 @@ struct _ClutterGstVideoTextureClass
   ClutterTextureClass parent_class;
 
   /* Future padding */
-  void (* _clutter_reserved1) (void);
+  void (* download_buffering) (ClutterGstVideoTexture *video_texture,
+			       gdouble                 start,
+			       gdouble                 stop);
   void (* _clutter_reserved2) (void);
   void (* _clutter_reserved3) (void);
   void (* _clutter_reserved4) (void);
@@ -114,20 +131,23 @@ struct _ClutterGstVideoTextureClass
   void (* _clutter_reserved6) (void);
 };
 
-GType               clutter_gst_video_texture_get_type            (void) G_GNUC_CONST;
-ClutterActor *      clutter_gst_video_texture_new                 (void);
-
-GstElement *        clutter_gst_video_texture_get_pipeline        (ClutterGstVideoTexture *texture);
-
-CoglHandle          clutter_gst_video_texture_get_idle_material   (ClutterGstVideoTexture *texture);
-void                clutter_gst_video_texture_set_idle_material   (ClutterGstVideoTexture *texture,
-                                                                   CoglHandle              material);
-gchar *             clutter_gst_video_texture_get_user_agent      (ClutterGstVideoTexture *texture);
-void                clutter_gst_video_texture_set_user_agent      (ClutterGstVideoTexture *texture,
-                                                                   const gchar *           user_agent);
-ClutterGstSeekFlags clutter_gst_video_texture_get_seek_flags      (ClutterGstVideoTexture *texture);
-void                clutter_gst_video_texture_set_seek_flags      (ClutterGstVideoTexture *texture,
-                                                                   ClutterGstSeekFlags     flags);
+GType			  clutter_gst_video_texture_get_type            (void) G_GNUC_CONST;
+ClutterActor *		  clutter_gst_video_texture_new                 (void);
+
+GstElement *		  clutter_gst_video_texture_get_pipeline        (ClutterGstVideoTexture *texture);
+
+CoglHandle		  clutter_gst_video_texture_get_idle_material   (ClutterGstVideoTexture *texture);
+void			  clutter_gst_video_texture_set_idle_material   (ClutterGstVideoTexture *texture,
+									 CoglHandle              material);
+gchar *			  clutter_gst_video_texture_get_user_agent      (ClutterGstVideoTexture *texture);
+void			  clutter_gst_video_texture_set_user_agent      (ClutterGstVideoTexture *texture,
+									 const gchar *           user_agent);
+ClutterGstSeekFlags	  clutter_gst_video_texture_get_seek_flags      (ClutterGstVideoTexture *texture);
+void			  clutter_gst_video_texture_set_seek_flags      (ClutterGstVideoTexture *texture,
+									 ClutterGstSeekFlags     flags);
+ClutterGstBufferingMode	  clutter_gst_video_texture_get_buffering_mode	(ClutterGstVideoTexture *texture);
+void			  clutter_gst_video_texture_set_buffering_mode	(ClutterGstVideoTexture *texture,
+									 ClutterGstBufferingMode mode);
 
 G_END_DECLS
 
diff --git a/configure.ac b/configure.ac
index 2e2b980..d44f567 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,7 @@ AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 DOLT
 AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums])
+AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal])
 
 # Checks for header files.
 AC_HEADER_STDC
diff --git a/doc/reference/clutter-gst-sections.txt b/doc/reference/clutter-gst-sections.txt
index b88d287..dedb149 100644
--- a/doc/reference/clutter-gst-sections.txt
+++ b/doc/reference/clutter-gst-sections.txt
@@ -2,6 +2,7 @@
 <FILE>clutter-gst-video-texture</FILE>
 <TITLE>ClutterGstVideoTexture</TITLE>
 ClutterGstSeekFlags
+ClutterGstBufferingMode
 ClutterGstVideoTexture
 ClutterGstVideoTextureClass
 clutter_gst_video_texture_new
@@ -12,8 +13,13 @@ clutter_gst_video_texture_get_user_agent
 clutter_gst_video_texture_set_user_agent
 clutter_gst_video_texture_set_seek_flags
 clutter_gst_video_texture_get_seek_flags
+clutter_gst_video_texture_get_buffering_mode
+clutter_gst_video_texture_set_buffering_mode
 <SUBSECTION Standard>
 clutter_gst_seek_flags_get_type
+CLUTTER_GST_TYPE_SEEK_FLAGS
+clutter_gst_buffering_mode_get_type
+CLUTTER_GST_TYPE_BUFFERING_MODE
 CLUTTER_GST_VIDEO_TEXTURE
 CLUTTER_GST_IS_VIDEO_TEXTURE
 CLUTTER_GST_TYPE_VIDEO_TEXTURE
@@ -32,7 +38,6 @@ ClutterGstVideoSink
 ClutterGstVideoSinkClass
 clutter_gst_video_sink_new
 <SUBSECTION Standard>
-CLUTTER_GST_TYPE_SEEK_FLAGS
 CLUTTER_GST_VIDEO_SINK
 CLUTTER_GST_IS_VIDEO_SINK
 CLUTTER_GST_TYPE_VIDEO_SINK



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]