annotate plugin/PluginXml.cpp @ 295:a2dc34ce146a

* Window should be centred on its nominal time. I'm not sure what the reasoning was behind the previous formulations of these two lines.
author Chris Cannam
date Thu, 06 Sep 2007 15:14:47 +0000
parents d4a33cdca86f
children 70a232b1f12a
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@66 26 #include "vamp-sdk/PluginBase.h"
Chris@75 27 #include "RealTimePluginInstance.h"
Chris@66 28
Chris@66 29 #include <iostream>
Chris@66 30
Chris@66 31 PluginXml::PluginXml(Vamp::PluginBase *plugin) :
Chris@66 32 m_plugin(plugin)
Chris@66 33 {
Chris@66 34 }
Chris@66 35
Chris@66 36 PluginXml::~PluginXml() { }
Chris@66 37
Chris@66 38 QString
Chris@81 39 PluginXml::encodeConfigurationChars(QString text)
Chris@81 40 {
Chris@81 41 QString rv(text);
Chris@81 42 rv.replace(";", "[[SEMICOLON]]");
Chris@81 43 rv.replace("=", "[[EQUALS]]");
Chris@81 44 return rv;
Chris@81 45 }
Chris@81 46
Chris@81 47 QString
Chris@81 48 PluginXml::decodeConfigurationChars(QString text)
Chris@81 49 {
Chris@81 50 QString rv(text);
Chris@81 51 rv.replace("[[SEMICOLON]]", ";");
Chris@81 52 rv.replace("[[EQUALS]]", "=");
Chris@81 53 return rv;
Chris@81 54 }
Chris@81 55
Chris@81 56 QString
Chris@66 57 PluginXml::toXmlString(QString indent, QString extraAttributes) const
Chris@66 58 {
Chris@66 59 QString s;
Chris@66 60 s += indent;
Chris@66 61
Chris@239 62 s += QString("<plugin identifier=\"%1\" name=\"%2\" description=\"%3\" maker=\"%4\" version=\"%5\" copyright=\"%6\" %7 ")
Chris@239 63 .arg(encodeEntities(QString(m_plugin->getIdentifier().c_str())))
Chris@66 64 .arg(encodeEntities(QString(m_plugin->getName().c_str())))
Chris@66 65 .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
Chris@66 66 .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
Chris@66 67 .arg(m_plugin->getPluginVersion())
Chris@66 68 .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
Chris@66 69 .arg(extraAttributes);
Chris@66 70
Chris@66 71 if (!m_plugin->getPrograms().empty()) {
Chris@66 72 s += QString("program=\"%1\" ")
Chris@66 73 .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
Chris@66 74 }
Chris@66 75
Chris@66 76 Vamp::PluginBase::ParameterList parameters =
Chris@66 77 m_plugin->getParameterDescriptors();
Chris@66 78
Chris@66 79 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@66 80 i != parameters.end(); ++i) {
Chris@185 81
Chris@185 82 // std::cerr << "PluginXml::toXmlString: parameter name \""
Chris@185 83 // << i->name.c_str() << "\" has value "
Chris@185 84 // << m_plugin->getParameter(i->name) << std::endl;
Chris@185 85
Chris@66 86 s += QString("param-%1=\"%2\" ")
Chris@239 87 .arg(stripInvalidParameterNameCharacters(QString(i->identifier.c_str())))
Chris@239 88 .arg(m_plugin->getParameter(i->identifier));
Chris@66 89 }
Chris@66 90
Chris@75 91 RealTimePluginInstance *rtpi =
Chris@75 92 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 93 if (rtpi) {
Chris@75 94 std::map<std::string, std::string> configurePairs =
Chris@75 95 rtpi->getConfigurePairs();
Chris@75 96 QString config;
Chris@75 97 for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
Chris@75 98 i != configurePairs.end(); ++i) {
Chris@75 99 QString key = i->first.c_str();
Chris@75 100 QString value = i->second.c_str();
Chris@81 101 key = encodeConfigurationChars(key);
Chris@81 102 value = encodeConfigurationChars(value);
Chris@75 103 if (config != "") config += ";";
Chris@75 104 config += QString("%1=%2").arg(key).arg(value);
Chris@75 105 }
Chris@75 106 if (config != "") {
Chris@75 107 s += QString("configuration=\"%1\" ")
Chris@75 108 .arg(encodeEntities(config));
Chris@75 109 }
Chris@75 110 }
Chris@75 111
Chris@66 112 s += "/>\n";
Chris@66 113 return s;
Chris@66 114 }
Chris@66 115
Chris@66 116 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
Chris@66 117 QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
Chris@66 118 if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
Chris@66 119 std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
Chris@66 120 << #ATTRIBUTE << " does not match (attributes have \"" \
Chris@66 121 << ATTRIBUTE.toStdString() << "\", my " \
Chris@66 122 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
Chris@66 123 }
Chris@66 124
Chris@66 125 void
Chris@66 126 PluginXml::setParameters(const QXmlAttributes &attrs)
Chris@66 127 {
Chris@239 128 CHECK_ATTRIBUTE(identifier, m_plugin->getIdentifier);
Chris@66 129 CHECK_ATTRIBUTE(name, m_plugin->getName);
Chris@66 130 CHECK_ATTRIBUTE(description, m_plugin->getDescription);
Chris@66 131 CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
Chris@66 132 CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
Chris@66 133
Chris@66 134 bool ok;
Chris@66 135 int version = attrs.value("version").trimmed().toInt(&ok);
Chris@66 136 if (ok && version != m_plugin->getPluginVersion()) {
Chris@66 137 std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
Chris@66 138 }
Chris@66 139
Chris@75 140 RealTimePluginInstance *rtpi =
Chris@75 141 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 142 if (rtpi) {
Chris@75 143 QString config = attrs.value("configuration");
Chris@75 144 if (config != "") {
Chris@75 145 QStringList configList = config.split(";");
Chris@75 146 for (QStringList::iterator i = configList.begin();
Chris@75 147 i != configList.end(); ++i) {
Chris@75 148 QStringList kv = i->split("=");
Chris@75 149 if (kv.count() < 2) {
Chris@75 150 std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl;
Chris@75 151 continue;
Chris@75 152 }
Chris@75 153 QString key(kv[0]), value(kv[1]);
Chris@81 154 key = decodeConfigurationChars(key);
Chris@81 155 value = decodeConfigurationChars(value);
Chris@75 156 rtpi->configure(key.toStdString(), value.toStdString());
Chris@75 157 }
Chris@75 158 }
Chris@75 159 }
Chris@75 160
Chris@66 161 if (!m_plugin->getPrograms().empty()) {
Chris@66 162 m_plugin->selectProgram(attrs.value("program").toStdString());
Chris@66 163 }
Chris@66 164
Chris@66 165 Vamp::PluginBase::ParameterList parameters =
Chris@66 166 m_plugin->getParameterDescriptors();
Chris@66 167
Chris@66 168 for (Vamp::PluginBase::ParameterList::const_iterator i =
Chris@66 169 parameters.begin(); i != parameters.end(); ++i) {
Chris@66 170
Chris@239 171 QString pname = QString("param-%1")
Chris@66 172 .arg(stripInvalidParameterNameCharacters
Chris@239 173 (QString(i->identifier.c_str())));
Chris@66 174
Chris@239 175 if (attrs.value(pname) == "") {
Chris@117 176 // std::cerr << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 177 continue;
Chris@66 178 }
Chris@66 179
Chris@66 180 bool ok;
Chris@239 181 float value = attrs.value(pname).trimmed().toFloat(&ok);
Chris@66 182 if (ok) {
Chris@260 183 // std::cerr << "PluginXml::setParameters: setting parameter \""
Chris@260 184 // << i->identifier << "\" to value " << value << std::endl;
Chris@239 185 m_plugin->setParameter(i->identifier, value);
Chris@66 186 } else {
Chris@239 187 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(pname).toStdString() << "\" for parameter \"" << i->identifier << "\" (attribute \"" << pname.toStdString() << "\")" << std::endl;
Chris@66 188 }
Chris@66 189 }
Chris@66 190 }
Chris@66 191
Chris@66 192 void
Chris@66 193 PluginXml::setParametersFromXml(QString xml)
Chris@66 194 {
Chris@66 195 QDomDocument doc;
Chris@66 196
Chris@66 197 QString error;
Chris@66 198 int errorLine;
Chris@66 199 int errorColumn;
Chris@66 200
Chris@185 201 // std::cerr << "PluginXml::setParametersFromXml: XML is \""
Chris@185 202 // << xml.toLocal8Bit().data() << "\"" << std::endl;
Chris@185 203
Chris@66 204 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@66 205 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
Chris@66 206 std::cerr << "Input follows:" << std::endl;
Chris@66 207 std::cerr << xml.toStdString() << std::endl;
Chris@66 208 std::cerr << "Input ends." << std::endl;
Chris@66 209 return;
Chris@66 210 }
Chris@66 211
Chris@66 212 QDomElement pluginElt = doc.firstChildElement("plugin");
Chris@66 213 QDomNamedNodeMap attrNodes = pluginElt.attributes();
Chris@66 214 QXmlAttributes attrs;
Chris@66 215
Chris@66 216 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@66 217 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@66 218 if (attr.isNull()) continue;
Chris@117 219 // std::cerr << "PluginXml::setParametersFromXml: Adding attribute \"" << attr.name().toStdString()
Chris@117 220 // << "\" with value \"" << attr.value().toStdString() << "\"" << std::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