mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 09:25:42 +00:00
implement URI schemes
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
This commit is contained in:
parent
4e8fb08626
commit
25f85868d4
24 changed files with 1027 additions and 439 deletions
|
@ -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>
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ struct _GstFileSink {
|
|||
GstElement element;
|
||||
|
||||
gchar *filename;
|
||||
gchar *uri;
|
||||
FILE *file;
|
||||
|
||||
guint64 data_written;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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?*/
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -433,6 +459,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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
505
gst/gsturi.c
505
gst/gsturi.c
|
@ -20,17 +20,22 @@
|
|||
* 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"
|
||||
|
||||
static void gst_uri_handler_class_init (GstURIHandlerClass *klass);
|
||||
static void gst_uri_handler_init (GstURIHandler *factory);
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static GstPluginFeatureClass *parent_class = NULL;
|
||||
/* static guint gst_uri_handler_signals[LAST_SIGNAL] = { 0 }; */
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_uri_handler_debug);
|
||||
#define GST_CAT_DEFAULT gst_uri_handler_debug
|
||||
|
||||
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_base_init (gpointer g_class)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
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_class_init (GstURIHandlerClass *klass)
|
||||
gst_uri_protocol_check_internal (const gchar *uri, gchar **endptr)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstObjectClass *gstobject_class;
|
||||
GstPluginFeatureClass *gstpluginfeature_class;
|
||||
gchar *check = (gchar *) uri;
|
||||
|
||||
g_assert (uri != NULL);
|
||||
g_assert (endptr != NULL);
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstobject_class = (GstObjectClass*)klass;
|
||||
gstpluginfeature_class = (GstPluginFeatureClass*) klass;
|
||||
if (isalpha (*check)) {
|
||||
check++;
|
||||
while (isalnum (*check)) check++;
|
||||
}
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
|
||||
*endptr = check;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_uri_handler_init (GstURIHandler *factory)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_protocol_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 protocol identifier. Protocols
|
||||
* must consist of alphanumeric characters and not start with a number.
|
||||
*
|
||||
* Returns: the new urihandler
|
||||
*/
|
||||
GstURIHandler*
|
||||
gst_uri_handler_new (const gchar *name,
|
||||
const gchar *uri, const gchar *longdesc,
|
||||
const gchar *element, gchar *property)
|
||||
{
|
||||
GstURIHandler *factory;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_uri_handler_find:
|
||||
* @name: the name of the urihandler to find
|
||||
*
|
||||
* Return the URIHandler with the given name.
|
||||
*
|
||||
* Returns: a GstURIHandler with the given name;
|
||||
*/
|
||||
GstURIHandler*
|
||||
gst_uri_handler_find (const gchar *name)
|
||||
{
|
||||
GstPluginFeature *feature;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
feature = gst_registry_pool_find_feature (name, GST_TYPE_URI_HANDLER);
|
||||
if (feature)
|
||||
return GST_URI_HANDLER (feature);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
static gboolean
|
||||
g_str_has_prefix_glib22 (gchar *haystack, gchar *needle)
|
||||
{
|
||||
if (haystack == NULL && needle == NULL) {
|
||||
return TRUE;
|
||||
}
|
||||
if (haystack == NULL || needle == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
if (strncmp (haystack, needle, strlen (needle)) == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_uri_handler_uri_filter:
|
||||
* @feature: the feature to inspect
|
||||
* @uri: the name of the uri to match
|
||||
*
|
||||
* 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.
|
||||
* Returns: TRUE if the string is a valid protocol identifier
|
||||
*/
|
||||
gboolean
|
||||
gst_uri_handler_uri_filter (GstPluginFeature *feature, const gchar *uri)
|
||||
gst_uri_protocol_is_valid (const gchar *protocol)
|
||||
{
|
||||
if (G_OBJECT_TYPE (feature) == GST_TYPE_URI_HANDLER) {
|
||||
GstURIHandler *handler = GST_URI_HANDLER (feature);
|
||||
gchar *endptr;
|
||||
|
||||
if (g_str_has_prefix_glib22 ((gchar *) uri, handler->uri)) {
|
||||
g_return_val_if_fail (protocol != NULL, FALSE);
|
||||
|
||||
gst_uri_protocol_check_internal (protocol, &endptr);
|
||||
|
||||
return *endptr == '\0' && endptr != protocol;
|
||||
}
|
||||
/**
|
||||
* gst_uri_is_valid:
|
||||
* @protocol: string to check
|
||||
*
|
||||
* 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: TRUE if the string is a valid URI
|
||||
*/
|
||||
gboolean
|
||||
gst_uri_is_valid (const gchar *uri)
|
||||
{
|
||||
gchar *endptr;
|
||||
|
||||
g_return_val_if_fail (uri != NULL, FALSE);
|
||||
|
||||
gst_uri_protocol_check_internal (uri, &endptr);
|
||||
|
||||
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 (gst_uri_is_valid (uri), NULL);
|
||||
|
||||
colon = strstr (uri, "://");
|
||||
|
||||
return g_strndup (uri, colon - uri);
|
||||
}
|
||||
/**
|
||||
* gst_uri_get_location:
|
||||
* @uri: URI to get the location from
|
||||
*
|
||||
* 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: The location for this URI.
|
||||
*/
|
||||
gchar *
|
||||
gst_uri_get_location (const gchar *uri)
|
||||
{
|
||||
gchar *colon;
|
||||
|
||||
g_return_val_if_fail (uri != NULL, NULL);
|
||||
g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
|
||||
|
||||
colon = strstr (uri, "://");
|
||||
|
||||
return g_strdup (colon + 3);
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
search_by_entry (GstPluginFeature *feature, gpointer search_entry)
|
||||
{
|
||||
gchar **protocols;
|
||||
GstElementFactory *factory;
|
||||
SearchEntry *entry = (SearchEntry *) search_entry;
|
||||
|
||||
if (!GST_IS_ELEMENT_FACTORY (feature))
|
||||
return FALSE;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_uri_handler_find_by_uri:
|
||||
* @uri: the uri to find a handler for
|
||||
*
|
||||
* Find a URIHandler for the given uri.
|
||||
*
|
||||
* Returns: a GstURIHandler that can handle the given uri.
|
||||
*/
|
||||
GstURIHandler*
|
||||
gst_uri_handler_find_by_uri (const gchar *uri)
|
||||
static gint
|
||||
sort_by_rank (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
GList *walk;
|
||||
GstURIHandler *result = NULL;
|
||||
|
||||
g_return_val_if_fail (uri != NULL, NULL);
|
||||
GstPluginFeature *first = GST_PLUGIN_FEATURE (a);
|
||||
GstPluginFeature *second = GST_PLUGIN_FEATURE (b);
|
||||
|
||||
walk = gst_registry_pool_feature_filter (
|
||||
(GstPluginFeatureFilter) gst_uri_handler_uri_filter, TRUE, (gpointer) uri);
|
||||
return gst_plugin_feature_get_rank (second) - gst_plugin_feature_get_rank (first);
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Creates an element for handling the given URI.
|
||||
*
|
||||
* Returns: a new element or NULL if none could be created
|
||||
*/
|
||||
GstElement *
|
||||
gst_element_make_from_uri (const GstURIType type, const gchar *uri, const gchar *elementname)
|
||||
{
|
||||
GList *possibilities, *walk;
|
||||
SearchEntry entry;
|
||||
GstElement *ret = NULL;
|
||||
|
||||
if (walk) {
|
||||
result = GST_URI_HANDLER (walk->data);
|
||||
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;
|
||||
}
|
||||
g_list_free (walk);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_uri_handler_create:
|
||||
* @handler: the uri handler to use
|
||||
* @name: the name of the element
|
||||
*
|
||||
* Create an element with the given name from the given handler.
|
||||
*
|
||||
* Returns: a new element associated with the handler.
|
||||
*/
|
||||
GstElement*
|
||||
gst_uri_handler_create (GstURIHandler *handler, const gchar *name)
|
||||
{
|
||||
GstElement *element = NULL;
|
||||
|
||||
g_return_val_if_fail (handler != NULL, NULL);
|
||||
|
||||
element = gst_element_factory_make (handler->element, name);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_uri_handler_make_by_uri:
|
||||
* @uri: the uri
|
||||
* @name: the name of the element
|
||||
*
|
||||
* Create an element with the given name that can handle the given
|
||||
* uri. This function will also use set the uri on the element.
|
||||
*
|
||||
* Returns: a new element that can handle the uri.
|
||||
*/
|
||||
GstElement*
|
||||
gst_uri_handler_make_by_uri (const gchar *uri, const gchar *name)
|
||||
{
|
||||
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);
|
||||
|
||||
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 element;
|
||||
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_get_uri_type:
|
||||
* @handler: Handler to query type of
|
||||
*
|
||||
* Gets the type of a URI handler
|
||||
*
|
||||
* Returns: the type of the URI handler
|
||||
*/
|
||||
guint
|
||||
gst_uri_handler_get_uri_type (GstURIHandler *handler)
|
||||
{
|
||||
GstURIHandlerInterface *iface;
|
||||
guint ret;
|
||||
|
||||
g_return_val_if_fail (GST_IS_URI_HANDLER (handler), GST_URI_UNKNOWN);
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* gst_uri_handler_get_protocols:
|
||||
* @handler: Handler to get protocols for
|
||||
*
|
||||
* Gets the list of supported protocols for this handler. This list may not be
|
||||
* modified.
|
||||
*
|
||||
* Returns: the supported protocols
|
||||
*/
|
||||
gchar **
|
||||
gst_uri_handler_get_protocols (GstURIHandler *handler)
|
||||
{
|
||||
GstURIHandlerInterface *iface;
|
||||
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_protocols != NULL, NULL);
|
||||
ret = iface->get_protocols ();
|
||||
g_return_val_if_fail (ret != NULL, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* gst_uri_handler_get_uri:
|
||||
* @handler: handler to query URI of
|
||||
*
|
||||
* Gets the currently handled URI of the handler or NULL, if none is set.
|
||||
*
|
||||
* Returns: the URI
|
||||
*/
|
||||
G_CONST_RETURN gchar *
|
||||
gst_uri_handler_get_uri (GstURIHandler *handler)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
78
gst/gsturi.h
78
gst/gsturi.h
|
@ -30,50 +30,76 @@
|
|||
|
||||
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 */
|
||||
|
||||
struct _GstURIHandlerClass {
|
||||
GstPluginFeatureClass parent;
|
||||
/* querying capabilities */
|
||||
GstURIType (* get_type) (void);
|
||||
gchar ** (* get_protocols) (void);
|
||||
|
||||
/* 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__ */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
@ -812,30 +826,6 @@ gst_xml_registry_parse_index_factory (GMarkupParseContext *context, const gchar
|
|||
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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ struct _GstFileSink {
|
|||
GstElement element;
|
||||
|
||||
gchar *filename;
|
||||
gchar *uri;
|
||||
FILE *file;
|
||||
|
||||
guint64 data_written;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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?*/
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue