implement URI schemes
authorBenjamin Otte <otte@gnome.org>
Mon, 24 Nov 2003 03:21:54 +0000 (03:21 +0000)
committerBenjamin Otte <otte@gnome.org>
Mon, 24 Nov 2003 03:21:54 +0000 (03:21 +0000)
Original commit message from CVS:
implement URI schemes
Elements can now register as a source or sink for a protocol and applications can use gst_element_make_from_uri () to get an element that handles a given URI.
This patch provides:
- removal of old broken URI handling scheme.
- new URI handling using interfaces.
- updates for registry to save handled URIs.
- interface for URI handlers.
- implementation of that in filesrc and filesink for the file:// URI
- extension to pipeline parsing to allow specifying only a URI instead of element

Does not include:
- tests
- inclusion in docs build

24 files changed:
docs/gst/tmpl/gstreamer-unused.sgml
docs/gst/tmpl/gsturi.sgml
gst/elements/gstfakesink.c
gst/elements/gstfilesink.c
gst/elements/gstfilesink.h
gst/elements/gstfilesrc.c
gst/elements/gstfilesrc.h
gst/gstelement.h
gst/gstelementfactory.c
gst/gstpluginfeature.c
gst/gstpluginfeature.h
gst/gsturi.c
gst/gsturi.h
gst/parse/grammar.y
gst/parse/parse.l
gst/parse/types.h
gst/registries/gstxmlregistry.c
plugins/elements/gstfakesink.c
plugins/elements/gstfilesink.c
plugins/elements/gstfilesink.h
plugins/elements/gstfilesrc.c
plugins/elements/gstfilesrc.h
tools/gst-inspect.c
tools/gst-xmlinspect.c

index 7110bc5..0cad7ce 100644 (file)
@@ -10248,6 +10248,15 @@ Destroy the scheduler
 @parent: 
 @Returns: 
 
+<!-- ##### FUNCTION gst_uri_handler_create ##### -->
+<para>
+
+</para>
+
+@handler: 
+@name: 
+@Returns: 
+
 <!-- ##### FUNCTION gst_uri_handler_destroy ##### -->
 <para>
 
@@ -10255,6 +10264,43 @@ Destroy the scheduler
 
 @handler: 
 
+<!-- ##### FUNCTION gst_uri_handler_find ##### -->
+<para>
+
+</para>
+
+@name: 
+@Returns: 
+
+<!-- ##### FUNCTION gst_uri_handler_find_by_uri ##### -->
+<para>
+
+</para>
+
+@uri: 
+@Returns: 
+
+<!-- ##### FUNCTION gst_uri_handler_make_by_uri ##### -->
+<para>
+
+</para>
+
+@uri: 
+@name: 
+@Returns: 
+
+<!-- ##### FUNCTION gst_uri_handler_new ##### -->
+<para>
+
+</para>
+
+@name: 
+@uri: 
+@longdesc: 
+@element: 
+@property: 
+@Returns: 
+
 <!-- ##### FUNCTION gst_util_get_bool_arg ##### -->
 <para>
 
index 603da64..1488c3d 100644 (file)
@@ -15,54 +15,3 @@ and the element property that can handle a given URI.
 
 </para>
 
-<!-- ##### FUNCTION gst_uri_handler_new ##### -->
-<para>
-
-</para>
-
-@name: 
-@uri: 
-@longdesc: 
-@element: 
-@property: 
-@Returns: 
-
-
-<!-- ##### FUNCTION gst_uri_handler_find ##### -->
-<para>
-
-</para>
-
-@name: 
-@Returns: 
-
-
-<!-- ##### FUNCTION gst_uri_handler_find_by_uri ##### -->
-<para>
-
-</para>
-
-@uri: 
-@Returns: 
-
-
-<!-- ##### FUNCTION gst_uri_handler_create ##### -->
-<para>
-
-</para>
-
-@handler: 
-@name: 
-@Returns: 
-
-
-<!-- ##### FUNCTION gst_uri_handler_make_by_uri ##### -->
-<para>
-
-</para>
-
-@uri: 
-@name: 
-@Returns: 
-
-
index 4f23d8b..1e82e51 100644 (file)
@@ -173,7 +173,7 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
   gst_fakesink_signals[SIGNAL_HANDOFF] =
     g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                     G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
-                    gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 1,
+                    gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
                     GST_TYPE_BUFFER, GST_TYPE_PAD);
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesink_set_property);
index 5c4c81c..fef5d7e 100644 (file)
@@ -69,6 +69,7 @@ GST_PAD_FORMATS_FUNCTION (gst_filesink_get_formats,
 static void    gst_filesink_base_init          (gpointer g_class);
 static void    gst_filesink_class_init         (GstFileSinkClass *klass);
 static void    gst_filesink_init               (GstFileSink *filesink);
+static void    gst_filesink_dispose            (GObject *object);
 
 static void    gst_filesink_set_property       (GObject *object, guint prop_id, 
                                                 const GValue *value, GParamSpec *pspec);
@@ -83,6 +84,8 @@ static gboolean       gst_filesink_pad_query          (GstPad *pad, GstQueryType type,
                                                 GstFormat *format, gint64 *value);
 static void    gst_filesink_chain              (GstPad *pad,GstData *_data);
 
+static void    gst_filesink_uri_handler_init   (gpointer g_iface, gpointer iface_data);
+  
 static GstElementStateReturn gst_filesink_change_state (GstElement *element);
 
 static GstElementClass *parent_class = NULL;
@@ -105,7 +108,14 @@ gst_filesink_get_type (void)
       0,
       (GInstanceInitFunc)gst_filesink_init,
     };
+    static const GInterfaceInfo urihandler_info = {
+      gst_filesink_uri_handler_init,
+      NULL,
+      NULL
+    };
     filesink_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFileSink", &filesink_info, 0);
+    
+    g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER, &urihandler_info);
   
     GST_DEBUG_CATEGORY_INIT (gst_filesink_debug, "filesink", 0, "filesink element");
   }
@@ -138,8 +148,8 @@ gst_filesink_class_init (GstFileSinkClass *klass)
 
   gobject_class->set_property = gst_filesink_set_property;
   gobject_class->get_property = gst_filesink_get_property;
+  gobject_class->dispose      = gst_filesink_dispose;
 }
-
 static void 
 gst_filesink_init (GstFileSink *filesink) 
 {
@@ -158,7 +168,38 @@ gst_filesink_init (GstFileSink *filesink)
   filesink->filename = NULL;
   filesink->file = NULL;
 }
+static void
+gst_filesink_dispose (GObject *object)
+{
+  GstFileSink *sink = GST_FILESINK (object);
 
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+  
+  g_free (sink->uri);
+  sink->uri = NULL;
+  g_free (sink->filename);
+  sink->filename = NULL;
+}
+static gboolean
+gst_filesink_set_location (GstFileSink *sink, const gchar *location)
+{
+  /* the element must be stopped or paused in order to do this */
+  if (GST_STATE (sink) > GST_STATE_PAUSED)
+    return FALSE;
+  if (GST_STATE (sink) == GST_STATE_PAUSED &&
+      GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN))
+    return FALSE;
+
+  g_free (sink->filename);
+  g_free (sink->uri);
+  sink->filename = g_strdup (location);
+  sink->uri = gst_uri_construct ("file", location);
+  
+  if (GST_STATE (sink) == GST_STATE_PAUSED)
+    gst_filesink_open_file (sink);
+
+  return TRUE;
+}
 static void
 gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
@@ -169,16 +210,7 @@ gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value,
 
   switch (prop_id) {
     case ARG_LOCATION:
-      /* the element must be stopped or paused in order to do this */
-      g_return_if_fail (GST_STATE (sink) <= GST_STATE_PAUSED);
-      if (GST_STATE (sink) == GST_STATE_PAUSED)
-        g_return_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN));
-
-      if (sink->filename)
-       g_free (sink->filename);
-      sink->filename = g_strdup (g_value_get_string (value));
-      if (GST_STATE (sink) == GST_STATE_PAUSED)
-        gst_filesink_open_file (sink);   
+      gst_filesink_set_location (sink, g_value_get_string (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -435,3 +467,54 @@ gst_filesink_change_state (GstElement *element)
 
   return GST_STATE_SUCCESS;
 }
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static guint
+gst_filesink_uri_get_type (void)
+{
+  return GST_URI_SINK;
+}
+static gchar **
+gst_filesink_uri_get_protocols(void)
+{
+  static gchar *protocols[] = {"file", NULL};
+  return protocols;
+}
+static const gchar *
+gst_filesink_uri_get_uri (GstURIHandler *handler)
+{
+  GstFileSink *sink = GST_FILESINK (handler);
+  
+  return sink->uri;
+}
+static gboolean
+gst_filesink_uri_set_uri (GstURIHandler *handler, const gchar *uri)
+{
+  gchar *protocol, *location;
+  gboolean ret;
+  GstFileSink *sink = GST_FILESINK (handler);
+
+  protocol = gst_uri_get_protocol (uri);
+  if (strcmp (protocol, "file") != 0) {
+    g_free (protocol);
+    return FALSE;
+  }
+  g_free (protocol);
+  location = gst_uri_get_location (uri);
+  ret = gst_filesink_set_location (sink, location);
+  g_free (location);
+
+  return ret;
+}
+
+static void
+gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+  iface->get_type = gst_filesink_uri_get_type;
+  iface->get_protocols = gst_filesink_uri_get_protocols;
+  iface->get_uri = gst_filesink_uri_get_uri;
+  iface->set_uri = gst_filesink_uri_set_uri;
+}
index b72551b..bd85a1d 100644 (file)
@@ -53,6 +53,7 @@ struct _GstFileSink {
   GstElement element;
 
   gchar *filename;
+  gchar *uri;
   FILE *file;
 
   guint64 data_written;
index 275d730..e1d4bff 100644 (file)
@@ -136,6 +136,8 @@ static gboolean     gst_filesrc_srcpad_query        (GstPad *pad, GstQueryType type,
 
 static GstElementStateReturn   gst_filesrc_change_state        (GstElement *element);
 
+static void            gst_filesrc_uri_handler_init    (gpointer g_iface, gpointer iface_data);
+
 
 static GstElementClass *parent_class = NULL;
 /*static guint gst_filesrc_signals[LAST_SIGNAL] = { 0 };*/
@@ -157,8 +159,15 @@ gst_filesrc_get_type(void)
       0,
       (GInstanceInitFunc)gst_filesrc_init,
     };
+    static const GInterfaceInfo urihandler_info = {
+      gst_filesrc_uri_handler_init,
+      NULL,
+      NULL
+    };
     filesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFileSrc", &filesrc_info, 0);
-
+    
+    g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
+    
     GST_DEBUG_CATEGORY_INIT (gst_filesrc_debug, "filesrc", 0, "filesrc element");
   }
   return filesrc_type;
@@ -263,8 +272,32 @@ gst_filesrc_dispose (GObject *object)
   g_mutex_free (src->map_regions_lock);
   if (src->filename)
     g_free (src->filename);
+  if (src->uri)
+    g_free (src->uri);
 }
 
+static gboolean
+gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
+{
+  /* the element must be stopped in order to do this */
+  if (GST_STATE (src) == GST_STATE_PLAYING)
+    return FALSE;
+
+  if (src->filename) g_free (src->filename);
+  if (src->uri) g_free (src->uri);
+  /* clear the filename if we get a NULL (is that possible?) */
+  if (location == NULL) {
+    src->filename = NULL;
+    src->uri = NULL;
+  } else {
+    src->filename = g_strdup (location);
+    src->uri = gst_uri_construct ("file", src->filename);
+  }
+  g_object_notify (G_OBJECT (src), "location");
+  gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
+
+  return TRUE;
+}
 
 static void
 gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
@@ -278,19 +311,7 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
 
   switch (prop_id) {
     case ARG_LOCATION:
-      /* the element must be stopped in order to do this */
-      g_return_if_fail (GST_STATE (src) < GST_STATE_PLAYING);
-
-      if (src->filename) g_free (src->filename);
-      /* clear the filename if we get a NULL (is that possible?) */
-      if (g_value_get_string (value) == NULL) {
-        gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
-        src->filename = NULL;
-      /* otherwise set the new filename */
-      } else {
-        src->filename = g_strdup (g_value_get_string (value));
-      }
-      g_object_notify (G_OBJECT (src), "location");
+      gst_filesrc_set_location (src, g_value_get_string (value));
       break;
     case ARG_BLOCKSIZE:
       src->block_size = g_value_get_ulong (value);
@@ -918,3 +939,55 @@ error:
   gst_event_unref (event);
   return FALSE;
 }
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static guint
+gst_filesrc_uri_get_type (void)
+{
+  return GST_URI_SRC;
+}
+static gchar **
+gst_filesrc_uri_get_protocols(void)
+{
+  static gchar *protocols[] = {"file", NULL};
+  return protocols;
+}
+static const gchar *
+gst_filesrc_uri_get_uri (GstURIHandler *handler)
+{
+  GstFileSrc *src = GST_FILESRC (handler);
+  
+  return src->uri;
+}
+static gboolean
+gst_filesrc_uri_set_uri (GstURIHandler *handler, const gchar *uri)
+{
+  gchar *protocol, *location;
+  gboolean ret;
+  GstFileSrc *src = GST_FILESRC (handler);
+
+  protocol = gst_uri_get_protocol (uri);
+  if (strcmp (protocol, "file") != 0) {
+    g_free (protocol);
+    return FALSE;
+  }
+  g_free (protocol);
+  location = gst_uri_get_location (uri);
+  ret = gst_filesrc_set_location (src, location);
+  g_free (location);
+
+  return ret;
+}
+
+static void
+gst_filesrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+  iface->get_type = gst_filesrc_uri_get_type;
+  iface->get_protocols = gst_filesrc_uri_get_protocols;
+  iface->get_uri = gst_filesrc_uri_get_uri;
+  iface->set_uri = gst_filesrc_uri_set_uri;
+}
+
index 23b6dde..1f584be 100644 (file)
@@ -58,6 +58,7 @@ struct _GstFileSrc {
   guint pagesize;                      /* system page size*/
  
   gchar *filename;                     /* filename */
+  gchar *uri;                          /* caching the URI */
   gint fd;                             /* open file descriptor*/
   off_t filelen;                       /* what's the file length?*/
 
index f40547f..18622ee 100644 (file)
@@ -398,7 +398,11 @@ struct _GstElementFactory {
   GList *              padtemplates;
   guint                        numpadtemplates;
 
-  GList *interfaces;           /* interfaces this element implements */
+  /* URI interface stuff */
+  guint                        uri_type;
+  gchar **             uri_protocols;
+  
+  GList *              interfaces;             /* interfaces this element implements */
 
   GST_OBJECT_PADDING
 };
@@ -423,8 +427,10 @@ G_CONST_RETURN gchar *     gst_element_factory_get_klass           (GstElementFactory *factor
 G_CONST_RETURN gchar * gst_element_factory_get_description     (GstElementFactory *factory);
 G_CONST_RETURN gchar * gst_element_factory_get_version         (GstElementFactory *factory);
 G_CONST_RETURN gchar * gst_element_factory_get_author          (GstElementFactory *factory);
-guint                  gst_element_factory_get_num_pad_templates (GstElementFactory *factory);
-G_CONST_RETURN GList * gst_element_factory_get_pad_templates   (GstElementFactory *factory);
+guint                  gst_element_factory_get_num_padtemplates (GstElementFactory *factory);
+G_CONST_RETURN GList * gst_element_factory_get_padtemplates    (GstElementFactory *factory);
+guint                  gst_element_factory_get_uri_type        (GstElementFactory *factory);           
+gchar **               gst_element_factory_get_uri_protocols   (GstElementFactory *factory);           
 
 GstElement*            gst_element_factory_create              (GstElementFactory *factory,
                                                                 const gchar *name);
index 8e1e7ab..a3642fc 100644 (file)
@@ -26,6 +26,7 @@
 #include "gstelement.h"
 #include "gstregistrypool.h"
 #include "gstinfo.h"
+#include "gsturi.h"
 
 GST_DEBUG_CATEGORY_STATIC (element_factory_debug);
 #define GST_CAT_DEFAULT element_factory_debug
@@ -85,6 +86,9 @@ gst_element_factory_init (GstElementFactory *factory)
   factory->padtemplates = NULL;
   factory->numpadtemplates = 0;
 
+  factory->uri_type = GST_URI_UNKNOWN;
+  factory->uri_protocols = NULL;
+
   factory->interfaces = NULL;
 }
 /**
@@ -150,6 +154,11 @@ gst_element_factory_cleanup (GstElementFactory *factory)
   g_list_free (factory->padtemplates);
   factory->padtemplates = NULL;
   factory->numpadtemplates = 0;
+  factory->uri_type = GST_URI_UNKNOWN;
+  if (factory->uri_protocols) {
+    g_strfreev (factory->uri_protocols);
+    factory->uri_protocols = NULL;
+  }
   
   g_list_foreach (factory->interfaces, (GFunc) g_free, NULL);
   g_list_free (factory->interfaces);
@@ -198,6 +207,20 @@ gst_element_register (GstPlugin *plugin, const gchar *name, guint rank, GType ty
   g_list_foreach (factory->padtemplates, (GFunc) g_object_ref, NULL);
   factory->numpadtemplates = klass->numpadtemplates;
 
+  /* special stuff for URI handling */
+  if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) {
+    GstURIHandlerInterface *iface = (GstURIHandlerInterface *) 
+           g_type_interface_peek (klass, GST_TYPE_URI_HANDLER);
+    if (!iface || !iface->get_type || !iface->get_protocols)
+      goto error;
+    factory->uri_type = iface->get_type ();
+    if (!GST_URI_TYPE_IS_VALID (factory->uri_type))
+      goto error;
+    factory->uri_protocols = g_strdupv (iface->get_protocols ());
+    if (!factory->uri_protocols)
+      goto error;
+  }
+
   interfaces = g_type_interfaces (type, &n_interfaces);
   for (i = 0; i < n_interfaces; i++) {
     __gst_element_factory_add_interface (factory, g_type_name (interfaces[i]));
@@ -205,10 +228,13 @@ gst_element_register (GstPlugin *plugin, const gchar *name, guint rank, GType ty
   g_free (interfaces);
   
   gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
-
   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
 
   return TRUE;
+
+error:
+  gst_element_factory_cleanup (factory);
+  return FALSE;
 }
 /**
  * gst_element_factory_create:
@@ -422,7 +448,7 @@ __gst_element_factory_add_interface (GstElementFactory *elementfactory, const gc
  * gst_element_factory_get_pad_templates:
  * @factory: a #GstElementFactory
  * 
- * Gets the #Glist of pad templates for this factory.
+ * Gets the #GList of padtemplates for this factory.
  *
  * Returns: the padtemplates
  */
@@ -434,6 +460,38 @@ gst_element_factory_get_pad_templates (GstElementFactory *factory)
   return factory->padtemplates;
 }
 /**
+ * gst_element_factory_get_uri_type:
+ * @factory: a #GstElementFactory
+ * 
+ * Gets the type of URIs the element supports or GST_URI_UNKNOWN if none.
+ *
+ * Returns: type of URIs this element supports
+ */
+guint
+gst_element_factory_get_uri_type (GstElementFactory *factory)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), GST_URI_UNKNOWN);
+
+  return factory->uri_type;
+}
+/**
+ * gst_element_factory_get_uri_protocols:
+ * @factory: a #GstElementFactory
+ * 
+ * Gets a NULL-terminated array of protocols this element supports or NULL, if
+ * no protocols are supported. You may not change the contents of the returned
+ * array as it is still ownt by the element factory. Use g_strdupv() if you want to.
+ *
+ * Returns: the supported protocols or NULL
+ */
+gchar **
+gst_element_factory_get_uri_protocols (GstElementFactory *factory)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
+
+  return factory->uri_protocols;
+}
+/**
  * gst_element_factory_can_src_caps :
  * @factory: factory to query
  * @caps: the caps to check
index 5c8afed..788222f 100644 (file)
@@ -147,7 +147,7 @@ gst_plugin_feature_type_name_filter (GstPluginFeature *feature,
  * the most appropriate feature.
  */
 void
-gst_plugin_feature_set_rank (GstPluginFeature *feature, guint16 rank)
+gst_plugin_feature_set_rank (GstPluginFeature *feature, guint rank)
 {
   g_return_if_fail (feature != NULL);
   g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature));
@@ -155,7 +155,7 @@ gst_plugin_feature_set_rank (GstPluginFeature *feature, guint16 rank)
   feature->rank = rank;
 }
 /**
- * gst_plugin_feature_set_rank:
+ * gst_plugin_feature_set_name:
  * @feature: a feature
  * @name: the name to set
  *
@@ -175,4 +175,34 @@ gst_plugin_feature_set_name (GstPluginFeature *feature, const gchar *name)
     feature->name = g_strdup (name);
   }
 }
+/**
+ * gst_plugin_feature_get rank:
+ * @feature: a feature
+ *
+ * Gets the rank of a plugin feature.
+ *
+ * Returns: The rank of the feature
+ */
+guint
+gst_plugin_feature_get_rank (GstPluginFeature *feature)
+{
+  g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), GST_RANK_NONE);
+  
+  return feature->rank;
+}
+/**
+ * gst_plugin_feature_set_name:
+ * @feature: a feature
+ *
+ * Gets the name of a pluginfeature.
+ *
+ * Returns: the name
+ */
+G_CONST_RETURN gchar *
+gst_plugin_feature_get_name (GstPluginFeature *feature)
+{
+  g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), NULL);
+  
+  return feature->name;
+}
 
index a543f66..760214c 100644 (file)
@@ -44,10 +44,10 @@ typedef struct _GstPluginFeatureClass GstPluginFeatureClass;
 struct _GstPluginFeature {
   GObject       object;
 
+  /*< private >*/
   gchar        *name;
-  gint          rank;
+  guint         rank;
 
-  /* --- private --- */
   gpointer      manager;
 
   GST_OBJECT_PADDING
@@ -79,8 +79,10 @@ void         gst_plugin_feature_unload_thyself       (GstPluginFeature *feature);
 gboolean       gst_plugin_feature_type_name_filter     (GstPluginFeature *feature,
                                                         GstTypeNameData *data);
 
-void           gst_plugin_feature_set_rank             (GstPluginFeature *feature, guint16 rank);
+void           gst_plugin_feature_set_rank             (GstPluginFeature *feature, guint rank);
 void           gst_plugin_feature_set_name             (GstPluginFeature *feature, const gchar *name);
+guint          gst_plugin_feature_get_rank             (GstPluginFeature *feature);
+G_CONST_RETURN gchar *gst_plugin_feature_get_name      (GstPluginFeature *feature);
 
 G_END_DECLS
 
index e198998..17f60d0 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#include "gst_private.h"
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
 
 #include "gsturi.h"
-#include "gstregistrypool.h"
 #include "gstinfo.h"
+#include "gstregistrypool.h"
+#include "gstmarshal.h"
+
+#include <string.h>
+#include <ctype.h>
 
-static void            gst_uri_handler_class_init      (GstURIHandlerClass *klass);
-static void            gst_uri_handler_init            (GstURIHandler *factory);
+GST_DEBUG_CATEGORY_STATIC (gst_uri_handler_debug);
+#define GST_CAT_DEFAULT gst_uri_handler_debug
 
-static GstPluginFeatureClass *parent_class = NULL;
-/* static guint gst_uri_handler_signals[LAST_SIGNAL] = { 0 }; */
+static void    gst_uri_handler_base_init       (gpointer g_class);
 
 GType
 gst_uri_handler_get_type (void)
@@ -39,222 +44,346 @@ gst_uri_handler_get_type (void)
 
   if (!urihandler_type) {
     static const GTypeInfo urihandler_info = {
-      sizeof (GstURIHandlerClass),
+      sizeof (GstURIHandlerInterface),
+      gst_uri_handler_base_init,
       NULL,
       NULL,
-      (GClassInitFunc) gst_uri_handler_class_init,
       NULL,
       NULL,
-      sizeof(GstURIHandler),
       0,
-      (GInstanceInitFunc) gst_uri_handler_init,
+      0,
+      NULL,
       NULL
     };
-    urihandler_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
-                                               "GstURIHandler", &urihandler_info, 0);
+    urihandler_type = g_type_register_static (G_TYPE_INTERFACE,
+           "GstURIHandler", &urihandler_info, 0);
+
+    GST_DEBUG_CATEGORY_INIT (gst_uri_handler_debug, "GST_URI", GST_DEBUG_BOLD, "handling of URIs");
   }
   return urihandler_type;
 }
-
 static void
-gst_uri_handler_class_init (GstURIHandlerClass *klass)
+gst_uri_handler_base_init (gpointer g_class)
 {
-  GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
-  GstPluginFeatureClass *gstpluginfeature_class;
-
-  gobject_class = (GObjectClass*)klass;
-  gstobject_class = (GstObjectClass*)klass;
-  gstpluginfeature_class = (GstPluginFeatureClass*) klass;
+  static gboolean initialized = FALSE;
 
-  parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
+  if (!initialized) {
+    g_signal_new ("new_uri", GST_TYPE_URI_HANDLER, G_SIGNAL_RUN_LAST,
+           G_STRUCT_OFFSET (GstURIHandlerInterface, new_uri), NULL, NULL,
+           gst_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+    initialized = TRUE;
+  }
 }
+                                                                                                                    
 
 static void
-gst_uri_handler_init (GstURIHandler *factory)
+gst_uri_protocol_check_internal (const gchar *uri, gchar **endptr)
 {
+  gchar *check = (gchar *) uri;
+  
+  g_assert (uri != NULL);
+  g_assert (endptr != NULL);
+
+  if (isalpha (*check)) {
+    check++;
+    while (isalnum (*check)) check++;
+  }
+
+  *endptr = check;
 }
+/**
+ * gst_uri_protocol_is_valid:
+ * @protocol: string to check
+ *
+ * Tests if the given string is a valid protocol identifier. Protocols
+ * must consist of alphanumeric characters and not start with a number.
+ *
+ * Returns: TRUE if the string is a valid protocol identifier
+ */
+gboolean
+gst_uri_protocol_is_valid (const gchar *protocol)
+{
+  gchar *endptr;
+  
+  g_return_val_if_fail (protocol != NULL, FALSE);
+  
+  gst_uri_protocol_check_internal (protocol, &endptr);
 
+  return *endptr == '\0' && endptr != protocol;
+}
 /**
- * gst_uri_handler_new:
- * @name: the name of the feature
- * @uri: the uri to register
- * @longdesc: a description for this uri
- * @element: an element that can handle the uri
- * @property: the property on the element to set the uri
+ * gst_uri_is_valid:
+ * @protocol: string to check
  *
- * Creates a plugin feature to register an element that can
- * handle the given uri on the given property.
+ * Tests if the given string is a valid URI identifier. URIs start with a valid
+ * protocol followed by "://" and a string identifying the location.
  *
- * Returns: the new urihandler
+ * Returns: TRUE if the string is a valid URI
  */
-GstURIHandler*
-gst_uri_handler_new (const gchar *name, 
-                    const gchar *uri, const gchar *longdesc, 
-                    const gchar *element, gchar *property)
+gboolean
+gst_uri_is_valid (const gchar *uri)
 {
-  GstURIHandler *factory;
+  gchar *endptr;
+  
+  g_return_val_if_fail (uri != NULL, FALSE);
+  
+  gst_uri_protocol_check_internal (uri, &endptr);
 
-  g_return_val_if_fail (name != NULL, NULL);
+  return (*endptr == ':' &&
+         *(endptr + 1) == '/' &&
+         *(endptr + 2) == '/');
+}
+/**
+ * gst_uri_get_protocol:
+ * @uri: URI to get protocol from
+ *
+ * Extracts the protocol out of a given valid URI. The returned string must be
+ * freed using g_free().
+ *
+ * Returns: The protocol for this URI.
+ */
+gchar *
+gst_uri_get_protocol (const gchar *uri)
+{
+  gchar *colon;
+  
   g_return_val_if_fail (uri != NULL, NULL);
-  g_return_val_if_fail (element != NULL, NULL);
-  g_return_val_if_fail (property != NULL, NULL);
-
-  factory = gst_uri_handler_find (name);
-
-  if (!factory) {
-    factory = GST_URI_HANDLER (g_object_new (GST_TYPE_URI_HANDLER, NULL));
-  }
+  g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
 
-  GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
-  factory->uri = g_strdup (uri);
-  factory->longdesc = g_strdup (longdesc);
-  factory->element = g_strdup (element);
-  factory->property = g_strdup (property);
+  colon = strstr (uri, "://");
 
-  return factory;
+  return g_strndup (uri, colon - uri);
 }
-
 /**
- * gst_uri_handler_find:
- * @name: the name of the urihandler to find
+ * gst_uri_get_location:
+ * @uri: URI to get the location from
  *
- * Return the URIHandler with the given name. 
+ * Extracts the location out of a given valid URI. So the protocol and "://"
+ * are stripped from the URI. The returned string must be freed using 
+ * g_free().
  *
- * Returns: a GstURIHandler with the given name;
+ * Returns: The location for this URI.
  */
-GstURIHandler*
-gst_uri_handler_find (const gchar *name)
+gchar *
+gst_uri_get_location (const gchar *uri)
 {
-  GstPluginFeature *feature;
-
-  g_return_val_if_fail (name != NULL, NULL);
+  gchar *colon;
+  
+  g_return_val_if_fail (uri != NULL, NULL);
+  g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
 
-  feature = gst_registry_pool_find_feature (name, GST_TYPE_URI_HANDLER);
-  if (feature)
-    return GST_URI_HANDLER (feature);
+  colon = strstr (uri, "://");
 
-  return NULL;
+  return g_strdup (colon + 3);
 }
-
-/*
- * this is a straight copy from glib 2.2
- * remove this function when glib 2.2 is sufficiently widespread and
- * then change to using the regular g_str_has_prefix
+/**
+ * gst_uri_construct:
+ * @protocol: protocol for URI
+ * @location: location for URI
+ *
+ * Constructs a URI for a given valid protocol and location.
+ *
+ * Returns: a new string for this URI
  */
+gchar *
+gst_uri_construct (const gchar *protocol, const gchar *location)
+{
+  g_return_val_if_fail (gst_uri_protocol_is_valid (protocol), NULL);
+  g_return_val_if_fail (location != NULL, NULL);
+
+  return g_strdup_printf ("%s://%s", protocol, location);
+}
+typedef struct{
+  GstURIType   type;
+  gchar *      protocol;
+} SearchEntry;
 static gboolean
-g_str_has_prefix_glib22 (gchar *haystack, gchar *needle)
+search_by_entry (GstPluginFeature *feature, gpointer search_entry)
 {
-  if (haystack == NULL && needle == NULL) {
-    return TRUE;
-  }
-  if (haystack == NULL || needle == NULL) {
+  gchar **protocols;
+  GstElementFactory *factory;
+  SearchEntry *entry = (SearchEntry *) search_entry;
+
+  if (!GST_IS_ELEMENT_FACTORY (feature))
     return FALSE;
-  }
-  if (strncmp (haystack, needle, strlen (needle)) == 0) {
-    return TRUE;
+  factory = GST_ELEMENT_FACTORY (feature);
+
+  if (gst_element_factory_get_uri_type (factory) != entry->type)
+    return FALSE;
+  
+  protocols = gst_element_factory_get_uri_protocols (factory);
+  /* must be set when uri type is valid */
+  g_assert (protocols);
+  while (*protocols != NULL) {
+    if (strcmp (*protocols, entry->protocol) == 0)
+      return TRUE;
+    protocols++;
   }
   return FALSE;
 }
+static gint
+sort_by_rank (gconstpointer a, gconstpointer b)
+{
+  GstPluginFeature *first = GST_PLUGIN_FEATURE (a);
+  GstPluginFeature *second = GST_PLUGIN_FEATURE (b);
 
+  return gst_plugin_feature_get_rank (second) - gst_plugin_feature_get_rank (first);
+}
 /**
- * gst_uri_handler_uri_filter:
- * @feature: the feature to inspect
- * @uri: the name of the uri to match
+ * gst_element_make_from_uri:
+ * @type: wether to create a source or a sink
+ * @uri: URI to create element for
+ * @elementname: optional name of created element
  *
- * Check if the given pluginfeature is a uri hanler and that
- * it can handle the given uri.
- *
- * Returns: TRUE if the feature can handle the uri.
+ * Creates an element for handling the given URI. 
+ * 
+ * Returns: a new element or NULL if none could be created
  */
-gboolean
-gst_uri_handler_uri_filter (GstPluginFeature *feature, const gchar *uri)
+GstElement *
+gst_element_make_from_uri (const GstURIType type, const gchar *uri, const gchar *elementname)
 {
-  if (G_OBJECT_TYPE (feature) == GST_TYPE_URI_HANDLER) {
-    GstURIHandler *handler = GST_URI_HANDLER (feature);
+  GList *possibilities, *walk;
+  SearchEntry entry;
+  GstElement *ret = NULL;
+
+  g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL);
+  g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
+
+  entry.type = type;
+  entry.protocol = gst_uri_get_protocol (uri);
+  possibilities = gst_registry_pool_feature_filter (search_by_entry, FALSE, &entry);
+  g_free (entry.protocol);
+
+  if (!possibilities) {
+    GST_DEBUG ("No %s for URI '%s'", type == GST_URI_SINK ? "sink" : "source", uri);
+    return NULL;
+  }
   
-    if (g_str_has_prefix_glib22 ((gchar *) uri, handler->uri)) {
-      return TRUE;
+  possibilities = g_list_sort (possibilities, sort_by_rank);
+  walk = possibilities;
+  while (walk) {
+    if ((ret = gst_element_factory_create (GST_ELEMENT_FACTORY (walk->data), 
+                 elementname)) != NULL) {
+      GstURIHandler *handler = GST_URI_HANDLER (ret);
+      if (gst_uri_handler_set_uri (handler, uri))
+       break;
+      g_object_unref (ret);
+      ret = NULL;
     }
   }
-  return FALSE;
-}
+  g_list_free (possibilities);
 
+  GST_LOG_OBJECT (ret, "created %s for URL '%s'", type == GST_URI_SINK ? "sink" : "source", uri);
+  return ret;
+}
 /**
- * gst_uri_handler_find_by_uri:
- * @uri: the uri to find a handler for
+ * gst_uri_handler_get_uri_type:
+ * @handler: Handler to query type of
  *
- * Find a URIHandler for the given uri.
+ * Gets the type of a URI handler
  *
- * Returns: a GstURIHandler that can handle the given uri.
+ * Returns: the type of the URI handler
  */
-GstURIHandler*
-gst_uri_handler_find_by_uri (const gchar *uri)
+guint
+gst_uri_handler_get_uri_type (GstURIHandler *handler)
 {
-  GList *walk;
-  GstURIHandler *result = NULL;
+  GstURIHandlerInterface *iface;
+  guint ret;
   
-  g_return_val_if_fail (uri != NULL, NULL);
+  g_return_val_if_fail (GST_IS_URI_HANDLER (handler), GST_URI_UNKNOWN);
 
-  walk = gst_registry_pool_feature_filter (
-                 (GstPluginFeatureFilter) gst_uri_handler_uri_filter, TRUE, (gpointer) uri);
+  iface = GST_URI_HANDLER_GET_INTERFACE (handler);
+  g_return_val_if_fail (iface != NULL, GST_URI_UNKNOWN);
+  g_return_val_if_fail (iface->get_type != NULL, GST_URI_UNKNOWN);
+  ret = iface->get_type ();
+  g_return_val_if_fail (GST_URI_TYPE_IS_VALID (ret), GST_URI_UNKNOWN);
 
-  if (walk) {
-    result = GST_URI_HANDLER (walk->data);
-  }
-  g_list_free (walk);
-
-  return result;
+  return ret;
 }
-
 /**
- * gst_uri_handler_create:
- * @handler: the uri handler to use
- * @name: the name of the element
+ * gst_uri_handler_get_protocols:
+ * @handler: Handler to get protocols for
  *
- * Create an element with the given name from the given handler.
+ * Gets the list of supported protocols for this handler. This list may not be
+ * modified.
  *
- * Returns: a new element associated with the handler.
+ * Returns: the supported protocols
  */
-GstElement*
-gst_uri_handler_create (GstURIHandler *handler, const gchar *name)
+gchar **
+gst_uri_handler_get_protocols (GstURIHandler *handler)
 {
-  GstElement *element = NULL;
-
-  g_return_val_if_fail (handler != NULL, NULL);
+  GstURIHandlerInterface *iface;
+  gchar **ret;
+  
+  g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL);
 
-  element = gst_element_factory_make (handler->element, name);
+  iface = GST_URI_HANDLER_GET_INTERFACE (handler);
+  g_return_val_if_fail (iface != NULL, NULL);
+  g_return_val_if_fail (iface->get_protocols != NULL, NULL);
+  ret = iface->get_protocols ();
+  g_return_val_if_fail (ret != NULL, NULL);
 
-  return element;
+  return ret;
 }
-
 /**
- * gst_uri_handler_make_by_uri:
- * @uri: the uri
- * @name: the name of the element
+ * gst_uri_handler_get_uri:
+ * @handler: handler to query URI of
  *
- * Create an element with the given name that can handle the given
- * uri. This function will also use set the uri on the element.
+ * Gets the currently handled URI of the handler or NULL, if none is set.
  *
- * Returns: a new element that can handle the uri.
+ * Returns: the URI
  */
-GstElement*
-gst_uri_handler_make_by_uri (const gchar *uri, const gchar *name)
+G_CONST_RETURN gchar *
+gst_uri_handler_get_uri (GstURIHandler *handler)
 {
-  GstElement *element = NULL;
-  GstURIHandler *handler;
-
-  g_return_val_if_fail (uri != NULL, NULL);
-
-  handler = gst_uri_handler_find_by_uri (uri);
-  if (handler) {
-    element = gst_uri_handler_create (handler, name);
-    if (element) {
-      g_object_set (G_OBJECT (element), handler->property, uri, NULL);
-    }
-  }
-  return element;
+  GstURIHandlerInterface *iface;
+  const gchar *ret;
+  
+  g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL);
+
+  iface = GST_URI_HANDLER_GET_INTERFACE (handler);
+  g_return_val_if_fail (iface != NULL, NULL);
+  g_return_val_if_fail (iface->get_uri != NULL, NULL);
+  ret = iface->get_uri (handler);
+  if (ret != NULL)
+    g_return_val_if_fail (gst_uri_is_valid (ret), NULL);
+    
+  return ret;
 }
+/**
+ * gst_uri_handler_set_uri:
+ * @handler: handler to set URI of
+ * @uri: URI to set
+ *
+ * Tries to set the URI of the given handler and returns TRUE if it succeeded.
+ *
+ * Returns: TRUE, if the URI was set successfully
+ */
+gboolean
+gst_uri_handler_set_uri (GstURIHandler *handler, const gchar *uri)
+{
+  GstURIHandlerInterface *iface;
+  
+  g_return_val_if_fail (GST_IS_URI_HANDLER (handler), FALSE);
+  g_return_val_if_fail (gst_uri_is_valid (uri), FALSE);
 
+  iface = GST_URI_HANDLER_GET_INTERFACE (handler);
+  g_return_val_if_fail (iface != NULL, FALSE);
+  g_return_val_if_fail (iface->set_uri != NULL, FALSE);
+  return iface->set_uri (handler, uri);
+}
+/**
+ * gst_uri_handler_new_uri:
+ * @handler: handler with a new URI
+ * @uri: new URI or NULL if it was unset
+ *
+ * Emits the new-uri event for a given handler, when that handler has a new URI.
+ * This function should only be called by URI handlers themselves.
+ */
+void
+gst_uri_handler_new_uri (GstURIHandler *handler, const gchar *uri)
+{
+  g_return_if_fail (GST_IS_URI_HANDLER (handler));
 
-
+  g_signal_emit_by_name (handler, "new-uri", uri);
+}
index 2662b47..0d0a109 100644 (file)
 
 G_BEGIN_DECLS
 
+typedef enum {
+  GST_URI_UNKNOWN,
+  GST_URI_SINK,
+  GST_URI_SRC
+} GstURIType;
+
+#define GST_URI_TYPE_IS_VALID(type) ((type) == GST_URI_SRC || (type) == GST_URI_SINK)
+
 /* uri handler functions */
 #define GST_TYPE_URI_HANDLER           (gst_uri_handler_get_type ())
 #define GST_URI_HANDLER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
 #define GST_IS_URI_HANDLER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_URI_HANDLER))
-#define GST_URI_HANDLER_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_URI_HANDLER, GstURIHandlerClass))
-#define GST_IS_URI_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_URI_HANDLER))
-#define GST_URI_HANDLER_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerClass))
+#define GST_URI_HANDLER_GET_INTERFACE(obj)     (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerInterface))
+#define GST_URI_HANDLER_CLASS(obj)     (G_TYPE_CHECK_CLASS_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
 
 typedef struct _GstURIHandler GstURIHandler;
-typedef struct _GstURIHandlerClass GstURIHandlerClass;
+typedef struct _GstURIHandlerInterface GstURIHandlerInterface;
 
-struct _GstURIHandler {
-  GstPluginFeature feature;
+struct _GstURIHandlerInterface {
+  GTypeInterface       parent;
 
-  /* --- public ---- */
-  gchar *uri;              /* The uri that is described */
-  gchar *longdesc;         /* description of the uri */
-  gchar *element;          /* The element that can handle this uri */
-  gchar *property;         /* The property on the element to set the uri */
+  /* signals */
+  void                 (* new_uri)                             (GstURIHandler *        handler,
+                                                                const gchar *          uri);
+  /* idea for the future ?
+  gboolean             (* require_password)                    (GstURIHandler *        handler,
+                                                                gchar **               username,
+                                                                gchar **               password);
+   */
 
-  GST_OBJECT_PADDING
-};
+  /* vtable */
+
+  /* querying capabilities */
+  GstURIType           (* get_type)                            (void);
+  gchar **             (* get_protocols)                       (void);
 
-struct _GstURIHandlerClass {
-  GstPluginFeatureClass parent;
+  /* using the interface */
+  G_CONST_RETURN gchar *(* get_uri)                            (GstURIHandler *        handler);
+  gboolean             (* set_uri)                             (GstURIHandler *        handler,
+                                                                const gchar *          uri);
+  
+  /* we might want to add functions here to query features, someone with gnome-vfs knowledge go ahead */
 
   GST_CLASS_PADDING
 };
 
-GType                  gst_uri_handler_get_type        (void);
+/* general URI functions */
 
-GstURIHandler*         gst_uri_handler_new             (const gchar *name, 
-                                                        const gchar *uri, const gchar *longdesc, 
-                                                        const gchar *element, gchar *property);
+gboolean               gst_uri_protocol_is_valid               (const gchar *          protocol);
+gboolean               gst_uri_is_valid                        (const gchar *          uri);
+gchar *                        gst_uri_get_protocol                    (const gchar *          uri);
+gchar *                        gst_uri_get_location                    (const gchar *          uri);
+gchar *                        gst_uri_construct                       (const gchar *          protocol,
+                                                                const gchar *          location);
 
-GstURIHandler*         gst_uri_handler_find            (const gchar *name);
-GstURIHandler*         gst_uri_handler_find_by_uri     (const gchar *uri);
+GstElement *           gst_element_make_from_uri               (const GstURIType       type,
+                                                                const gchar *          uri,
+                                                                const gchar *          elementname);
 
-GstElement*            gst_uri_handler_create          (GstURIHandler *handler, const gchar *name);
-GstElement*            gst_uri_handler_make_by_uri     (const gchar *uri, const gchar *name);
+/* accessing the interface */
+GType                  gst_uri_handler_get_type                (void);
 
-/* filters */
-gboolean               gst_uri_handler_uri_filter      (GstPluginFeature *feature, const gchar *uri);
+guint                  gst_uri_handler_get_uri_type            (GstURIHandler *        handler);
+gchar **               gst_uri_handler_get_protocols           (GstURIHandler *        handler);
+G_CONST_RETURN gchar *         gst_uri_handler_get_uri                 (GstURIHandler *        handler);
+gboolean               gst_uri_handler_set_uri                 (GstURIHandler *        handler,
+                                                                const gchar *          uri);
+void                   gst_uri_handler_new_uri                 (GstURIHandler *        handler,
+                                                                const gchar *          uri);
 
 G_END_DECLS
 
-#endif /* __GST_URI_H */
+#endif /* __GST_URI_H__ */
index 61f3196..5de57fe 100644 (file)
@@ -7,8 +7,10 @@
 
 #include "../gst_private.h"
 
+#include "../gstconfig.h"
 #include "../gstparse.h"
 #include "../gstinfo.h"
+#include "../gsturi.h"
 #include "types.h"
 
 #define YYERROR_VERBOSE 1
@@ -97,7 +99,7 @@ typedef struct {
   } \
 }G_STMT_END
 #define ERROR(type, ...) SET_ERROR (((graph_t *) graph)->error, (type), __VA_ARGS__ )
-#ifdef GST_DEBUG_ENABLED
+#ifndef GST_DISABLE_GST_DEBUG
 #  define YYDEBUG 1
    /* bison 1.35 calls this macro with side effects, we need to make sure the
       side effects work - crappy bison
@@ -122,7 +124,7 @@ typedef struct {
   } \
 }G_STMT_END
 #define ERROR(type, args...) SET_ERROR (((graph_t *) graph)->error, (type), ## args )
-#ifdef GST_DEBUG_ENABLED
+#ifndef GST_DISABLE_GST_DEBUG
 #  define YYDEBUG 1
    /* bison 1.35 calls this macro with side effects, we need to make sure the
       side effects work - crappy bison
@@ -147,7 +149,7 @@ typedef struct {
   } \
 }G_STMT_END
 #define ERROR(type, ...) SET_ERROR (((graph_t *) graph)->error, (type), "error while parsing")
-#ifdef GST_DEBUG_ENABLED
+#ifndef GST_DISABLE_GST_DEBUG
 #  define YYDEBUG 1
 #endif
 
@@ -210,23 +212,6 @@ typedef struct {
   MAKE_LINK (link, NULL, _src, pads, NULL, NULL, NULL); \
 }G_STMT_END
 
-static inline void gst_parse_unescape (gchar *str)
-{
-  gchar *walk;
-  
-  g_return_if_fail (str != NULL);
-  
-  walk = str;
-  
-  while (*walk) {
-    if (*walk == '\\')
-      walk++;
-    *str = *walk;
-    str++;
-    walk++;
-  }
-  *str = '\0';
-}
 static void
 gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
 {
@@ -532,6 +517,7 @@ static int yyerror (const char *s);
     graph_t *g;
 }
 
+%token <s> PARSE_URL
 %token <s> IDENTIFIER
 %left <s> REF PADREF BINREF
 %token <s> ASSIGNMENT
@@ -542,7 +528,7 @@ static int yyerror (const char *s);
 %type <l> reference
 %type <l> linkpart link
 %type <p> linklist
-%type <e> element
+%type <e> element 
 %type <p> padlist pads assignments
 
 %left '{' '}' '(' ')'
@@ -566,12 +552,11 @@ element:  IDENTIFIER                    { $$ = gst_element_factory_make ($1, NULL);
                                                $$ = $1;
                                              }
        ;
-       
 assignments:   /* NOP */                     { $$ = NULL; }
        |       assignments ASSIGNMENT        { $$ = g_slist_prepend ($1, $2); }
        ;               
-bin:           '{' assignments chain '}'     { GST_BIN_MAKE ($$, "thread", $3, $2); }
-        |       '(' assignments chain ')'     { GST_BIN_MAKE ($$, "bin", $3, $2); }
+bin:           '{' assignments chain '}' { GST_BIN_MAKE ($$, "thread", $3, $2); }
+        |       '(' assignments chain ')' { GST_BIN_MAKE ($$, "bin", $3, $2); }
         |       BINREF assignments chain ')'  { GST_BIN_MAKE ($$, $1, $3, $2); 
                                                gst_parse_strfree ($1);
                                              }
@@ -670,21 +655,6 @@ chain:     element                       { $$ = gst_parse_chain_new ();
                                                gst_parse_chain_free ($2);
                                                $$ = $1;
                                              }
-       |       link chain                    { if ($2->front) {
-                                                 if (!$2->front->src_name) {
-                                                   ERROR (GST_PARSE_ERROR_LINK, "link without source element");
-                                                   gst_parse_free_link ($2->front);
-                                                 } else {
-                                                   ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
-                                                 }
-                                               }
-                                               if (!$1->sink_name) {
-                                                 $1->sink = $2->first;
-                                               }
-                                               $2->front = $1;
-                                               $$ = $2;
-                                             }
-                                       
        |       chain linklist                { GSList *walk;
                                                if ($1->back) {
                                                  $2 = g_slist_prepend ($2, $1->back);
@@ -716,8 +686,60 @@ chain:     element                       { $$ = gst_parse_chain_new ();
                                                $$ = $1;
                                              }
        |       chain error                   { $$ = $1; }
+       |       link chain                    { if ($2->front) {
+                                                 if (!$2->front->src_name) {
+                                                   ERROR (GST_PARSE_ERROR_LINK, "link without source element");
+                                                   gst_parse_free_link ($2->front);
+                                                 } else {
+                                                   ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
+                                                 }
+                                               }
+                                               if (!$1->sink_name) {
+                                                 $1->sink = $2->first;
+                                               }
+                                               $2->front = $1;
+                                               $$ = $2;
+                                             }
+       |       PARSE_URL chain               { $$ = $2;
+                                               if ($$->front) {
+                                                 GstElement *element = 
+                                                         gst_element_make_from_uri (GST_URI_SRC, $1, NULL);
+                                                 if (!element) {
+                                                   ERROR (GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
+                                                           "No source element for URI \"%s\"", $1);
+                                                 } else {
+                                                   $$->front->src = element;
+                                                   ((graph_t *) graph)->links = g_slist_prepend (
+                                                           ((graph_t *) graph)->links, $$->front);
+                                                   $$->front = NULL;
+                                                   $$->elements = g_slist_prepend ($$->elements, element);
+                                                 }
+                                               } else {
+                                                 ERROR (GST_PARSE_ERROR_LINK, 
+                                                         "No element to link URI \"%s\" to", $1);
+                                               }
+                                               g_free ($1);
+                                             }
+       |       link PARSE_URL                { GstElement *element =
+                                                         gst_element_make_from_uri (GST_URI_SINK, $2, NULL);
+                                               if (!element) {
+                                                 ERROR (GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
+                                                         "No sink element for URI \"%s\"", $2);
+                                                 YYERROR;
+                                               } else if ($1->sink_name || $1->sink_pads) {
+                                                 ERROR (GST_PARSE_ERROR_LINK, 
+                                                         "could not link sink element for URI \"%s\"", $2);
+                                                 YYERROR;
+                                               } else {
+                                                 $$ = gst_parse_chain_new ();
+                                                 $$->first = $$->last = element;
+                                                 $$->front = $1;
+                                                 $$->front->sink = element;
+                                                 $$->elements = g_slist_prepend (NULL, element);
+                                               }
+                                               g_free ($2);
+                                             }
        ;
-       
 graph:         /* NOP */                     { ERROR (GST_PARSE_ERROR_EMPTY, "Empty pipeline not allowed");
                                                $$ = (graph_t *) graph;
                                              }
@@ -785,7 +807,7 @@ _gst_parse_launch (const gchar *str, GError **error)
   dstr = g_strdup (str);
   _gst_parse_yy_scan_string (dstr);
 
-#ifdef GST_DEBUG_ENABLED
+#ifndef GST_DISABLE_GST_DEBUG
   yydebug = 1;
 #endif
 
index 021d13b..95fb0c5 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "types.h"
 #include "../gstinfo.h"
+#include "../gsturi.h"
 #include "grammar.tab.h"
 
 #ifdef G_HAVE_ISO_VARARGS
@@ -29,6 +30,9 @@ _string {_char}+|("\""([^\"]|"\\\"")*"\"")|("'"([^']|"\\\"")*"'")
 _comma [[:space:]]*","[[:space:]]*
 _assign [[:space:]]*"="[[:space:]]*
 
+_protocol [[:alpha:]][[:alnum:]+-\.]*
+_url {_protocol}"://"{_string}|["."{_identifier}]?"/"{_string}
+
 /* we must do this here, because nearly everything matches a {_string} */ 
 _assignment {_identifier}{_assign}{_string}
 
@@ -106,6 +110,17 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*";"[[:space:]]*{_caps})*[[:space:]]*"!
     BEGIN (INITIAL);
     return LINK;
 }
+{_url} {
+  PRINT ("URL: %s\n", yytext);
+  if (gst_uri_is_valid (yytext)) {
+    lvalp->s = g_strdup (yytext);
+  } else {
+    lvalp->s = gst_uri_construct ("file", yytext);
+  }
+  gst_parse_unescape (lvalp->s);
+  BEGIN (INITIAL);
+  return PARSE_URL;
+}
 
 {_operator} { PRINT ("OPERATOR: [%s]\n", yytext); return *yytext; }
 
index ffc7643..3fa3588 100644 (file)
@@ -66,4 +66,23 @@ void __gst_parse_chain_free (chain_t *data);
 #  define gst_parse_chain_free g_free
 #endif /* __GST_PARSE_TRACE */
 
+static inline void
+gst_parse_unescape (gchar *str)
+{
+  gchar *walk;
+  
+  g_return_if_fail (str != NULL);
+  
+  walk = str;
+  
+  while (*walk) {
+    if (*walk == '\\')
+      walk++;
+    *str = *walk;
+    str++;
+    walk++;
+  }
+  *str = '\0';
+}
+
 #endif /* __GST_PARSE_TYPES_H__ */
index 76f2679..dcf10b3 100644 (file)
@@ -680,6 +680,26 @@ gst_xml_registry_parse_plugin (GMarkupParseContext *context, const gchar *tag, c
   return TRUE;
 }
 
+static void
+add_to_char_array (gchar ***array, gchar *value)
+{
+  gchar **new;
+  gchar **old = *array;
+  gint i = 0;
+    
+  /* expensive, but cycles are cheap... */
+  if (old)
+    while (old[i]) i++;
+  new = g_new0 (gchar *, i + 2);
+  new[i] = value;
+  while (i > 0) {
+    i--;
+    new[i] = old[i];
+  }
+  g_free (old);
+  *array = new;
+}
+
 static gboolean
 gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
                                         gsize text_len, GstXMLRegistry *registry, GError **error)
@@ -715,6 +735,14 @@ gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gcha
     if (ret == text + text_len) {
      gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
     }
+  } else if (!strcmp (tag, "uri_type")) {
+    if (strncasecmp (text, "sink", 4) == 0) {
+      factory->uri_type = GST_URI_SINK;
+    } else if (strncasecmp (text, "source", 5) == 0) {
+      factory->uri_type = GST_URI_SRC;
+    }
+  } else if (!strcmp (tag, "uri_protocol")) {
+    add_to_char_array (&factory->uri_protocols, g_strndup (text, text_len));
   }
   else if (!strcmp(tag, "interface")) {
     gchar *tmp = g_strndup (text, text_len);
@@ -747,21 +775,7 @@ gst_xml_registry_parse_type_find_factory (GMarkupParseContext *context, const gc
     factory->caps = g_strndup (text, text_len);
   }*/
   else if (!strcmp(tag, "extension")) {
-    gchar **new;
-    gchar **old = factory->extensions;
-    gint i = 0;
-    
-    /* expensive, but cycles are cheap... */
-    if (old)
-      while (old[i]) i++;
-    new = g_new0 (gchar *, i + 2);
-    new[i] = g_strndup (text, text_len);
-    while (i > 0) {
-      i--;
-      new[i] = old[i];
-    }
-    g_free (old);
-    factory->extensions = new;
+    add_to_char_array (&factory->extensions, g_strndup (text, text_len));
   }
 
   return TRUE;
@@ -813,30 +827,6 @@ gst_xml_registry_parse_index_factory (GMarkupParseContext *context, const gchar
 }
 
 static gboolean
-gst_xml_registry_parse_uri_handler (GMarkupParseContext *context, const gchar *tag, const gchar *text,
-                                    gsize text_len, GstXMLRegistry *registry, GError **error)
-{
-  GstURIHandler *handler = GST_URI_HANDLER (registry->current_feature);
-
-  if (!strcmp (tag, "name")) {
-    registry->current_feature->name = g_strndup (text, text_len);
-  }
-  else if (!strcmp (tag, "uri")) {
-    handler->uri = g_strndup (text, text_len);
-  }
-  else if (!strcmp (tag, "longdesc")) {
-    handler->longdesc = g_strndup (text, text_len);
-  }
-  else if (!strcmp (tag, "element")) {
-    handler->element = g_strndup (text, text_len);
-  }
-  else if (!strcmp (tag, "property")) {
-    handler->property = g_strndup (text, text_len);
-  }
-  return TRUE;
-}
-
-static gboolean
 gst_xml_registry_parse_padtemplate (GMarkupParseContext *context, const gchar *tag, const gchar *text,
                                     gsize text_len, GstXMLRegistry *registry, GError **error)
 {
@@ -953,9 +943,6 @@ gst_xml_registry_start_element (GMarkupParseContext *context,
          else if (GST_IS_INDEX_FACTORY (feature)) {
            xmlregistry->parser = gst_xml_registry_parse_index_factory;
          }
-         else if (GST_IS_URI_HANDLER (feature)) {
-           xmlregistry->parser = gst_xml_registry_parse_uri_handler;
-         }
          else {
             g_warning ("unkown feature type");
          }
@@ -1495,6 +1482,18 @@ gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *fe
       PUT_ESCAPED ("interface", (gchar *) walk->data);
       walk = g_list_next (walk);
     }
+
+    if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
+      gchar **protocol;
+      
+      PUT_ESCAPED ("uri_type", factory->uri_type == GST_URI_SINK ? "sink" : "source");
+      g_assert (factory->uri_protocols);
+      protocol = factory->uri_protocols;
+      while (*protocol) {
+       PUT_ESCAPED ("uri_protocol", *protocol);
+       protocol++;
+      }
+    }
   }
   else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
@@ -1521,18 +1520,9 @@ gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *fe
   else if (GST_IS_INDEX_FACTORY (feature)) {
     PUT_ESCAPED ("longdesc", GST_INDEX_FACTORY (feature)->longdesc);
   }
-  else if (GST_IS_URI_HANDLER (feature)) {
-    GstURIHandler *handler = GST_URI_HANDLER (feature);
-
-    PUT_ESCAPED ("uri", handler->uri);
-    PUT_ESCAPED ("longdesc", handler->longdesc);
-    PUT_ESCAPED ("element", handler->element);
-    PUT_ESCAPED ("property", handler->property);
-  }
   return TRUE;
 }
 
-
 static gboolean
 gst_xml_registry_save_plugin (GstXMLRegistry *xmlregistry, GstPlugin *plugin)
 {
index 4f23d8b..1e82e51 100644 (file)
@@ -173,7 +173,7 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
   gst_fakesink_signals[SIGNAL_HANDOFF] =
     g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
                     G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
-                    gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 1,
+                    gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
                     GST_TYPE_BUFFER, GST_TYPE_PAD);
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesink_set_property);
index 5c4c81c..fef5d7e 100644 (file)
@@ -69,6 +69,7 @@ GST_PAD_FORMATS_FUNCTION (gst_filesink_get_formats,
 static void    gst_filesink_base_init          (gpointer g_class);
 static void    gst_filesink_class_init         (GstFileSinkClass *klass);
 static void    gst_filesink_init               (GstFileSink *filesink);
+static void    gst_filesink_dispose            (GObject *object);
 
 static void    gst_filesink_set_property       (GObject *object, guint prop_id, 
                                                 const GValue *value, GParamSpec *pspec);
@@ -83,6 +84,8 @@ static gboolean       gst_filesink_pad_query          (GstPad *pad, GstQueryType type,
                                                 GstFormat *format, gint64 *value);
 static void    gst_filesink_chain              (GstPad *pad,GstData *_data);
 
+static void    gst_filesink_uri_handler_init   (gpointer g_iface, gpointer iface_data);
+  
 static GstElementStateReturn gst_filesink_change_state (GstElement *element);
 
 static GstElementClass *parent_class = NULL;
@@ -105,7 +108,14 @@ gst_filesink_get_type (void)
       0,
       (GInstanceInitFunc)gst_filesink_init,
     };
+    static const GInterfaceInfo urihandler_info = {
+      gst_filesink_uri_handler_init,
+      NULL,
+      NULL
+    };
     filesink_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFileSink", &filesink_info, 0);
+    
+    g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER, &urihandler_info);
   
     GST_DEBUG_CATEGORY_INIT (gst_filesink_debug, "filesink", 0, "filesink element");
   }
@@ -138,8 +148,8 @@ gst_filesink_class_init (GstFileSinkClass *klass)
 
   gobject_class->set_property = gst_filesink_set_property;
   gobject_class->get_property = gst_filesink_get_property;
+  gobject_class->dispose      = gst_filesink_dispose;
 }
-
 static void 
 gst_filesink_init (GstFileSink *filesink) 
 {
@@ -158,7 +168,38 @@ gst_filesink_init (GstFileSink *filesink)
   filesink->filename = NULL;
   filesink->file = NULL;
 }
+static void
+gst_filesink_dispose (GObject *object)
+{
+  GstFileSink *sink = GST_FILESINK (object);
 
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+  
+  g_free (sink->uri);
+  sink->uri = NULL;
+  g_free (sink->filename);
+  sink->filename = NULL;
+}
+static gboolean
+gst_filesink_set_location (GstFileSink *sink, const gchar *location)
+{
+  /* the element must be stopped or paused in order to do this */
+  if (GST_STATE (sink) > GST_STATE_PAUSED)
+    return FALSE;
+  if (GST_STATE (sink) == GST_STATE_PAUSED &&
+      GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN))
+    return FALSE;
+
+  g_free (sink->filename);
+  g_free (sink->uri);
+  sink->filename = g_strdup (location);
+  sink->uri = gst_uri_construct ("file", location);
+  
+  if (GST_STATE (sink) == GST_STATE_PAUSED)
+    gst_filesink_open_file (sink);
+
+  return TRUE;
+}
 static void
 gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
@@ -169,16 +210,7 @@ gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value,
 
   switch (prop_id) {
     case ARG_LOCATION:
-      /* the element must be stopped or paused in order to do this */
-      g_return_if_fail (GST_STATE (sink) <= GST_STATE_PAUSED);
-      if (GST_STATE (sink) == GST_STATE_PAUSED)
-        g_return_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN));
-
-      if (sink->filename)
-       g_free (sink->filename);
-      sink->filename = g_strdup (g_value_get_string (value));
-      if (GST_STATE (sink) == GST_STATE_PAUSED)
-        gst_filesink_open_file (sink);   
+      gst_filesink_set_location (sink, g_value_get_string (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -435,3 +467,54 @@ gst_filesink_change_state (GstElement *element)
 
   return GST_STATE_SUCCESS;
 }
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static guint
+gst_filesink_uri_get_type (void)
+{
+  return GST_URI_SINK;
+}
+static gchar **
+gst_filesink_uri_get_protocols(void)
+{
+  static gchar *protocols[] = {"file", NULL};
+  return protocols;
+}
+static const gchar *
+gst_filesink_uri_get_uri (GstURIHandler *handler)
+{
+  GstFileSink *sink = GST_FILESINK (handler);
+  
+  return sink->uri;
+}
+static gboolean
+gst_filesink_uri_set_uri (GstURIHandler *handler, const gchar *uri)
+{
+  gchar *protocol, *location;
+  gboolean ret;
+  GstFileSink *sink = GST_FILESINK (handler);
+
+  protocol = gst_uri_get_protocol (uri);
+  if (strcmp (protocol, "file") != 0) {
+    g_free (protocol);
+    return FALSE;
+  }
+  g_free (protocol);
+  location = gst_uri_get_location (uri);
+  ret = gst_filesink_set_location (sink, location);
+  g_free (location);
+
+  return ret;
+}
+
+static void
+gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+  iface->get_type = gst_filesink_uri_get_type;
+  iface->get_protocols = gst_filesink_uri_get_protocols;
+  iface->get_uri = gst_filesink_uri_get_uri;
+  iface->set_uri = gst_filesink_uri_set_uri;
+}
index b72551b..bd85a1d 100644 (file)
@@ -53,6 +53,7 @@ struct _GstFileSink {
   GstElement element;
 
   gchar *filename;
+  gchar *uri;
   FILE *file;
 
   guint64 data_written;
index 275d730..e1d4bff 100644 (file)
@@ -136,6 +136,8 @@ static gboolean     gst_filesrc_srcpad_query        (GstPad *pad, GstQueryType type,
 
 static GstElementStateReturn   gst_filesrc_change_state        (GstElement *element);
 
+static void            gst_filesrc_uri_handler_init    (gpointer g_iface, gpointer iface_data);
+
 
 static GstElementClass *parent_class = NULL;
 /*static guint gst_filesrc_signals[LAST_SIGNAL] = { 0 };*/
@@ -157,8 +159,15 @@ gst_filesrc_get_type(void)
       0,
       (GInstanceInitFunc)gst_filesrc_init,
     };
+    static const GInterfaceInfo urihandler_info = {
+      gst_filesrc_uri_handler_init,
+      NULL,
+      NULL
+    };
     filesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFileSrc", &filesrc_info, 0);
-
+    
+    g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
+    
     GST_DEBUG_CATEGORY_INIT (gst_filesrc_debug, "filesrc", 0, "filesrc element");
   }
   return filesrc_type;
@@ -263,8 +272,32 @@ gst_filesrc_dispose (GObject *object)
   g_mutex_free (src->map_regions_lock);
   if (src->filename)
     g_free (src->filename);
+  if (src->uri)
+    g_free (src->uri);
 }
 
+static gboolean
+gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
+{
+  /* the element must be stopped in order to do this */
+  if (GST_STATE (src) == GST_STATE_PLAYING)
+    return FALSE;
+
+  if (src->filename) g_free (src->filename);
+  if (src->uri) g_free (src->uri);
+  /* clear the filename if we get a NULL (is that possible?) */
+  if (location == NULL) {
+    src->filename = NULL;
+    src->uri = NULL;
+  } else {
+    src->filename = g_strdup (location);
+    src->uri = gst_uri_construct ("file", src->filename);
+  }
+  g_object_notify (G_OBJECT (src), "location");
+  gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
+
+  return TRUE;
+}
 
 static void
 gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
@@ -278,19 +311,7 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
 
   switch (prop_id) {
     case ARG_LOCATION:
-      /* the element must be stopped in order to do this */
-      g_return_if_fail (GST_STATE (src) < GST_STATE_PLAYING);
-
-      if (src->filename) g_free (src->filename);
-      /* clear the filename if we get a NULL (is that possible?) */
-      if (g_value_get_string (value) == NULL) {
-        gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
-        src->filename = NULL;
-      /* otherwise set the new filename */
-      } else {
-        src->filename = g_strdup (g_value_get_string (value));
-      }
-      g_object_notify (G_OBJECT (src), "location");
+      gst_filesrc_set_location (src, g_value_get_string (value));
       break;
     case ARG_BLOCKSIZE:
       src->block_size = g_value_get_ulong (value);
@@ -918,3 +939,55 @@ error:
   gst_event_unref (event);
   return FALSE;
 }
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static guint
+gst_filesrc_uri_get_type (void)
+{
+  return GST_URI_SRC;
+}
+static gchar **
+gst_filesrc_uri_get_protocols(void)
+{
+  static gchar *protocols[] = {"file", NULL};
+  return protocols;
+}
+static const gchar *
+gst_filesrc_uri_get_uri (GstURIHandler *handler)
+{
+  GstFileSrc *src = GST_FILESRC (handler);
+  
+  return src->uri;
+}
+static gboolean
+gst_filesrc_uri_set_uri (GstURIHandler *handler, const gchar *uri)
+{
+  gchar *protocol, *location;
+  gboolean ret;
+  GstFileSrc *src = GST_FILESRC (handler);
+
+  protocol = gst_uri_get_protocol (uri);
+  if (strcmp (protocol, "file") != 0) {
+    g_free (protocol);
+    return FALSE;
+  }
+  g_free (protocol);
+  location = gst_uri_get_location (uri);
+  ret = gst_filesrc_set_location (src, location);
+  g_free (location);
+
+  return ret;
+}
+
+static void
+gst_filesrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+  iface->get_type = gst_filesrc_uri_get_type;
+  iface->get_protocols = gst_filesrc_uri_get_protocols;
+  iface->get_uri = gst_filesrc_uri_get_uri;
+  iface->set_uri = gst_filesrc_uri_set_uri;
+}
+
index 23b6dde..1f584be 100644 (file)
@@ -58,6 +58,7 @@ struct _GstFileSrc {
   guint pagesize;                      /* system page size*/
  
   gchar *filename;                     /* filename */
+  gchar *uri;                          /* caching the URI */
   gint fd;                             /* open file descriptor*/
   off_t filelen;                       /* what's the file length?*/
 
index 366ea8a..3192922 100644 (file)
@@ -874,16 +874,6 @@ print_element_list (void)
         g_print ("%s:  %s: %s\n", plugin->desc.name,
                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
       }
-#ifndef GST_DISABLE_URI
-      else if (GST_IS_URI_HANDLER (feature)) {
-        GstURIHandler *handler;
-
-        handler = GST_URI_HANDLER (feature);
-        g_print ("%s:  %s: \"%s\" (%s) element \"%s\" property \"%s\"\n",
-                plugin->desc.name, GST_PLUGIN_FEATURE_NAME (handler), handler->uri,
-                handler->longdesc, handler->element, handler->property);
-      }
-#endif
       else {
         g_print ("%s:  %s (%s)\n", plugin->desc.name,
                 GST_PLUGIN_FEATURE_NAME (feature),
index 89d1c03..3467e58 100644 (file)
@@ -867,16 +867,6 @@ print_element_list (void)
         g_print ("%s:  %s: %s\n", plugin->desc.name,
                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
       }
-#ifndef GST_DISABLE_URI
-      else if (GST_IS_URI_HANDLER (feature)) {
-        GstURIHandler *handler;
-
-        handler = GST_URI_HANDLER (feature);
-        g_print ("%s:  %s: \"%s\" (%s) element \"%s\" property \"%s\"\n",
-                 plugin->desc.name, GST_PLUGIN_FEATURE_NAME (handler), handler->uri,
-                 handler->longdesc, handler->element, handler->property);
-      }
-#endif
       else {
         g_print ("%s:  %s (%s)\n", plugin->desc.name,
                 GST_PLUGIN_FEATURE_NAME (feature),