GstPad * gst_ghost_pad_new_from_template (const gchar * name, GstPad * target, GstPadTemplate * templ) { GstPad *ret; g_return_val_if_fail (GST_IS_PAD (target), NULL); g_return_val_if_fail (!gst_pad_is_linked (target), NULL); g_return_val_if_fail (templ != NULL, NULL); g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_DIRECTION (target), NULL); GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name), GST_DEBUG_PAD_NAME (target), templ); if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ))) if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target)) goto set_target_failed; return ret; /* ERRORS */ set_target_failed: { GST_WARNING_OBJECT (ret, "failed to set target %s:%s", GST_DEBUG_PAD_NAME (target)); gst_object_unref (ret); return NULL; } }
static GstPad * gst_gl_mixer_bin_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) { GstGLMixerBin *self = GST_GL_MIXER_BIN (element); GstPadTemplate *mixer_templ; struct input_chain *chain; GstPad *mixer_pad; chain = g_new0 (struct input_chain, 1); mixer_templ = _find_element_pad_template (self->mixer, GST_PAD_TEMPLATE_DIRECTION (templ), GST_PAD_TEMPLATE_PRESENCE (templ)); g_return_val_if_fail (mixer_templ, NULL); mixer_pad = gst_element_request_pad (self->mixer, mixer_templ, req_name, NULL); g_return_val_if_fail (mixer_pad, NULL); if (!_create_input_chain (self, chain, mixer_pad)) { gst_element_release_request_pad (self->mixer, mixer_pad); _free_input_chain (chain); return NULL; } GST_OBJECT_LOCK (element); self->priv->input_chains = g_list_prepend (self->priv->input_chains, chain); GST_OBJECT_UNLOCK (element); gst_child_proxy_child_added (GST_CHILD_PROXY (self), G_OBJECT (chain->ghost_pad), GST_OBJECT_NAME (chain->ghost_pad)); return GST_PAD (chain->ghost_pad); }
/** * gst_ghost_pad_new_no_target_from_template: * @name: (allow-none): the name of the new pad, or NULL to assign a default name * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from. * * Create a new ghostpad based on @templ, without setting a target. The * direction will be taken from the @templ. * * Returns: (transfer full): a new #GstPad, or NULL in case of an error. */ GstPad * gst_ghost_pad_new_no_target_from_template (const gchar * name, GstPadTemplate * templ) { GstPad *ret; g_return_val_if_fail (templ != NULL, NULL); ret = gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ); return ret; }
static GValueArray * gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { GstElementClass *klass; const GList *templates; snd_pcm_stream_t mode = -1; GValueArray *array; GValue value = { 0, }; GList *l, *list; if (!g_str_equal (pspec->name, "device")) { G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); return NULL; } klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe)); /* I'm pretty sure ALSA has a good way to do this. However, their cool * auto-generated documentation is pretty much useless if you try to * do function-wise look-ups. */ /* we assume one pad template at max [zero=mixer] */ templates = gst_element_class_get_pad_template_list (klass); if (templates) { if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC) mode = SND_PCM_STREAM_CAPTURE; else mode = SND_PCM_STREAM_PLAYBACK; } list = gst_alsa_get_device_list (mode); if (list == NULL) { GST_LOG_OBJECT (probe, "No devices found"); return NULL; } array = g_value_array_new (g_list_length (list)); g_value_init (&value, G_TYPE_STRING); for (l = list; l != NULL; l = l->next) { GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data); g_value_take_string (&value, (gchar *) l->data); l->data = NULL; g_value_array_append (array, &value); } g_value_unset (&value); g_list_free (list); return array; }
static GstPad * gst_switch_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstSwitch *swit = GST_SWITCH (element); GstGhostPad *pad; INFO ("requesting: %s.%s (%d=%d+%d)", GST_ELEMENT_NAME (swit), name ? name : GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), element->numpads, element->numsrcpads, element->numsinkpads); GST_SWITCH_LOCK (swit); switch (GST_PAD_TEMPLATE_DIRECTION (templ)) { case GST_PAD_SRC: pad = gst_switch_request_new_src_pad (swit, templ, name, caps); break; case GST_PAD_SINK: pad = gst_switch_request_new_sink_pad (swit, templ, name, caps); break; default: pad = NULL; break; } if (pad) { gst_pad_set_active (GST_PAD (pad), TRUE); if (gst_element_add_pad (GST_ELEMENT (swit), GST_PAD (pad))) { GstPad *basepad = gst_ghost_pad_get_target (pad); GstElement *swcase = GST_ELEMENT (GST_PAD_PARENT (basepad)); GST_OBJECT_FLAG_SET (basepad, GST_SWITCH_PAD_FLAG_GHOSTED); GST_DEBUG_OBJECT (swit, "New %s:%s on %s:%s", GST_ELEMENT_NAME (swit), GST_PAD_NAME (pad), GST_ELEMENT_NAME (swcase), GST_PAD_NAME (basepad)); INFO ("requested %s.%s on %s.%s", GST_ELEMENT_NAME (swit), GST_PAD_NAME (pad), GST_ELEMENT_NAME (swcase), GST_PAD_NAME (basepad)); } } GST_SWITCH_UNLOCK (swit); return GST_PAD (pad); }
static GstPadTemplate * _find_element_pad_template (GstElement * element, GstPadDirection direction, GstPadPresence presence) { GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); GList *templ_list = gst_element_class_get_pad_template_list (klass); GstPadTemplate *templ; /* find suitable template */ while (templ_list) { templ = (GstPadTemplate *) templ_list->data; if (GST_PAD_TEMPLATE_DIRECTION (templ) != direction || GST_PAD_TEMPLATE_PRESENCE (templ) != presence) { templ_list = templ_list->next; templ = NULL; continue; } break; } return templ; }
static gboolean connect_element (InsanityTest * test, GstElement * demux) { GList *pads; gboolean res = TRUE; gboolean dynamic = FALSE; GList *to_connect = NULL; /* 1. Loop over pad templates, grabbing existing pads along the way */ for (pads = GST_ELEMENT_GET_CLASS (demux)->padtemplates; pads; pads = g_list_next (pads)) { GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data); const gchar *templ_name; /* we are only interested in source pads */ if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC) continue; templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ); /* figure out what kind of pad this is */ switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { case GST_PAD_ALWAYS: { GstPad *pad = gst_element_get_static_pad (demux, templ_name); /* We concider the demuxer is not broken, and thus always * pads are always here */ to_connect = g_list_prepend (to_connect, pad); break; } case GST_PAD_SOMETIMES: { /* try to get the pad to see if it is already created or * not */ GstPad *pad = gst_element_get_static_pad (demux, templ_name); if (pad) { /* the pad is created, we need to try to link to it */ to_connect = g_list_prepend (to_connect, pad); } else { /* we have an element that will create dynamic pads */ dynamic = TRUE; } break; } case GST_PAD_REQUEST: /* ignore request pads */ break; } } /* 2. if there are more potential pads, connect to signal */ if (dynamic) { g_signal_connect (glob_demuxer, "pad-added", G_CALLBACK (pad_added_cb), test); } /* 3. for every available pad, check if we can connect it */ for (pads = to_connect; pads; pads = g_list_next (pads)) { GstPad *pad = GST_PAD_CAST (pads->data); pad_added_cb (demux, pad, test); gst_object_unref (pad); } g_list_free (to_connect); return res; }