2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gsturi.c: register URI handlers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
29 #include "gstregistrypool.h"
30 #include "gstmarshal.h"
34 GST_DEBUG_CATEGORY_STATIC (gst_uri_handler_debug);
35 #define GST_CAT_DEFAULT gst_uri_handler_debug
37 static void gst_uri_handler_base_init (gpointer g_class);
40 gst_uri_handler_get_type (void)
42 static GType urihandler_type = 0;
44 if (!urihandler_type) {
45 static const GTypeInfo urihandler_info = {
46 sizeof (GstURIHandlerInterface),
47 gst_uri_handler_base_init,
58 urihandler_type = g_type_register_static (G_TYPE_INTERFACE,
59 "GstURIHandler", &urihandler_info, 0);
61 GST_DEBUG_CATEGORY_INIT (gst_uri_handler_debug, "GST_URI", GST_DEBUG_BOLD,
64 return urihandler_type;
67 gst_uri_handler_base_init (gpointer g_class)
69 static gboolean initialized = FALSE;
72 g_signal_new ("new-uri", GST_TYPE_URI_HANDLER, G_SIGNAL_RUN_LAST,
73 G_STRUCT_OFFSET (GstURIHandlerInterface, new_uri), NULL, NULL,
74 gst_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
80 gst_uri_protocol_check_internal (const gchar * uri, gchar ** endptr)
82 gchar *check = (gchar *) uri;
84 g_assert (uri != NULL);
85 g_assert (endptr != NULL);
87 if (g_ascii_isalpha (*check)) {
89 while (g_ascii_isalnum (*check))
97 * gst_uri_protocol_is_valid:
98 * @protocol: string to check
100 * Tests if the given string is a valid protocol identifier. Protocols
101 * must consist of alphanumeric characters and not start with a number.
103 * Returns: TRUE if the string is a valid protocol identifier
106 gst_uri_protocol_is_valid (const gchar * protocol)
110 g_return_val_if_fail (protocol != NULL, FALSE);
112 gst_uri_protocol_check_internal (protocol, &endptr);
114 return *endptr == '\0' && endptr != protocol;
119 * @protocol: string to check
121 * Tests if the given string is a valid URI identifier. URIs start with a valid
122 * protocol followed by "://" and a string identifying the location.
124 * Returns: TRUE if the string is a valid URI
127 gst_uri_is_valid (const gchar * uri)
131 g_return_val_if_fail (uri != NULL, FALSE);
133 gst_uri_protocol_check_internal (uri, &endptr);
135 return (*endptr == ':' && *(endptr + 1) == '/' && *(endptr + 2) == '/');
139 * gst_uri_get_protocol:
140 * @uri: URI to get protocol from
142 * Extracts the protocol out of a given valid URI. The returned string must be
143 * freed using g_free().
145 * Returns: The protocol for this URI.
148 gst_uri_get_protocol (const gchar * uri)
152 g_return_val_if_fail (uri != NULL, NULL);
153 g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
155 colon = strstr (uri, "://");
157 return g_strndup (uri, colon - uri);
161 * gst_uri_get_location:
162 * @uri: URI to get the location from
164 * Extracts the location out of a given valid URI. So the protocol and "://"
165 * are stripped from the URI. The returned string must be freed using
168 * Returns: The location for this URI.
171 gst_uri_get_location (const gchar * uri)
175 g_return_val_if_fail (uri != NULL, NULL);
176 g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
178 colon = strstr (uri, "://");
180 return g_strdup (colon + 3);
185 * @protocol: protocol for URI
186 * @location: location for URI
188 * Constructs a URI for a given valid protocol and location.
190 * Returns: a new string for this URI
193 gst_uri_construct (const gchar * protocol, const gchar * location)
195 g_return_val_if_fail (gst_uri_protocol_is_valid (protocol), NULL);
196 g_return_val_if_fail (location != NULL, NULL);
198 return g_strdup_printf ("%s://%s", protocol, location);
207 search_by_entry (GstPluginFeature * feature, gpointer search_entry)
210 GstElementFactory *factory;
211 SearchEntry *entry = (SearchEntry *) search_entry;
213 if (!GST_IS_ELEMENT_FACTORY (feature))
215 factory = GST_ELEMENT_FACTORY (feature);
217 if (gst_element_factory_get_uri_type (factory) != entry->type)
220 protocols = gst_element_factory_get_uri_protocols (factory);
221 /* must be set when uri type is valid */
222 g_assert (protocols);
223 while (*protocols != NULL) {
224 if (strcmp (*protocols, entry->protocol) == 0)
232 sort_by_rank (gconstpointer a, gconstpointer b)
234 GstPluginFeature *first = GST_PLUGIN_FEATURE (a);
235 GstPluginFeature *second = GST_PLUGIN_FEATURE (b);
237 return gst_plugin_feature_get_rank (second) -
238 gst_plugin_feature_get_rank (first);
242 * gst_element_make_from_uri:
243 * @type: wether to create a source or a sink
244 * @uri: URI to create element for
245 * @elementname: optional name of created element
247 * Creates an element for handling the given URI.
249 * Returns: a new element or NULL if none could be created
252 gst_element_make_from_uri (const GstURIType type, const gchar * uri,
253 const gchar * elementname)
255 GList *possibilities, *walk;
257 GstElement *ret = NULL;
259 g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL);
260 g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
263 entry.protocol = gst_uri_get_protocol (uri);
265 gst_registry_pool_feature_filter (search_by_entry, FALSE, &entry);
266 g_free (entry.protocol);
268 if (!possibilities) {
269 GST_DEBUG ("No %s for URI '%s'", type == GST_URI_SINK ? "sink" : "source",
274 possibilities = g_list_sort (possibilities, sort_by_rank);
275 walk = possibilities;
277 if ((ret = gst_element_factory_create (GST_ELEMENT_FACTORY (walk->data),
278 elementname)) != NULL) {
279 GstURIHandler *handler = GST_URI_HANDLER (ret);
281 if (gst_uri_handler_set_uri (handler, uri))
283 g_object_unref (ret);
287 g_list_free (possibilities);
289 GST_LOG_OBJECT (ret, "created %s for URL '%s'",
290 type == GST_URI_SINK ? "sink" : "source", uri);
295 * gst_uri_handler_get_uri_type:
296 * @handler: Handler to query type of
298 * Gets the type of a URI handler
300 * Returns: the type of the URI handler
303 gst_uri_handler_get_uri_type (GstURIHandler * handler)
305 GstURIHandlerInterface *iface;
308 g_return_val_if_fail (GST_IS_URI_HANDLER (handler), GST_URI_UNKNOWN);
310 iface = GST_URI_HANDLER_GET_INTERFACE (handler);
311 g_return_val_if_fail (iface != NULL, GST_URI_UNKNOWN);
312 g_return_val_if_fail (iface->get_type != NULL, GST_URI_UNKNOWN);
313 ret = iface->get_type ();
314 g_return_val_if_fail (GST_URI_TYPE_IS_VALID (ret), GST_URI_UNKNOWN);
320 * gst_uri_handler_get_protocols:
321 * @handler: Handler to get protocols for
323 * Gets the list of supported protocols for this handler. This list may not be
326 * Returns: the supported protocols
329 gst_uri_handler_get_protocols (GstURIHandler * handler)
331 GstURIHandlerInterface *iface;
334 g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL);
336 iface = GST_URI_HANDLER_GET_INTERFACE (handler);
337 g_return_val_if_fail (iface != NULL, NULL);
338 g_return_val_if_fail (iface->get_protocols != NULL, NULL);
339 ret = iface->get_protocols ();
340 g_return_val_if_fail (ret != NULL, NULL);
346 * gst_uri_handler_get_uri:
347 * @handler: handler to query URI of
349 * Gets the currently handled URI of the handler or NULL, if none is set.
353 G_CONST_RETURN gchar *
354 gst_uri_handler_get_uri (GstURIHandler * handler)
356 GstURIHandlerInterface *iface;
359 g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL);
361 iface = GST_URI_HANDLER_GET_INTERFACE (handler);
362 g_return_val_if_fail (iface != NULL, NULL);
363 g_return_val_if_fail (iface->get_uri != NULL, NULL);
364 ret = iface->get_uri (handler);
366 g_return_val_if_fail (gst_uri_is_valid (ret), NULL);
372 * gst_uri_handler_set_uri:
373 * @handler: handler to set URI of
376 * Tries to set the URI of the given handler and returns TRUE if it succeeded.
378 * Returns: TRUE, if the URI was set successfully
381 gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
383 GstURIHandlerInterface *iface;
385 g_return_val_if_fail (GST_IS_URI_HANDLER (handler), FALSE);
386 g_return_val_if_fail (gst_uri_is_valid (uri), FALSE);
388 iface = GST_URI_HANDLER_GET_INTERFACE (handler);
389 g_return_val_if_fail (iface != NULL, FALSE);
390 g_return_val_if_fail (iface->set_uri != NULL, FALSE);
391 return iface->set_uri (handler, uri);
395 * gst_uri_handler_new_uri:
396 * @handler: handler with a new URI
397 * @uri: new URI or NULL if it was unset
399 * Emits the new-uri event for a given handler, when that handler has a new URI.
400 * This function should only be called by URI handlers themselves.
403 gst_uri_handler_new_uri (GstURIHandler * handler, const gchar * uri)
405 g_return_if_fail (GST_IS_URI_HANDLER (handler));
407 g_signal_emit_by_name (handler, "new-uri", uri);