@parent:
@Returns:
+<!-- ##### FUNCTION gst_uri_handler_create ##### -->
+<para>
+
+</para>
+
+@handler:
+@name:
+@Returns:
+
<!-- ##### FUNCTION gst_uri_handler_destroy ##### -->
<para>
@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>
</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:
-
-
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);
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);
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;
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");
}
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)
{
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)
{
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);
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;
+}
GstElement element;
gchar *filename;
+ gchar *uri;
FILE *file;
guint64 data_written;
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 };*/
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;
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)
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);
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;
+}
+
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?*/
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
};
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);
#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
factory->padtemplates = NULL;
factory->numpadtemplates = 0;
+ factory->uri_type = GST_URI_UNKNOWN;
+ factory->uri_protocols = NULL;
+
factory->interfaces = NULL;
}
/**
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);
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]));
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:
* 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
*/
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
* 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));
feature->rank = rank;
}
/**
- * gst_plugin_feature_set_rank:
+ * gst_plugin_feature_set_name:
* @feature: a feature
* @name: the name to set
*
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;
+}
struct _GstPluginFeature {
GObject object;
+ /*< private >*/
gchar *name;
- gint rank;
+ guint rank;
- /* --- private --- */
gpointer manager;
GST_OBJECT_PADDING
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
* 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)
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);
+}
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__ */
#include "../gst_private.h"
+#include "../gstconfig.h"
#include "../gstparse.h"
#include "../gstinfo.h"
+#include "../gsturi.h"
#include "types.h"
#define YYERROR_VERBOSE 1
} \
}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
} \
}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
} \
}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
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)
{
graph_t *g;
}
+%token <s> PARSE_URL
%token <s> IDENTIFIER
%left <s> REF PADREF BINREF
%token <s> ASSIGNMENT
%type <l> reference
%type <l> linkpart link
%type <p> linklist
-%type <e> element
+%type <e> element
%type <p> padlist pads assignments
%left '{' '}' '(' ')'
$$ = $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);
}
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);
$$ = $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;
}
dstr = g_strdup (str);
_gst_parse_yy_scan_string (dstr);
-#ifdef GST_DEBUG_ENABLED
+#ifndef GST_DISABLE_GST_DEBUG
yydebug = 1;
#endif
#include "types.h"
#include "../gstinfo.h"
+#include "../gsturi.h"
#include "grammar.tab.h"
#ifdef G_HAVE_ISO_VARARGS
_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}
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; }
# 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__ */
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)
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);
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;
}
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)
{
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");
}
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);
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)
{
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);
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);
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;
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");
}
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)
{
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)
{
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);
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;
+}
GstElement element;
gchar *filename;
+ gchar *uri;
FILE *file;
guint64 data_written;
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 };*/
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;
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)
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);
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;
+}
+
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?*/
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),
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),