annotate plugin/PluginXml.cpp @ 808:67003fb58ba4

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:36:05 +0100
parents 1424aa29ae95
children e802e550a1f2
rev   line source
Chris@66 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@66 2
Chris@66 3 /*
Chris@66 4 Sonic Visualiser
Chris@66 5 An audio file viewer and annotation editor.
Chris@66 6 Centre for Digital Music, Queen Mary, University of London.
Chris@66 7 This file copyright 2006 Chris Cannam.
Chris@66 8
Chris@66 9 This program is free software; you can redistribute it and/or
Chris@66 10 modify it under the terms of the GNU General Public License as
Chris@66 11 published by the Free Software Foundation; either version 2 of the
Chris@66 12 License, or (at your option) any later version. See the file
Chris@66 13 COPYING included with this distribution for more information.
Chris@66 14 */
Chris@66 15
Chris@66 16 #include "PluginXml.h"
Chris@66 17
Chris@66 18 #include <QRegExp>
Chris@66 19 #include <QXmlAttributes>
Chris@66 20
Chris@66 21 #include <QDomDocument>
Chris@66 22 #include <QDomElement>
Chris@66 23 #include <QDomNamedNodeMap>
Chris@66 24 #include <QDomAttr>
Chris@66 25
Chris@314 26 #include <QTextStream>
Chris@314 27
Chris@475 28 #include <vamp-hostsdk/PluginBase.h>
Chris@75 29 #include "RealTimePluginInstance.h"
Chris@66 30
Chris@66 31 #include <iostream>
Chris@66 32
Chris@66 33 PluginXml::PluginXml(Vamp::PluginBase *plugin) :
Chris@66 34 m_plugin(plugin)
Chris@66 35 {
Chris@66 36 }
Chris@66 37
Chris@66 38 PluginXml::~PluginXml() { }
Chris@66 39
Chris@66 40 QString
Chris@81 41 PluginXml::encodeConfigurationChars(QString text)
Chris@81 42 {
Chris@81 43 QString rv(text);
Chris@81 44 rv.replace(";", "[[SEMICOLON]]");
Chris@81 45 rv.replace("=", "[[EQUALS]]");
Chris@81 46 return rv;
Chris@81 47 }
Chris@81 48
Chris@81 49 QString
Chris@81 50 PluginXml::decodeConfigurationChars(QString text)
Chris@81 51 {
Chris@81 52 QString rv(text);
Chris@81 53 rv.replace("[[SEMICOLON]]", ";");
Chris@81 54 rv.replace("[[EQUALS]]", "=");
Chris@81 55 return rv;
Chris@81 56 }
Chris@81 57
Chris@314 58 void
Chris@314 59 PluginXml::toXml(QTextStream &stream,
Chris@314 60 QString indent, QString extraAttributes) const
Chris@66 61 {
Chris@314 62 stream << indent;
Chris@66 63
Chris@314 64 stream << QString("<plugin identifier=\"%1\" name=\"%2\" description=\"%3\" maker=\"%4\" version=\"%5\" copyright=\"%6\" %7 ")
Chris@239 65 .arg(encodeEntities(QString(m_plugin->getIdentifier().c_str())))
Chris@66 66 .arg(encodeEntities(QString(m_plugin->getName().c_str())))
Chris@66 67 .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
Chris@66 68 .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
Chris@66 69 .arg(m_plugin->getPluginVersion())
Chris@66 70 .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
Chris@66 71 .arg(extraAttributes);
Chris@66 72
Chris@66 73 if (!m_plugin->getPrograms().empty()) {
Chris@314 74 stream << QString("program=\"%1\" ")
Chris@66 75 .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
Chris@66 76 }
Chris@66 77
Chris@66 78 Vamp::PluginBase::ParameterList parameters =
Chris@66 79 m_plugin->getParameterDescriptors();
Chris@66 80
Chris@66 81 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@66 82 i != parameters.end(); ++i) {
Chris@185 83
Chris@690 84 // SVDEBUG << "PluginXml::toXml: parameter name \""
Chris@185 85 // << i->name.c_str() << "\" has value "
Chris@687 86 // << m_plugin->getParameter(i->name) << endl;
Chris@185 87
Chris@314 88 stream << QString("param-%1=\"%2\" ")
Chris@239 89 .arg(stripInvalidParameterNameCharacters(QString(i->identifier.c_str())))
Chris@239 90 .arg(m_plugin->getParameter(i->identifier));
Chris@66 91 }
Chris@66 92
Chris@75 93 RealTimePluginInstance *rtpi =
Chris@75 94 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 95 if (rtpi) {
Chris@75 96 std::map<std::string, std::string> configurePairs =
Chris@75 97 rtpi->getConfigurePairs();
Chris@75 98 QString config;
Chris@75 99 for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
Chris@75 100 i != configurePairs.end(); ++i) {
Chris@75 101 QString key = i->first.c_str();
Chris@75 102 QString value = i->second.c_str();
Chris@81 103 key = encodeConfigurationChars(key);
Chris@81 104 value = encodeConfigurationChars(value);
Chris@75 105 if (config != "") config += ";";
Chris@75 106 config += QString("%1=%2").arg(key).arg(value);
Chris@75 107 }
Chris@75 108 if (config != "") {
Chris@314 109 stream << QString("configuration=\"%1\" ")
Chris@75 110 .arg(encodeEntities(config));
Chris@75 111 }
Chris@75 112 }
Chris@75 113
Chris@314 114 stream << "/>\n";
Chris@66 115 }
Chris@66 116
Chris@66 117 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
Chris@66 118 QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
Chris@66 119 if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
Chris@66 120 std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
Chris@66 121 << #ATTRIBUTE << " does not match (attributes have \"" \
Chris@686 122 << ATTRIBUTE << "\", my " \
Chris@66 123 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
Chris@66 124 }
Chris@66 125
Chris@66 126 void
Chris@66 127 PluginXml::setParameters(const QXmlAttributes &attrs)
Chris@66 128 {
Chris@239 129 CHECK_ATTRIBUTE(identifier, m_plugin->getIdentifier);
Chris@66 130 CHECK_ATTRIBUTE(name, m_plugin->getName);
Chris@66 131 CHECK_ATTRIBUTE(description, m_plugin->getDescription);
Chris@66 132 CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
Chris@66 133 CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
Chris@66 134
Chris@66 135 bool ok;
Chris@66 136 int version = attrs.value("version").trimmed().toInt(&ok);
Chris@66 137 if (ok && version != m_plugin->getPluginVersion()) {
Chris@66 138 std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
Chris@66 139 }
Chris@66 140
Chris@75 141 RealTimePluginInstance *rtpi =
Chris@75 142 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 143 if (rtpi) {
Chris@75 144 QString config = attrs.value("configuration");
Chris@75 145 if (config != "") {
Chris@75 146 QStringList configList = config.split(";");
Chris@75 147 for (QStringList::iterator i = configList.begin();
Chris@75 148 i != configList.end(); ++i) {
Chris@75 149 QStringList kv = i->split("=");
Chris@75 150 if (kv.count() < 2) {
Chris@75 151 std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl;
Chris@75 152 continue;
Chris@75 153 }
Chris@75 154 QString key(kv[0]), value(kv[1]);
Chris@81 155 key = decodeConfigurationChars(key);
Chris@81 156 value = decodeConfigurationChars(value);
Chris@75 157 rtpi->configure(key.toStdString(), value.toStdString());
Chris@75 158 }
Chris@75 159 }
Chris@75 160 }
Chris@75 161
Chris@66 162 if (!m_plugin->getPrograms().empty()) {
Chris@66 163 m_plugin->selectProgram(attrs.value("program").toStdString());
Chris@66 164 }
Chris@66 165
Chris@66 166 Vamp::PluginBase::ParameterList parameters =
Chris@66 167 m_plugin->getParameterDescriptors();
Chris@66 168
Chris@66 169 for (Vamp::PluginBase::ParameterList::const_iterator i =
Chris@66 170 parameters.begin(); i != parameters.end(); ++i) {
Chris@66 171
Chris@239 172 QString pname = QString("param-%1")
Chris@66 173 .arg(stripInvalidParameterNameCharacters
Chris@239 174 (QString(i->identifier.c_str())));
Chris@66 175
Chris@239 176 if (attrs.value(pname) == "") {
Chris@690 177 // SVDEBUG << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name << "\")" << endl;
Chris@66 178 continue;
Chris@66 179 }
Chris@66 180
Chris@66 181 bool ok;
Chris@239 182 float value = attrs.value(pname).trimmed().toFloat(&ok);
Chris@66 183 if (ok) {
Chris@690 184 // SVDEBUG << "PluginXml::setParameters: setting parameter \""
Chris@687 185 // << i->identifier << "\" to value " << value << endl;
Chris@239 186 m_plugin->setParameter(i->identifier, value);
Chris@66 187 } else {
Chris@686 188 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(pname) << "\" for parameter \"" << i->identifier << "\" (attribute \"" << pname << "\")" << std::endl;
Chris@66 189 }
Chris@66 190 }
Chris@66 191 }
Chris@66 192
Chris@66 193 void
Chris@66 194 PluginXml::setParametersFromXml(QString xml)
Chris@66 195 {
Chris@66 196 QDomDocument doc;
Chris@66 197
Chris@66 198 QString error;
Chris@66 199 int errorLine;
Chris@66 200 int errorColumn;
Chris@66 201
Chris@690 202 // SVDEBUG << "PluginXml::setParametersFromXml: XML is \""
Chris@687 203 // << xml.toLocal8Bit().data() << "\"" << endl;
Chris@185 204
Chris@66 205 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@686 206 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error << " at line " << errorLine << ", column " << errorColumn << std::endl;
Chris@66 207 std::cerr << "Input follows:" << std::endl;
Chris@686 208 std::cerr << xml << std::endl;
Chris@66 209 std::cerr << "Input ends." << std::endl;
Chris@66 210 return;
Chris@66 211 }
Chris@66 212
Chris@66 213 QDomElement pluginElt = doc.firstChildElement("plugin");
Chris@66 214 QDomNamedNodeMap attrNodes = pluginElt.attributes();
Chris@66 215 QXmlAttributes attrs;
Chris@66 216
Chris@66 217 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@66 218 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@66 219 if (attr.isNull()) continue;
Chris@690 220 // SVDEBUG << "PluginXml::setParametersFromXml: Adding attribute \"" << attr.name()// << "\" with value \"" << attr.value() << "\"" << endl;
Chris@66 221 attrs.append(attr.name(), "", "", attr.value());
Chris@66 222 }
Chris@66 223
Chris@66 224 setParameters(attrs);
Chris@66 225 }
Chris@163 226
Chris@66 227 QString
Chris@66 228 PluginXml::stripInvalidParameterNameCharacters(QString s) const
Chris@66 229 {
Chris@66 230 s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
Chris@66 231 return s;
Chris@66 232 }
Chris@66 233