Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / ext / gnomevfs / gstgnomevfssrc.c
index ef9ab74..59c2613 100644 (file)
@@ -117,9 +117,6 @@ enum
   ARG_IRADIO_TITLE
 };
 
-static void gst_gnome_vfs_src_base_init (gpointer g_class);
-static void gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass);
-static void gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc);
 static void gst_gnome_vfs_src_finalize (GObject * object);
 static void gst_gnome_vfs_src_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
@@ -132,7 +129,6 @@ static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id,
 static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src);
 static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src);
 static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_check_get_range (GstBaseSrc * src);
 static gboolean gst_gnome_vfs_src_unlock (GstBaseSrc * basesrc);
 static gboolean gst_gnome_vfs_src_unlock_stop (GstBaseSrc * basesrc);
 static gboolean gst_gnome_vfs_src_get_size (GstBaseSrc * src, guint64 * size);
@@ -140,67 +136,24 @@ static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc,
     guint64 offset, guint size, GstBuffer ** buffer);
 static gboolean gst_gnome_vfs_src_query (GstBaseSrc * src, GstQuery * query);
 
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_gnome_vfs_src_get_type (void)
-{
-  static GType gnomevfssrc_type = 0;
-
-  if (!gnomevfssrc_type) {
-    static const GTypeInfo gnomevfssrc_info = {
-      sizeof (GstGnomeVFSSrcClass),
-      gst_gnome_vfs_src_base_init,
-      NULL,
-      (GClassInitFunc) gst_gnome_vfs_src_class_init,
-      NULL,
-      NULL,
-      sizeof (GstGnomeVFSSrc),
-      0,
-      (GInstanceInitFunc) gst_gnome_vfs_src_init,
-    };
-    static const GInterfaceInfo urihandler_info = {
-      gst_gnome_vfs_src_uri_handler_init,
-      NULL,
-      NULL
-    };
-
-    gnomevfssrc_type =
-        g_type_register_static (GST_TYPE_BASE_SRC,
-        "GstGnomeVFSSrc", &gnomevfssrc_info, 0);
-    g_type_add_interface_static (gnomevfssrc_type, GST_TYPE_URI_HANDLER,
-        &urihandler_info);
-  }
-  return gnomevfssrc_type;
-}
-
-static void
-gst_gnome_vfs_src_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_set_details_simple (element_class,
-      "GnomeVFS Source", "Source/File",
-      "Read from any GnomeVFS-supported file",
-      "Bastien Nocera <hadess@hadess.net>, "
-      "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
-
-  GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0,
-      "Gnome-VFS Source");
-}
+#define gst_gnome_vfs_src_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstGnomeVFSSrc, gst_gnome_vfs_src, GST_TYPE_BASE_SRC,
+    G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
+        gst_gnome_vfs_src_uri_handler_init));
 
 static void
 gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbasesrc_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
+  GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0,
+      "Gnome-VFS Source");
 
   gobject_class->finalize = gst_gnome_vfs_src_finalize;
   gobject_class->set_property = gst_gnome_vfs_src_set_property;
@@ -242,6 +195,14 @@ gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass)
           "Name of currently playing song", NULL,
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_set_details_simple (gstelement_class,
+      "GnomeVFS Source", "Source/File",
+      "Read from any GnomeVFS-supported file",
+      "Bastien Nocera <hadess@hadess.net>, "
+      "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
+
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop);
   gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_unlock);
@@ -250,8 +211,6 @@ gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass)
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size);
   gstbasesrc_class->is_seekable =
       GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable);
-  gstbasesrc_class->check_get_range =
-      GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_check_get_range);
   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_create);
   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_query);
 }
@@ -609,8 +568,8 @@ gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
   GnomeVFSResult res;
   GstBuffer *buf;
   GnomeVFSFileSize readbytes;
-  guint8 *data;
-  guint todo;
+  guint8 *data, *ptr;
+  gsize todo;
   GstGnomeVFSSrc *src;
   gboolean interrupted = FALSE;
 
@@ -633,14 +592,15 @@ gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
     }
   }
 
-  buf = gst_buffer_try_new_and_alloc (size);
+  buf = gst_buffer_new_and_alloc (size);
   if (G_UNLIKELY (buf == NULL)) {
     GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
     return GST_FLOW_ERROR;
   }
 
-  data = GST_BUFFER_DATA (buf);
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
 
+  ptr = data;
   todo = size;
   while (!src->interrupted && todo > 0) {
     /* this can return less that we ask for */
@@ -653,7 +613,6 @@ gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
 
       /* Just take what we've so far gotten and return */
       size = size - todo;
-      GST_BUFFER_SIZE (buf) = size;
       todo = 0;
       interrupted = TRUE;
       break;
@@ -667,13 +626,14 @@ gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
       goto read_failed;
 
     if (readbytes < todo) {
-      data = &data[readbytes];
+      ptr += readbytes;
       todo -= readbytes;
     } else {
       todo = 0;
     }
     GST_LOG ("  got size %" G_GUINT64_FORMAT, readbytes);
   }
+  gst_buffer_unmap (buf, data, size);
 
   if (interrupted)
     goto interrupted;
@@ -702,6 +662,7 @@ cannot_seek:
   }
 read_failed:
   {
+    gst_buffer_unmap (buf, data, size);
     gst_buffer_unref (buf);
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
         ("Failed to read data: %s", gnome_vfs_result_to_string (res)));
@@ -714,6 +675,7 @@ interrupted:
   }
 eos:
   {
+    gst_buffer_unmap (buf, data, size);
     gst_buffer_unref (buf);
     GST_DEBUG_OBJECT (src, "Reading data gave EOS");
     return GST_FLOW_UNEXPECTED;
@@ -721,28 +683,6 @@ eos:
 }
 
 static gboolean
-gst_gnome_vfs_src_query (GstBaseSrc * basesrc, GstQuery * query)
-{
-  gboolean ret = FALSE;
-  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (basesrc);
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_URI:
-      gst_query_set_uri (query, src->uri_name);
-      ret = TRUE;
-      break;
-    default:
-      ret = FALSE;
-      break;
-  }
-
-  if (!ret)
-    ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
-
-  return ret;
-}
-
-static gboolean
 gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc)
 {
   GstGnomeVFSSrc *src;
@@ -753,48 +693,73 @@ gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc)
 }
 
 static gboolean
-gst_gnome_vfs_src_check_get_range (GstBaseSrc * basesrc)
+gst_gnome_vfs_src_scheduling (GstBaseSrc * basesrc, GstQuery * query)
 {
   GstGnomeVFSSrc *src;
   const gchar *protocol;
+  gboolean pull_mode;
 
   src = GST_GNOME_VFS_SRC (basesrc);
 
+  pull_mode = FALSE;
+
   if (src->uri == NULL) {
     GST_WARNING_OBJECT (src, "no URI set yet");
-    return FALSE;
+    goto undecided;
   }
 
   if (gnome_vfs_uri_is_local (src->uri)) {
     GST_LOG_OBJECT (src, "local URI (%s), assuming random access is possible",
         GST_STR_NULL (src->uri_name));
-    return TRUE;
-  }
-
-  /* blacklist certain protocols we know won't work getrange-based */
-  protocol = gnome_vfs_uri_get_scheme (src->uri);
-  if (protocol == NULL)
+    pull_mode = TRUE;
+  } else {
+    /* blacklist certain protocols we know won't work getrange-based */
+    protocol = gnome_vfs_uri_get_scheme (src->uri);
+    if (protocol == NULL)
+      goto undecided;
+
+    if (strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0) {
+      GST_LOG_OBJECT (src,
+          "blacklisted protocol '%s', no random access possible" " (URI=%s)",
+          protocol, GST_STR_NULL (src->uri_name));
+    } else {
+      GST_LOG_OBJECT (src, "undecided about URI '%s', let base class handle it",
+          GST_STR_NULL (src->uri_name));
+    }
     goto undecided;
-
-  if (strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0) {
-    GST_LOG_OBJECT (src, "blacklisted protocol '%s', no random access possible"
-        " (URI=%s)", protocol, GST_STR_NULL (src->uri_name));
-    return FALSE;
   }
+  gst_query_set_scheduling (query, pull_mode, pull_mode, FALSE, 1, -1, 1);
 
-  /* fall through to undecided */
+  return TRUE;
 
+  /* fall through to undecided */
 undecided:
   {
     /* don't know what to do, let the basesrc class decide for us */
-    GST_LOG_OBJECT (src, "undecided about URI '%s', let base class handle it",
-        GST_STR_NULL (src->uri_name));
+    return GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
+  }
+}
 
-    if (GST_BASE_SRC_CLASS (parent_class)->check_get_range)
-      return GST_BASE_SRC_CLASS (parent_class)->check_get_range (basesrc);
+static gboolean
+gst_gnome_vfs_src_query (GstBaseSrc * basesrc, GstQuery * query)
+{
+  gboolean ret = FALSE;
+  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (basesrc);
 
-    return FALSE;
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_URI:
+      gst_query_set_uri (query, src->uri_name);
+      ret = TRUE;
+      break;
+    case GST_QUERY_SCHEDULING:
+      ret = gst_gnome_vfs_src_scheduling (basesrc, query);
+      break;
+    default:
+      ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
+      break;
   }
+
+  return ret;
 }
 
 /* Interrupt a blocking request. */