#include "PipelineIE.h" #include #include #include #include #include #include static void clearPipeline(GstElement *pipeline) { if(!pipeline) return; GstIterator *iter; iter = gst_bin_iterate_elements (GST_BIN (pipeline)); GstElement *element = NULL; bool done = false; while (!done) { #if GST_VERSION_MAJOR >= 1 GValue value = { 0 }; switch (gst_iterator_next (iter, &value)) { case GST_ITERATOR_OK: { element = GST_ELEMENT(g_value_get_object(&value)); #else switch (gst_iterator_next (iter, (gpointer *)&element)) { case GST_ITERATOR_OK: { #endif gst_bin_remove(GST_BIN(pipeline), element); #if GST_VERSION_MAJOR >= 1 g_value_reset (&value); #endif iter = gst_bin_iterate_elements (GST_BIN (pipeline)); if(!iter) done = true; break; } case GST_ITERATOR_DONE: case GST_ITERATOR_RESYNC: case GST_ITERATOR_ERROR: { done = true; break; } }; } gst_iterator_free (iter); } namespace { struct Connection { std::string element1; std::string pad1; std::string element2; std::string pad2; }; } static void writeProperties(QXmlStreamWriter &xmlWriter, const GstElement *element) { GParamSpec **prop_specs; guint num_props; prop_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS (element), &num_props); if(!num_props) return; xmlWriter.writeStartElement("properties"); for(std::size_t i = 0; i flags & G_PARAM_READABLE) && (param -> flags & G_PARAM_WRITABLE)) { GValue value = { 0 }; g_value_init (&value, param -> value_type); g_object_get_property (G_OBJECT(element), param -> name, &value); if(!g_param_value_defaults(param, &value)) { bool skip = false; QString propertyName = g_param_spec_get_name (param); QString propertyValue; switch (G_VALUE_TYPE (&value)) { case G_TYPE_STRING: { const char *string_val = g_value_get_string (&value); if(string_val) propertyValue = string_val; else skip = true; break; } case G_TYPE_BOOLEAN: { gboolean bool_val = g_value_get_boolean (&value); propertyValue = QString::number(bool_val); break; } case G_TYPE_ULONG: { propertyValue = QString::number(g_value_get_ulong(&value)); break; } case G_TYPE_LONG: { propertyValue = QString::number(g_value_get_long(&value)); break; } case G_TYPE_UINT: { propertyValue = QString::number(g_value_get_uint(&value)); break; } case G_TYPE_INT: { propertyValue = QString::number(g_value_get_int(&value)); break; } case G_TYPE_UINT64: { propertyValue = QString::number(g_value_get_uint64(&value)); break; } case G_TYPE_INT64: { propertyValue = QString::number(g_value_get_int64(&value)); break; } case G_TYPE_FLOAT: { propertyValue = QString::number(g_value_get_float(&value)); break; } case G_TYPE_DOUBLE: { propertyValue = QString::number(g_value_get_double(&value)); break; } default: { gchar *elementName = gst_element_get_name(element); qDebug() << "property `" << propertyName << "` for `" << elementName << "` not supported"; g_free(elementName); skip = true; break; } }; if(!skip) { xmlWriter.writeStartElement("property"); xmlWriter.writeAttribute("name", propertyName); xmlWriter.writeAttribute("value", propertyValue); xmlWriter.writeEndElement(); } g_value_reset(&value); } } } xmlWriter.writeEndElement(); g_free(prop_specs); } static void loadProperties(QDomElement node, GstElement *element) { QDomNode child = node.firstChild(); while(!child.isNull()) { if(child.toElement().tagName() == "property") { QString name = child.toElement().attribute("name"); QString value = child.toElement().attribute("value"); GParamSpec *param = g_object_class_find_property(G_OBJECT_GET_CLASS (element), name.toStdString().c_str()); if(!param) { gchar *elementName = gst_element_get_name(element); qDebug() << "problem with setting property `" << name << "` for `" << elementName << "`"; g_free(elementName); continue; } if(!(param -> flags & G_PARAM_WRITABLE)) continue; std::string tmpStr = name.toStdString(); const char *propName = tmpStr.c_str(); switch (param -> value_type) { case G_TYPE_STRING: { g_object_set(G_OBJECT(element), propName, value.toStdString().c_str(), NULL); break; } case G_TYPE_BOOLEAN: { gboolean val = value.toInt(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_ULONG: { gulong val = value.toULong(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_LONG: { glong val = value.toLong(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_UINT: { guint val = value.toUInt(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_INT: { gint val = value.toInt(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_UINT64: { guint64 val = value.toULongLong(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_INT64: { gint64 val = value.toLongLong(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_FLOAT: { gfloat val = value.toFloat(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } case G_TYPE_DOUBLE: { gdouble val = value.toDouble(); g_object_set(G_OBJECT(element), propName, val, NULL); break; } default: { gchar *elementName = gst_element_get_name(element); qDebug() << "property `" << name << "` for `" << QString(elementName) << "` not supported"; g_free(elementName); break; } }; } child = child.nextSibling(); } } static void create_requst_pad(GstElement *element, const QString &templateName, const QString &padName) { GstElementClass *klass = GST_ELEMENT_GET_CLASS(element); GstPadTemplate *templ = gst_element_class_get_pad_template(klass, templateName.toStdString().c_str()); gst_element_request_pad(element, templ, padName.toStdString().c_str(), NULL); } bool PipelineIE::Export(QSharedPointer pgraph, const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::warning(0, "Read only", "The file is in read only mode"); return false; } std::vector info = pgraph -> GetInfo(); QXmlStreamWriter xmlWriter; xmlWriter.setDevice(&file); xmlWriter.writeStartDocument(); xmlWriter.writeStartElement("pipeline"); for(std::size_t i=0; i m_pGraph), info[i].m_name.c_str()); for(std::size_t j=0; j pgraph, const QString &fileName) { GstElement *pipeline = pgraph -> m_pGraph; QFile file(fileName); if(!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(0, "Open failed", QString("Cannot read file ") + fileName + ": " + file.errorString()); return false; } QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if(!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn)) { QMessageBox::warning(0, "Xml parsing failed", QString("Parse error at line ") + QString::number(errorLine) + ", " "column " + QString::number(errorColumn) + ": " + errorStr); return false; } clearPipeline(pipeline); QDomElement root = doc.documentElement(); if(root.tagName() != "pipeline") { QMessageBox::warning(0, "Parsing failed", "Is invalid pipeline file"); return false; } QDomNode child = root.firstChild(); std::vector connections; while(!child.isNull()) { if(child.toElement().tagName() == "element") { QDomElement elNode = child.toElement(); GstElement *pel = gst_element_factory_make(elNode.attribute("plugin-name").toStdString().c_str(), elNode.attribute("name").toStdString().c_str()); if(!pel) { QMessageBox::warning(0, "Element creation failed", QString("Could not create element of `") + elNode.attribute("plugin-name") + "` with name `" + elNode.attribute("name") + "`"); child = child.nextSibling(); continue; } bool res = gst_bin_add(GST_BIN(pipeline), pel); if(!res) { QMessageBox::warning(0, "Element insertion failed", QString("Could not insert element `") + elNode.attribute("name") + "` to pipeline"); child = child.nextSibling(); continue; } gst_element_sync_state_with_parent(pel); QDomNode elementChild = elNode.firstChild(); while(!elementChild.isNull()) { if(elementChild.toElement().tagName() == "pad") { QDomNode padChild = elementChild.firstChild(); QDomElement elPad = elementChild.toElement(); // GstPadPresence presence = GST_PAD_ALWAYS; QString templaneName; if(elPad.attribute("presence") == "request") create_requst_pad(pel, elPad.attribute("template-name"), elPad.attribute("name")); while(!padChild.isNull()) { if(padChild.toElement().tagName() == "connected-to") { bool isExists = false; QDomElement elCoonnectedTo = padChild.toElement(); for(std::size_t i=0; i 0) setReady = false; while(true) { std::size_t i=0; for(; i