*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
* SECTION:gsturihandler
* @short_description: Interface to ease URI handling in plugins.
*
- * The URIHandler is an interface that is implemented by Source and Sink
+ * The URIHandler is an interface that is implemented by Source and Sink
* #GstElement to simplify then handling of URI.
*
* An application can use the following functions to quickly get an element
* (gst_element_make_from_uri()).
*
* Source and Sink plugins should implement this interface when possible.
- *
- * Last reviewed on 2005-11-09 (0.9.4)
*/
#ifdef HAVE_CONFIG_H
#endif
#include "gst_private.h"
+#include "gst.h"
#include "gsturi.h"
#include "gstinfo.h"
-#include "gstmarshal.h"
#include "gstregistry.h"
#include "gst-i18n-lib.h"
* must consist of alphanumeric characters, '+', '-' and '.' and must
* start with a alphabetic character. See RFC 3986 Section 3.1.
*
- * Returns: TRUE if the string is a valid protocol identifier, FALSE otherwise.
+ * Returns: %TRUE if the string is a valid protocol identifier, %FALSE otherwise.
*/
gboolean
gst_uri_protocol_is_valid (const gchar * protocol)
gst_uri_protocol_check_internal (protocol, &endptr);
- return *endptr == '\0' && endptr != protocol;
+ return *endptr == '\0' && ((gsize) (endptr - protocol)) >= 2;
}
/**
* Tests if the given string is a valid URI identifier. URIs start with a valid
* scheme followed by ":" and maybe a string identifying the location.
*
- * Returns: TRUE if the string is a valid URI
+ * Returns: %TRUE if the string is a valid URI
*/
gboolean
gst_uri_is_valid (const gchar * uri)
gst_uri_protocol_check_internal (uri, &endptr);
- return *endptr == ':';
+ return *endptr == ':' && ((gsize) (endptr - uri)) >= 2;
}
/**
* Checks if the protocol of a given valid URI matches @protocol.
*
* Returns: %TRUE if the protocol matches.
- *
- * Since: 0.10.4
*/
gboolean
gst_uri_has_protocol (const gchar * uri, const gchar * protocol)
*
* Free-function: g_free
*
- * Returns: (transfer full) (array zero-terminated=1): the location for this
- * URI. Returns NULL if the URI isn't valid. If the URI does not contain
- * a location, an empty string is returned.
+ * Returns: (transfer full): the location for this URI. Returns %NULL if the
+ * URI isn't valid. If the URI does not contain a location, an empty
+ * string is returned.
*/
gchar *
gst_uri_get_location (const gchar * uri)
g_ascii_isalpha (unescaped[1]) &&
(unescaped[2] == ':' || unescaped[2] == '|')) {
unescaped[2] = ':';
- g_memmove (unescaped, unescaped + 1, strlen (unescaped + 1) + 1);
+ memmove (unescaped, unescaped + 1, strlen (unescaped + 1) + 1);
}
#endif
/**
* gst_uri_construct:
* @protocol: Protocol for URI
- * @location: (array zero-terminated=1) (transfer none): Location for URI
+ * @location: (transfer none): Location for URI
*
* Constructs a URI for a given valid protocol and location.
*
* Free-function: g_free
*
- * Returns: (transfer full) (array zero-terminated=1): a new string for this
- * URI. Returns NULL if the given URI protocol is not valid, or the given
- * location is NULL.
+ * Returns: (transfer full): a new string for this URI. Returns %NULL if the
+ * given URI protocol is not valid, or the given location is %NULL.
*/
gchar *
gst_uri_construct (const gchar * protocol, const gchar * location)
* that a positive return value does not imply that a subsequent call to
* gst_element_make_from_uri() is guaranteed to work.
*
- * Returns: TRUE
- *
- * Since: 0.10.13
+ * Returns: %TRUE
*/
gboolean
gst_uri_protocol_is_supported (const GstURIType type, const gchar * protocol)
* gst_element_make_from_uri:
* @type: Whether to create a source or a sink
* @uri: URI to create an element for
- * @elementname: (allow-none): Name of created element, can be NULL.
+ * @elementname: (allow-none): Name of created element, can be %NULL.
+ * @error: (allow-none): address where to store error information, or %NULL.
*
* Creates an element for handling the given URI.
*
- * Returns: (transfer full): a new element or NULL if none could be created
+ * Returns: (transfer floating): 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)
+ const gchar * elementname, GError ** error)
{
GList *possibilities, *walk;
gchar *protocol;
GstElement *ret = NULL;
+ g_return_val_if_fail (gst_is_initialized (), NULL);
g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL);
g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ GST_DEBUG ("type:%d, uri:%s, elementname:%s", type, uri, elementname);
protocol = gst_uri_get_protocol (uri);
possibilities = get_element_factories_from_uri_protocol (type, protocol);
- g_free (protocol);
if (!possibilities) {
GST_DEBUG ("No %s for URI '%s'", type == GST_URI_SINK ? "sink" : "source",
uri);
+ /* The error message isn't great, but we don't expect applications to
+ * show that error to users, but call the missing plugins functions */
+ g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_UNSUPPORTED_PROTOCOL,
+ _("No URI handler for the %s protocol found"), protocol);
+ g_free (protocol);
return NULL;
}
+ g_free (protocol);
possibilities = g_list_sort (possibilities, (GCompareFunc) sort_by_rank);
walk = possibilities;
while (walk) {
- if ((ret =
- gst_element_factory_create (GST_ELEMENT_FACTORY_CAST (walk->data),
- elementname)) != NULL) {
+ GstElementFactory *factory = walk->data;
+ GError *uri_err = NULL;
+
+ ret = gst_element_factory_create (factory, elementname);
+ if (ret != NULL) {
GstURIHandler *handler = GST_URI_HANDLER (ret);
- if (gst_uri_handler_set_uri (handler, uri, NULL))
+ if (gst_uri_handler_set_uri (handler, uri, &uri_err))
break;
+
+ GST_WARNING ("%s didn't accept URI '%s': %s", GST_OBJECT_NAME (ret), uri,
+ uri_err->message);
+
+ if (error != NULL && *error == NULL)
+ g_propagate_error (error, uri_err);
+ else
+ g_error_free (uri_err);
+
gst_object_unref (ret);
ret = NULL;
}
GST_LOG_OBJECT (ret, "created %s for URL '%s'",
type == GST_URI_SINK ? "sink" : "source", uri);
+
+ /* if the first handler didn't work, but we found another one that works */
+ if (ret != NULL)
+ g_clear_error (error);
+
return ret;
}
* Gets the list of protocols supported by @handler. This list may not be
* modified.
*
- * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): the
- * supported protocols. Returns NULL if the @handler isn't implemented
- * properly, or the @handler doesn't support any protocols.
+ * Returns: (transfer none) (element-type utf8): the supported protocols.
+ * Returns %NULL if the @handler isn't implemented properly, or the @handler
+ * doesn't support any protocols.
*/
const gchar *const *
gst_uri_handler_get_protocols (GstURIHandler * handler)
* Gets the currently handled URI.
*
* Returns: (transfer full): the URI currently handled by the @handler.
- * Returns NULL if there are no URI currently handled. The
+ * Returns %NULL if there are no URI currently handled. The
* returned string must be freed with g_free() when no longer needed.
*/
gchar *
* @handler: A #GstURIHandler
* @uri: URI to set
* @error: (allow-none): address where to store a #GError in case of
- * an error, or NULL
+ * an error, or %NULL
*
* Tries to set the URI of the given handler.
*
- * Returns: TRUE if the URI was set successfully, else FALSE.
+ * Returns: %TRUE if the URI was set successfully, else %FALSE.
*/
gboolean
gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri,
}
if (!found_protocol) {
- g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_PROTOCOL,
+ g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_UNSUPPORTED_PROTOCOL,
_("URI scheme '%s' not supported"), protocol);
g_free (protocol);
return FALSE;
if (strcmp (*p, ".") == 0) {
/* just move all following parts on top of this, incl. NUL terminator */
g_free (*p);
- g_memmove (p, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *));
+ memmove (p, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *));
/* re-check the new current part again in the next iteration */
continue;
} else if (strcmp (*p, "..") == 0 && p > parts) {
* NUL terminator */
g_free (*(p - 1));
g_free (*p);
- g_memmove (p - 1, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *));
+ memmove (p - 1, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *));
/* re-check the new current part again in the next iteration */
--p;
continue;
num_parts = g_strv_length (parts) + 1; /* incl. terminator */
parts = g_renew (gchar *, parts, num_parts + 1);
- g_memmove (parts + 1, parts, num_parts * sizeof (gchar *));
+ memmove (parts + 1, parts, num_parts * sizeof (gchar *));
parts[0] = g_strdup ("/");
}
/**
* gst_filename_to_uri:
* @filename: absolute or relative file name path
- * @error: pointer to error, or NULL
+ * @error: pointer to error, or %NULL
*
* Similar to g_filename_to_uri(), but attempts to handle relative file paths
* as well. Before converting @filename into an URI, it will be prefixed by
* will be canonicalised so that it doesn't contain any './' or '../' segments.
*
* On Windows #filename should be in UTF-8 encoding.
- *
- * Since: 0.10.33
*/
gchar *
gst_filename_to_uri (const gchar * filename, GError ** error)