return result;
}
-static GstPad *
-_gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
- const gchar * name, const GstCaps * caps)
+static gboolean
+gst_element_is_valid_request_template_name (const gchar * templ_name,
+ const gchar * name)
{
- GstPad *newpad = NULL;
- GstElementClass *oclass;
+ gchar *endptr;
+ const gchar *templ_name_ptr, *name_ptr;
+ gboolean next_specifier;
+ guint templ_postfix_len = 0, name_postfix_len = 0;
- oclass = GST_ELEMENT_GET_CLASS (element);
+ g_return_val_if_fail (templ_name != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
-#ifndef G_DISABLE_CHECKS
- /* Some sanity checking here */
- if (name) {
- GstPad *pad;
+ /* Is this the template name? */
+ if (strcmp (templ_name, name) == 0)
+ return TRUE;
- /* Is this the template name? */
- if (strstr (name, "%") || !strchr (templ->name_template, '%')) {
- g_return_val_if_fail (strcmp (name, templ->name_template) == 0, NULL);
- } else {
- const gchar *str, *data;
- gchar *endptr;
+ /* otherwise check all the specifiers */
+ do {
+ /* Because of sanity checks in gst_pad_template_new(), we know that %s
+ * and %d and %u, occurring at the template_name */
+ templ_name_ptr = strchr (templ_name, '%');
+
+ /* check characters ahead of the specifier */
+ if (!templ_name_ptr || strlen (name) <= templ_name_ptr - templ_name
+ || strncmp (templ_name, name, templ_name_ptr - templ_name) != 0) {
+ return FALSE;
+ }
+
+ /* %s is not allowed for multiple specifiers, just a single specifier can be
+ * accepted in gst_pad_template_new() and can not be mixed with other
+ * specifier '%u' and '%d' */
+ if (*(templ_name_ptr + 1) == 's' && g_strcmp0 (templ_name, name) == 0) {
+ return TRUE;
+ }
+
+ name_ptr = name + (templ_name_ptr - templ_name);
+
+ /* search next specifier, each of specifier should be separated by '_' */
+ templ_name = strchr (templ_name_ptr, '_');
+ name = strchr (name_ptr, '_');
+
+ /* don't match the number of specifiers */
+ if ((templ_name && !name) || (!templ_name && name))
+ return FALSE;
+
+ if (templ_name && name)
+ next_specifier = TRUE;
+ else
+ next_specifier = FALSE;
+
+ /* check characters followed by the specifier */
+ if (*(templ_name_ptr + 2) != '\0' && *(templ_name_ptr + 2) != '_') {
+ if (next_specifier) {
+ templ_postfix_len = templ_name - (templ_name_ptr + 2);
+ name_postfix_len = name - name_ptr;
+ } else {
+ templ_postfix_len = strlen (templ_name_ptr + 2);
+ name_postfix_len = strlen (name_ptr);
+ }
+
+ if (strncmp (templ_name_ptr + 2,
+ name_ptr + name_postfix_len - templ_postfix_len,
+ templ_postfix_len) != 0) {
+ return FALSE;
+ }
+ }
+
+ /* verify the specifier */
+ if (*(name_ptr) == '%') {
+ guint len;
+
+ len = (next_specifier) ? name - name_ptr : strlen (name_ptr);
- /* Otherwise check if it's a valid name for the name template */
- str = strchr (templ->name_template, '%');
- g_return_val_if_fail (str != NULL, NULL);
- g_return_val_if_fail (strncmp (templ->name_template, name,
- str - templ->name_template) == 0, NULL);
- g_return_val_if_fail (strlen (name) > str - templ->name_template, NULL);
+ if (strncmp (name_ptr, templ_name_ptr, len) != 0)
+ return FALSE;
- data = name + (str - templ->name_template);
+ } else {
+ const gchar *specifier;
+ gchar *target = NULL;
+
+ /* extract specifier when it has postfix characters */
+ if (name_postfix_len > templ_postfix_len) {
+ target = g_strndup (name_ptr, name_postfix_len - templ_postfix_len);
+ }
+ specifier = target ? target : name_ptr;
- /* Can either be %s or %d or %u, do sanity checking for %d */
- if (*(str + 1) == 'd') {
+ if (*(templ_name_ptr + 1) == 'd') {
gint64 tmp;
/* it's an int */
- tmp = g_ascii_strtoll (data, &endptr, 10);
- g_return_val_if_fail (tmp >= G_MININT && tmp <= G_MAXINT
- && *endptr == '\0', NULL);
- } else if (*(str + 1) == 'u') {
+ tmp = g_ascii_strtoll (specifier, &endptr, 10);
+ if (tmp < G_MININT || tmp > G_MAXINT || (*endptr != '\0'
+ && *endptr != '_'))
+ return FALSE;
+ } else if (*(templ_name_ptr + 1) == 'u') {
guint64 tmp;
/* it's an int */
- tmp = g_ascii_strtoull (data, &endptr, 10);
- g_return_val_if_fail (tmp <= G_MAXUINT && *endptr == '\0', NULL);
+ tmp = g_ascii_strtoull (specifier, &endptr, 10);
+ if (tmp > G_MAXUINT || (*endptr != '\0' && *endptr != '_'))
+ return FALSE;
}
+
+ g_free (target);
+ }
+
+ /* otherwise we increment these from NULL to 1 */
+ if (next_specifier) {
+ templ_name++;
+ name++;
}
+ } while (next_specifier);
+
+ return TRUE;
+}
+
+static GstPad *
+_gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
+ const gchar * name, const GstCaps * caps)
+{
+ GstPad *newpad = NULL;
+ GstElementClass *oclass;
+
+ oclass = GST_ELEMENT_GET_CLASS (element);
+
+#ifndef G_DISABLE_CHECKS
+ /* Some sanity checking here */
+ if (name) {
+ GstPad *pad;
+
+ g_return_val_if_fail (gst_element_is_valid_request_template_name
+ (templ->name_template, name), NULL);
pad = gst_element_get_static_pad (element, name);
if (pad) {
const gchar *req_name = NULL;
gboolean templ_found = FALSE;
GList *list;
- const gchar *data;
- gchar *str, *endptr = NULL;
GstElementClass *class;
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
class = GST_ELEMENT_GET_CLASS (element);
- /* if the name contains a %, we assume it's the complete template name. Get
- * the template and try to get a pad */
- if (strstr (name, "%")) {
- templ = gst_element_class_get_request_pad_template (class, name);
- req_name = NULL;
- if (templ)
- templ_found = TRUE;
+ templ = gst_element_class_get_request_pad_template (class, name);
+ if (templ) {
+ req_name = strstr (name, "%") ? NULL : name;
+ templ_found = TRUE;
} else {
/* there is no % in the name, try to find a matching template */
list = class->padtemplates;
if (templ->presence == GST_PAD_REQUEST) {
GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
templ->name_template);
- /* see if we find an exact match */
- if (strcmp (name, templ->name_template) == 0) {
+ if (gst_element_is_valid_request_template_name (templ->name_template,
+ name)) {
templ_found = TRUE;
req_name = name;
break;
}
- /* Because of sanity checks in gst_pad_template_new(), we know that %s
- and %d and %u, occurring at the end of the name_template, are the only
- possibilities. */
- else if ((str = strchr (templ->name_template, '%'))
- && strncmp (templ->name_template, name,
- str - templ->name_template) == 0
- && strlen (name) > str - templ->name_template) {
- data = name + (str - templ->name_template);
- if (*(str + 1) == 'd') {
- glong tmp;
-
- /* it's an int */
- tmp = strtol (data, &endptr, 10);
- if (tmp != G_MINLONG && tmp != G_MAXLONG && endptr &&
- *endptr == '\0') {
- templ_found = TRUE;
- req_name = name;
- break;
- }
- } else if (*(str + 1) == 'u') {
- gulong tmp;
-
- /* it's an int */
- tmp = strtoul (data, &endptr, 10);
- if (tmp != G_MAXULONG && endptr && *endptr == '\0') {
- templ_found = TRUE;
- req_name = name;
- break;
- }
- } else {
- /* it's a string */
- templ_found = TRUE;
- req_name = name;
- break;
- }
- }
}
list = list->next;
}
}
/**
- * gst_element_message_full:
+ * gst_element_message_full_with_details:
* @element: a #GstElement to send message from
* @type: the #GstMessageType
* @domain: the GStreamer GError domain this message belongs to
* @file: the source code file where the error was generated
* @function: the source code function where the error was generated
* @line: the source code line where the error was generated
+ * @structure:(transfer full): optional details structure
*
* Post an error, warning or info message on the bus from inside an element.
*
* @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or
* #GST_MESSAGE_INFO.
*
- * MT safe.
+ * Since: 1.10
*/
-void gst_element_message_full
+void gst_element_message_full_with_details
(GstElement * element, GstMessageType type,
GQuark domain, gint code, gchar * text,
- gchar * debug, const gchar * file, const gchar * function, gint line)
+ gchar * debug, const gchar * file, const gchar * function, gint line,
+ GstStructure * structure)
{
GError *gerror = NULL;
gchar *name;
switch (type) {
case GST_MESSAGE_ERROR:
message =
- gst_message_new_error (GST_OBJECT_CAST (element), gerror, sent_debug);
+ gst_message_new_error_with_details (GST_OBJECT_CAST (element), gerror,
+ sent_debug, structure);
break;
case GST_MESSAGE_WARNING:
- message = gst_message_new_warning (GST_OBJECT_CAST (element), gerror,
- sent_debug);
+ message =
+ gst_message_new_warning_with_details (GST_OBJECT_CAST (element),
+ gerror, sent_debug, structure);
break;
case GST_MESSAGE_INFO:
- message = gst_message_new_info (GST_OBJECT_CAST (element), gerror,
- sent_debug);
+ message =
+ gst_message_new_info_with_details (GST_OBJECT_CAST (element), gerror,
+ sent_debug, structure);
break;
default:
g_assert_not_reached ();
break;
}
+
gst_element_post_message (element, message);
GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted %s message: %s",
}
/**
+ * gst_element_message_full:
+ * @element: a #GstElement to send message from
+ * @type: the #GstMessageType
+ * @domain: the GStreamer GError domain this message belongs to
+ * @code: the GError code belonging to the domain
+ * @text: (allow-none) (transfer full): an allocated text string to be used
+ * as a replacement for the default message connected to code,
+ * or %NULL
+ * @debug: (allow-none) (transfer full): an allocated debug message to be
+ * used as a replacement for the default debugging information,
+ * or %NULL
+ * @file: the source code file where the error was generated
+ * @function: the source code function where the error was generated
+ * @line: the source code line where the error was generated
+ *
+ * Post an error, warning or info message on the bus from inside an element.
+ *
+ * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or
+ * #GST_MESSAGE_INFO.
+ *
+ * MT safe.
+ */
+void gst_element_message_full
+ (GstElement * element, GstMessageType type,
+ GQuark domain, gint code, gchar * text,
+ gchar * debug, const gchar * file, const gchar * function, gint line)
+{
+ gst_element_message_full_with_details (element, type, domain, code, text,
+ debug, file, function, line, NULL);
+}
+
+/**
* gst_element_is_locked_state:
* @element: a #GstElement.
*
const gchar *context_type;
GList *l;
- GST_OBJECT_LOCK (element);
+ g_return_if_fail (GST_IS_CONTEXT (context));
context_type = gst_context_get_context_type (context);
+ g_return_if_fail (context_type != NULL);
+
+ GST_OBJECT_LOCK (element);
for (l = element->contexts; l; l = l->next) {
GstContext *tmp = l->data;
const gchar *tmp_type = gst_context_get_context_type (tmp);
/* Always store newest context but never replace
* a persistent one by a non-persistent one */
- if (strcmp (context_type, tmp_type) == 0 &&
+ if (g_strcmp0 (context_type, tmp_type) == 0 &&
(gst_context_is_persistent (context) ||
!gst_context_is_persistent (tmp))) {
gst_context_replace ((GstContext **) & l->data, context);
GstElementClass *oclass;
g_return_if_fail (GST_IS_ELEMENT (element));
+ g_return_if_fail (GST_IS_CONTEXT (context));
oclass = GST_ELEMENT_GET_CLASS (element);
gst_element_setup_thread_pool ();
}
}
+
+GstStructure *
+gst_make_element_message_details (const char *name, ...)
+{
+ GstStructure *structure;
+ va_list varargs;
+
+ if (name == NULL)
+ return NULL;
+
+ va_start (varargs, name);
+ structure = gst_structure_new_valist ("details", name, varargs);
+ va_end (varargs);
+
+ return structure;
+}