annotate plugin/PluginXml.cpp @ 661:a4faa1840384

* If a FileSource URL won't convert at all in strict mode, try again in tolerant mode (necessary for e.g. filenames with square brackets in them)
author Chris Cannam
date Tue, 19 Oct 2010 21:47:55 +0100
parents a70dcfed59c1
children b4a8d8221eaf
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@314 84 // std::cerr << "PluginXml::toXml: parameter name \""
Chris@185 85 // << i->name.c_str() << "\" has value "
Chris@185 86 // << m_plugin->getParameter(i->name) << std::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@66 122 << ATTRIBUTE.toStdString() << "\", 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@117 177 // std::cerr << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::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@260 184 // std::cerr << "PluginXml::setParameters: setting parameter \""
Chris@260 185 // << i->identifier << "\" to value " << value << std::endl;
Chris@239 186 m_plugin->setParameter(i->identifier, value);
Chris@66 187 } else {
Chris@239 188 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(pname).toStdString() << "\" for parameter \"" << i->identifier << "\" (attribute \"" << pname.toStdString() << "\")" << 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@185 202 // std::cerr << "PluginXml::setParametersFromXml: XML is \""
Chris@185 203 // << xml.toLocal8Bit().data() << "\"" << std::endl;
Chris@185 204
Chris@66 205 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@66 206 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
Chris@66 207 std::cerr << "Input follows:" << std::endl;
Chris@66 208 std::cerr << xml.toStdString() << 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@117 220 // std::cerr << "PluginXml::setParametersFromXml: Adding attribute \"" << attr.name().toStdString()
Chris@117 221 // << "\" with value \"" << attr.value().toStdString() << "\"" << std::endl;
Chris@66 222 attrs.append(attr.name(), "", "", attr.value());
Chris@66 223 }
Chris@66 224
Chris@66 225 setParameters(attrs);
Chris@66 226 }
Chris@163 227
Chris@66 228 QString
Chris@66 229 PluginXml::stripInvalidParameterNameCharacters(QString s) const
Chris@66 230 {
Chris@66 231 s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
Chris@66 232 return s;
Chris@66 233 }
Chris@66 234