annotate plugin/PluginXml.cpp @ 97:22494cc28c9f

* Reduce number of allocations and deallocations by keeping a spare buffer around (we were generally deallocating and then immediately allocating again, so it's much better not to have to bother as very large allocations can tie up the system)
author Chris Cannam
date Thu, 04 May 2006 20:17:28 +0000
parents f277a171749d
children c30728d5625c
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@66 80 s += QString("param-%1=\"%2\" ")
Chris@66 81 .arg(stripInvalidParameterNameCharacters(QString(i->name.c_str())))
Chris@66 82 .arg(m_plugin->getParameter(i->name));
Chris@66 83 }
Chris@66 84
Chris@75 85 RealTimePluginInstance *rtpi =
Chris@75 86 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 87 if (rtpi) {
Chris@75 88 std::map<std::string, std::string> configurePairs =
Chris@75 89 rtpi->getConfigurePairs();
Chris@75 90 QString config;
Chris@75 91 for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
Chris@75 92 i != configurePairs.end(); ++i) {
Chris@75 93 QString key = i->first.c_str();
Chris@75 94 QString value = i->second.c_str();
Chris@81 95 key = encodeConfigurationChars(key);
Chris@81 96 value = encodeConfigurationChars(value);
Chris@75 97 if (config != "") config += ";";
Chris@75 98 config += QString("%1=%2").arg(key).arg(value);
Chris@75 99 }
Chris@75 100 if (config != "") {
Chris@75 101 s += QString("configuration=\"%1\" ")
Chris@75 102 .arg(encodeEntities(config));
Chris@75 103 }
Chris@75 104 }
Chris@75 105
Chris@66 106 s += "/>\n";
Chris@66 107 return s;
Chris@66 108 }
Chris@66 109
Chris@66 110 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
Chris@66 111 QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
Chris@66 112 if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
Chris@66 113 std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
Chris@66 114 << #ATTRIBUTE << " does not match (attributes have \"" \
Chris@66 115 << ATTRIBUTE.toStdString() << "\", my " \
Chris@66 116 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
Chris@66 117 }
Chris@66 118
Chris@66 119 void
Chris@66 120 PluginXml::setParameters(const QXmlAttributes &attrs)
Chris@66 121 {
Chris@66 122 CHECK_ATTRIBUTE(name, m_plugin->getName);
Chris@66 123 CHECK_ATTRIBUTE(description, m_plugin->getDescription);
Chris@66 124 CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
Chris@66 125 CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
Chris@66 126
Chris@66 127 bool ok;
Chris@66 128 int version = attrs.value("version").trimmed().toInt(&ok);
Chris@66 129 if (ok && version != m_plugin->getPluginVersion()) {
Chris@66 130 std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
Chris@66 131 }
Chris@66 132
Chris@75 133 RealTimePluginInstance *rtpi =
Chris@75 134 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 135 if (rtpi) {
Chris@75 136 QString config = attrs.value("configuration");
Chris@75 137 if (config != "") {
Chris@75 138 QStringList configList = config.split(";");
Chris@75 139 for (QStringList::iterator i = configList.begin();
Chris@75 140 i != configList.end(); ++i) {
Chris@75 141 QStringList kv = i->split("=");
Chris@75 142 if (kv.count() < 2) {
Chris@75 143 std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl;
Chris@75 144 continue;
Chris@75 145 }
Chris@75 146 QString key(kv[0]), value(kv[1]);
Chris@81 147 key = decodeConfigurationChars(key);
Chris@81 148 value = decodeConfigurationChars(value);
Chris@75 149 rtpi->configure(key.toStdString(), value.toStdString());
Chris@75 150 }
Chris@75 151 }
Chris@75 152 }
Chris@75 153
Chris@66 154 if (!m_plugin->getPrograms().empty()) {
Chris@66 155 m_plugin->selectProgram(attrs.value("program").toStdString());
Chris@66 156 }
Chris@66 157
Chris@66 158 Vamp::PluginBase::ParameterList parameters =
Chris@66 159 m_plugin->getParameterDescriptors();
Chris@66 160
Chris@66 161 for (Vamp::PluginBase::ParameterList::const_iterator i =
Chris@66 162 parameters.begin(); i != parameters.end(); ++i) {
Chris@66 163
Chris@66 164 QString name = QString("param-%1")
Chris@66 165 .arg(stripInvalidParameterNameCharacters
Chris@66 166 (QString(i->name.c_str())));
Chris@66 167
Chris@66 168 if (attrs.value(name) == "") {
Chris@66 169 std::cerr << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 170 continue;
Chris@66 171 }
Chris@66 172
Chris@66 173 bool ok;
Chris@66 174 float value = attrs.value(name).trimmed().toFloat(&ok);
Chris@66 175 if (ok) {
Chris@66 176 m_plugin->setParameter(i->name, value);
Chris@66 177 } else {
Chris@66 178 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(name).toStdString() << "\" for parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 179 }
Chris@66 180 }
Chris@66 181 }
Chris@66 182
Chris@66 183 void
Chris@66 184 PluginXml::setParametersFromXml(QString xml)
Chris@66 185 {
Chris@66 186 QDomDocument doc;
Chris@66 187
Chris@66 188 QString error;
Chris@66 189 int errorLine;
Chris@66 190 int errorColumn;
Chris@66 191
Chris@66 192 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@66 193 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
Chris@66 194 std::cerr << "Input follows:" << std::endl;
Chris@66 195 std::cerr << xml.toStdString() << std::endl;
Chris@66 196 std::cerr << "Input ends." << std::endl;
Chris@66 197 return;
Chris@66 198 }
Chris@66 199
Chris@66 200 QDomElement pluginElt = doc.firstChildElement("plugin");
Chris@66 201 QDomNamedNodeMap attrNodes = pluginElt.attributes();
Chris@66 202 QXmlAttributes attrs;
Chris@66 203
Chris@66 204 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@66 205 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@66 206 if (attr.isNull()) continue;
Chris@66 207 std::cerr << "Adding attribute \"" << attr.name().toStdString()
Chris@66 208 << "\" with value \"" << attr.value().toStdString() << "\"" << std::endl;
Chris@66 209 attrs.append(attr.name(), "", "", attr.value());
Chris@66 210 }
Chris@66 211
Chris@66 212 setParameters(attrs);
Chris@66 213 }
Chris@66 214
Chris@66 215 QString
Chris@66 216 PluginXml::stripInvalidParameterNameCharacters(QString s) const
Chris@66 217 {
Chris@66 218 s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
Chris@66 219 return s;
Chris@66 220 }
Chris@66 221