annotate plugin/PluginXml.cpp @ 188:f86b74d1b143

* Simplify maker names in plugin menu * Make sure derived models have a name (based on the transform) * Don't start deriving a model from a derived model until the derived model is ready * Tidy up completion management in writable wave file model * Make writable models save/reload correctly from session file (i.e. regenerating from the original transform) * Same for dense 3d models -- don't save the data, just the transform details * Add a comment describing the SV file format
author Chris Cannam
date Fri, 13 Oct 2006 12:51:05 +0000
parents d5052b5fea9c
children 71f869dac40b
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@66 62 s += QString("<plugin name=\"%1\" description=\"%2\" maker=\"%3\" version=\"%4\" copyright=\"%5\" %6 ")
Chris@66 63 .arg(encodeEntities(QString(m_plugin->getName().c_str())))
Chris@66 64 .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
Chris@66 65 .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
Chris@66 66 .arg(m_plugin->getPluginVersion())
Chris@66 67 .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
Chris@66 68 .arg(extraAttributes);
Chris@66 69
Chris@66 70 if (!m_plugin->getPrograms().empty()) {
Chris@66 71 s += QString("program=\"%1\" ")
Chris@66 72 .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
Chris@66 73 }
Chris@66 74
Chris@66 75 Vamp::PluginBase::ParameterList parameters =
Chris@66 76 m_plugin->getParameterDescriptors();
Chris@66 77
Chris@66 78 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@66 79 i != parameters.end(); ++i) {
Chris@185 80
Chris@185 81 // std::cerr << "PluginXml::toXmlString: parameter name \""
Chris@185 82 // << i->name.c_str() << "\" has value "
Chris@185 83 // << m_plugin->getParameter(i->name) << std::endl;
Chris@185 84
Chris@66 85 s += QString("param-%1=\"%2\" ")
Chris@66 86 .arg(stripInvalidParameterNameCharacters(QString(i->name.c_str())))
Chris@66 87 .arg(m_plugin->getParameter(i->name));
Chris@66 88 }
Chris@66 89
Chris@75 90 RealTimePluginInstance *rtpi =
Chris@75 91 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 92 if (rtpi) {
Chris@75 93 std::map<std::string, std::string> configurePairs =
Chris@75 94 rtpi->getConfigurePairs();
Chris@75 95 QString config;
Chris@75 96 for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
Chris@75 97 i != configurePairs.end(); ++i) {
Chris@75 98 QString key = i->first.c_str();
Chris@75 99 QString value = i->second.c_str();
Chris@81 100 key = encodeConfigurationChars(key);
Chris@81 101 value = encodeConfigurationChars(value);
Chris@75 102 if (config != "") config += ";";
Chris@75 103 config += QString("%1=%2").arg(key).arg(value);
Chris@75 104 }
Chris@75 105 if (config != "") {
Chris@75 106 s += QString("configuration=\"%1\" ")
Chris@75 107 .arg(encodeEntities(config));
Chris@75 108 }
Chris@75 109 }
Chris@75 110
Chris@66 111 s += "/>\n";
Chris@66 112 return s;
Chris@66 113 }
Chris@66 114
Chris@66 115 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
Chris@66 116 QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
Chris@66 117 if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
Chris@66 118 std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
Chris@66 119 << #ATTRIBUTE << " does not match (attributes have \"" \
Chris@66 120 << ATTRIBUTE.toStdString() << "\", my " \
Chris@66 121 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
Chris@66 122 }
Chris@66 123
Chris@66 124 void
Chris@66 125 PluginXml::setParameters(const QXmlAttributes &attrs)
Chris@66 126 {
Chris@66 127 CHECK_ATTRIBUTE(name, m_plugin->getName);
Chris@66 128 CHECK_ATTRIBUTE(description, m_plugin->getDescription);
Chris@66 129 CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
Chris@66 130 CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
Chris@66 131
Chris@66 132 bool ok;
Chris@66 133 int version = attrs.value("version").trimmed().toInt(&ok);
Chris@66 134 if (ok && version != m_plugin->getPluginVersion()) {
Chris@66 135 std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
Chris@66 136 }
Chris@66 137
Chris@75 138 RealTimePluginInstance *rtpi =
Chris@75 139 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 140 if (rtpi) {
Chris@75 141 QString config = attrs.value("configuration");
Chris@75 142 if (config != "") {
Chris@75 143 QStringList configList = config.split(";");
Chris@75 144 for (QStringList::iterator i = configList.begin();
Chris@75 145 i != configList.end(); ++i) {
Chris@75 146 QStringList kv = i->split("=");
Chris@75 147 if (kv.count() < 2) {
Chris@75 148 std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl;
Chris@75 149 continue;
Chris@75 150 }
Chris@75 151 QString key(kv[0]), value(kv[1]);
Chris@81 152 key = decodeConfigurationChars(key);
Chris@81 153 value = decodeConfigurationChars(value);
Chris@75 154 rtpi->configure(key.toStdString(), value.toStdString());
Chris@75 155 }
Chris@75 156 }
Chris@75 157 }
Chris@75 158
Chris@66 159 if (!m_plugin->getPrograms().empty()) {
Chris@66 160 m_plugin->selectProgram(attrs.value("program").toStdString());
Chris@66 161 }
Chris@66 162
Chris@66 163 Vamp::PluginBase::ParameterList parameters =
Chris@66 164 m_plugin->getParameterDescriptors();
Chris@66 165
Chris@66 166 for (Vamp::PluginBase::ParameterList::const_iterator i =
Chris@66 167 parameters.begin(); i != parameters.end(); ++i) {
Chris@66 168
Chris@66 169 QString name = QString("param-%1")
Chris@66 170 .arg(stripInvalidParameterNameCharacters
Chris@66 171 (QString(i->name.c_str())));
Chris@66 172
Chris@66 173 if (attrs.value(name) == "") {
Chris@117 174 // std::cerr << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 175 continue;
Chris@66 176 }
Chris@66 177
Chris@66 178 bool ok;
Chris@66 179 float value = attrs.value(name).trimmed().toFloat(&ok);
Chris@66 180 if (ok) {
Chris@66 181 m_plugin->setParameter(i->name, value);
Chris@66 182 } else {
Chris@66 183 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(name).toStdString() << "\" for parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 184 }
Chris@66 185 }
Chris@66 186 }
Chris@66 187
Chris@66 188 void
Chris@66 189 PluginXml::setParametersFromXml(QString xml)
Chris@66 190 {
Chris@66 191 QDomDocument doc;
Chris@66 192
Chris@66 193 QString error;
Chris@66 194 int errorLine;
Chris@66 195 int errorColumn;
Chris@66 196
Chris@185 197 // std::cerr << "PluginXml::setParametersFromXml: XML is \""
Chris@185 198 // << xml.toLocal8Bit().data() << "\"" << std::endl;
Chris@185 199
Chris@66 200 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@66 201 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
Chris@66 202 std::cerr << "Input follows:" << std::endl;
Chris@66 203 std::cerr << xml.toStdString() << std::endl;
Chris@66 204 std::cerr << "Input ends." << std::endl;
Chris@66 205 return;
Chris@66 206 }
Chris@66 207
Chris@66 208 QDomElement pluginElt = doc.firstChildElement("plugin");
Chris@66 209 QDomNamedNodeMap attrNodes = pluginElt.attributes();
Chris@66 210 QXmlAttributes attrs;
Chris@66 211
Chris@66 212 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@66 213 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@66 214 if (attr.isNull()) continue;
Chris@117 215 // std::cerr << "PluginXml::setParametersFromXml: Adding attribute \"" << attr.name().toStdString()
Chris@117 216 // << "\" with value \"" << attr.value().toStdString() << "\"" << std::endl;
Chris@66 217 attrs.append(attr.name(), "", "", attr.value());
Chris@66 218 }
Chris@66 219
Chris@66 220 setParameters(attrs);
Chris@66 221 }
Chris@163 222
Chris@66 223 QString
Chris@66 224 PluginXml::stripInvalidParameterNameCharacters(QString s) const
Chris@66 225 {
Chris@66 226 s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
Chris@66 227 return s;
Chris@66 228 }
Chris@66 229