static void make_dynamic_link (GstEditorLink * link) { GstElement *srce, *sinke; GstPadTemplate *src = NULL, *sink = NULL; if (GST_IS_EDITOR_PAD_SOMETIMES (link->srcpad)) src = GST_PAD_TEMPLATE (link->srcpad->object); if (GST_IS_EDITOR_PAD_SOMETIMES (link->sinkpad)) sink = GST_PAD_TEMPLATE (link->sinkpad->object); srce = GST_ELEMENT (GST_EDITOR_ITEM (goo_canvas_item_get_parent (GOO_CANVAS_ITEM (link->srcpad)))->object); sinke = GST_ELEMENT (GST_EDITOR_ITEM (goo_canvas_item_get_parent (GOO_CANVAS_ITEM (link->sinkpad)))->object); g_return_if_fail (src || sink); if (src) g_signal_connect_after (srce, "pad-added", G_CALLBACK (on_new_pad), link); if (sink) g_signal_connect_after (sinke, "pad-added", G_CALLBACK (on_new_pad), link); g_print ("dynamic link\n"); }
static int add_templates (gpointer gclass, PyObject * templates) { if (PyTuple_Check (templates)) { gint i, len; PyGObject *templ; len = PyTuple_Size (templates); if (len == 0) return 0; for (i = 0; i < len; i++) { templ = (PyGObject *) PyTuple_GetItem (templates, i); if (!pygobject_check (templ, &PyGObject_Type)) { PyObject *repr = PyObject_Repr ((PyObject *) templ); #if PY_VERSION_HEX < 0x03000000 PyErr_Format (PyExc_TypeError, "expected GObject but got %s", PyString_AsString (repr)); #else PyErr_Format (PyExc_TypeError, "expected GObject but got %s", _PyUnicode_AsString (repr)); #endif Py_DECREF (repr); return -1; } else if (!GST_IS_PAD_TEMPLATE (pygobject_get (templ))) { gchar *error = g_strdup_printf ("entries for __gsttemplates__ must be of type GstPadTemplate (%s)", G_OBJECT_TYPE_NAME (pygobject_get (templ))); PyErr_SetString (PyExc_TypeError, error); g_free (error); return -1; } } for (i = 0; i < len; i++) { templ = (PyGObject *) PyTuple_GetItem (templates, i); gst_element_class_add_pad_template (gclass, GST_PAD_TEMPLATE (templ->obj)); } return 0; } else if (!pygobject_check (templates, &PyGObject_Type) || GST_IS_PAD_TEMPLATE (pygobject_get (templates)) == FALSE) { PyErr_SetString (PyExc_TypeError, "entry for __gsttemplates__ must be of type GstPadTemplate"); return -1; } gst_element_class_add_pad_template (gclass, GST_PAD_TEMPLATE (pygobject_get (templates))); return 0; }
static void gst_pad_template_dispose (GObject * object) { GstPadTemplate *templ = GST_PAD_TEMPLATE (object); g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ)); if (GST_PAD_TEMPLATE_CAPS (templ)) { gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ)); } G_OBJECT_CLASS (parent_class)->dispose (object); }
/* this function is only linked for dynamic links */ static void on_new_pad (GstElement * element, GstPad * pad, GstEditorLink * link) { GstPadTemplate *src = NULL, *sink = NULL; if (GST_IS_EDITOR_PAD_SOMETIMES (link->srcpad)) src = GST_PAD_TEMPLATE (link->srcpad->object); if (GST_IS_EDITOR_PAD_SOMETIMES (link->sinkpad)) sink = GST_PAD_TEMPLATE (link->sinkpad->object); g_message ("new pad"); if (pad->padtemplate) { g_message ("from a template"); /* can't do pointer comparison -- some templates appear to be from the elementfactories, some from template factories... have to compare names */ if (src && g_ascii_strcasecmp ( pad->padtemplate->name_template, src->name_template) == 0) g_object_set (G_OBJECT (GOO_CANVAS_ITEM (link)), "src-pad", gst_editor_item_get (GST_OBJECT (pad)), NULL); else if (sink && g_ascii_strcasecmp ( pad->padtemplate->name_template, sink->name_template) == 0) g_object_set (G_OBJECT (GOO_CANVAS_ITEM (link)), "sink-pad", gst_editor_item_get (GST_OBJECT (pad)), NULL); else return; g_message ("we made it, now let's link"); /*gst_element_set_state ((GstElement *) gst_element_get_managing_bin (element), GST_STATE_PAUSED); */ gst_editor_link_link (link); /*gst_element_set_state ((GstElement *) gst_element_get_managing_bin (element), GST_STATE_PLAYING); */ } }
static int add_templates (gpointer gclass, PyObject * templates) { if (PyTuple_Check (templates)) { gint i, len; PyGObject *templ; len = PyTuple_Size (templates); if (len == 0) return 0; for (i = 0; i < len; i++) { templ = (PyGObject *) PyTuple_GetItem (templates, i); if (GST_IS_PAD_TEMPLATE (pygobject_get (templ)) == FALSE) { PyErr_SetString (PyExc_TypeError, "entries for __gsttemplates__ must be of type GstPadTemplate"); return -1; } } for (i = 0; i < len; i++) { templ = (PyGObject *) PyTuple_GetItem (templates, i); gst_element_class_add_pad_template (gclass, GST_PAD_TEMPLATE (templ->obj)); } return 0; } if (GST_IS_PAD_TEMPLATE (pygobject_get (templates)) == FALSE) { PyErr_SetString (PyExc_TypeError, "entry for __gsttemplates__ must be of type GstPadTemplate"); return -1; } gst_element_class_add_pad_template (gclass, GST_PAD_TEMPLATE (pygobject_get (templates))); return 0; }
static gboolean has_sometimes_template (GstElement * element) { GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); GList *l; for (l = klass->padtemplates; l != NULL; l = l->next) { if (GST_PAD_TEMPLATE (l->data)->presence == GST_PAD_SOMETIMES) return TRUE; } return FALSE; }
gboolean gst_editor_link_link (GstEditorLink * link) { GObject * src, *sink; GstPad * srcpad = NULL, * sinkpad = NULL; GooCanvasItem * item; GooCanvasLineDash * dash; g_return_val_if_fail (GST_IS_EDITOR_LINK (link), FALSE); if (!link->srcpad || !link->sinkpad) goto error; src = (GObject *)GST_EDITOR_ITEM (link->srcpad)->object; sink = (GObject *)GST_EDITOR_ITEM (link->sinkpad)->object; if (!GST_EDITOR_PAD (link->srcpad)->istemplate) { if (!GST_EDITOR_PAD (link->sinkpad)->istemplate) { if (GST_PAD_PEER (src) || GST_PAD_PEER (sink)) { /*if (GST_PAD_PEER (src) != (GstPad *) sink) { g_warning ("The src pad is linked, but not to the sink pad"); goto error; } if (GST_PAD_PEER (sink) != (GstPad *) src) { g_warning ("The sink pad is linked, but not to the src pad"); goto error; } */ srcpad = GST_PAD (src); sinkpad = GST_PAD (sink); goto linked; /* yay goto */ } } else if (GST_PAD_PEER (src)) { /* the to pad is a template */ g_warning ("The src pad is linked, but not to the sink pad"); goto error; } } else if (!GST_EDITOR_PAD (link->sinkpad)->istemplate && GST_PAD_PEER (sink)) { /* from pad is a template */ g_warning ("The sink pad is linked, but not to the src pad"); goto error; } if (link->ghost) { g_object_set ( G_OBJECT (GOO_CANVAS_ITEM (link)), "fill-color", "grey70", NULL); goto linked; } else if (GST_IS_EDITOR_PAD_SOMETIMES (link->srcpad) || GST_IS_EDITOR_PAD_SOMETIMES (link->sinkpad)) { make_dynamic_link (link); g_object_set ( G_OBJECT (GOO_CANVAS_ITEM (link)), "fill-color", "grey50", NULL); goto linked; } else { if (!GST_EDITOR_PAD (link->srcpad)->istemplate) { srcpad = GST_PAD (src); } else if (GST_IS_EDITOR_PAD_REQUEST (link->srcpad)) { srcpad = gst_element_get_request_pad ( (GstElement *)GST_EDITOR_ITEM ( goo_canvas_item_get_parent (GOO_CANVAS_ITEM (link->srcpad))) ->object, GST_PAD_TEMPLATE (src)->name_template); /* the new_pad signal will cause a new pad to made automagically in the element */ g_object_set (G_OBJECT (GOO_CANVAS_ITEM (link)), "src-pad", gst_editor_item_get ((GstObject *)srcpad), NULL); } else { goto error; } if (!srcpad) goto error; if (!GST_EDITOR_PAD (link->sinkpad)->istemplate) { sinkpad = GST_PAD (sink); } else if (GST_IS_EDITOR_PAD_REQUEST (link->sinkpad)) { sinkpad = gst_element_get_request_pad ( (GstElement *)GST_EDITOR_ITEM ( goo_canvas_item_get_parent (GOO_CANVAS_ITEM (link->sinkpad))) ->object, GST_PAD_TEMPLATE (sink)->name_template); g_object_set (G_OBJECT (GOO_CANVAS_ITEM (link)), "sink-pad", gst_editor_item_get ((GstObject *)sinkpad), NULL); } else { goto error; } if (!sinkpad) goto error; if (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK) { GstEditorBin * srcbin, *sinkbin; g_object_set ( G_OBJECT (GOO_CANVAS_ITEM (link)), "fill-color", "black", NULL); linked: srcbin = sinkbin = NULL; dash = goo_canvas_line_dash_new (0, NULL); g_object_set (G_OBJECT (GOO_CANVAS_ITEM (link)), "line-dash", dash, NULL); goo_canvas_line_dash_unref (dash); g_signal_connect (link->srcpad, "position-changed", G_CALLBACK (on_editor_pad_position_changed), G_OBJECT (link)); g_signal_connect (link->sinkpad, "position-changed", G_CALLBACK (on_editor_pad_position_changed), G_OBJECT (link)); /* don't connect a signal on a ghost or dynamic link */ g_print ( "adding unlinked signal for src: %p and sink %p", srcpad, sinkpad); if (srcpad && sinkpad) { GST_CAT_DEBUG (gste_debug_cat, "link pad signal (%s:%s from %s:%s) with link %p", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), link); g_signal_connect (srcpad, "unlinked", G_CALLBACK (on_pad_unlink), link); g_signal_connect ( sinkpad, "unlinked", G_CALLBACK (on_pad_unlink), link); } item = goo_canvas_item_get_parent ( goo_canvas_item_get_parent (GOO_CANVAS_ITEM (link->srcpad))); if (GST_IS_EDITOR_BIN (item)) srcbin = GST_EDITOR_BIN (item); item = goo_canvas_item_get_parent ( goo_canvas_item_get_parent (GOO_CANVAS_ITEM (link->sinkpad))); if (GST_IS_EDITOR_BIN (item)) sinkbin = GST_EDITOR_BIN (item); if (sinkbin) sinkbin->links = g_list_prepend (sinkbin->links, link); if (srcbin && sinkbin != srcbin) srcbin->links = g_list_prepend (srcbin->links, link); return TRUE; } } error: g_message ("could not link"); if (link->srcpad) GST_EDITOR_PAD (link->srcpad)->link = NULL; if (link->sinkpad) GST_EDITOR_PAD (link->sinkpad)->link = NULL; return FALSE; }
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; }