annotate plugin/PluginXml.cpp @ 76:af2725b5d6fe

* Implement harmonic cursor in spectrogram * Implement layer export. This doesn't quite do the right thing for the SV XML layer export yet -- it doesn't include layer display information, so when imported, it only creates an invisible model. Could also do with fixing CSV file import so as to work correctly for note and text layers.
author Chris Cannam
date Mon, 10 Apr 2006 17:22:59 +0000
parents 163f3428bbe0
children f277a171749d
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@66 39 PluginXml::toXmlString(QString indent, QString extraAttributes) const
Chris@66 40 {
Chris@66 41 QString s;
Chris@66 42 s += indent;
Chris@66 43
Chris@66 44 s += QString("<plugin name=\"%1\" description=\"%2\" maker=\"%3\" version=\"%4\" copyright=\"%5\" %6 ")
Chris@66 45 .arg(encodeEntities(QString(m_plugin->getName().c_str())))
Chris@66 46 .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
Chris@66 47 .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
Chris@66 48 .arg(m_plugin->getPluginVersion())
Chris@66 49 .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
Chris@66 50 .arg(extraAttributes);
Chris@66 51
Chris@66 52 if (!m_plugin->getPrograms().empty()) {
Chris@66 53 s += QString("program=\"%1\" ")
Chris@66 54 .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
Chris@66 55 }
Chris@66 56
Chris@66 57 Vamp::PluginBase::ParameterList parameters =
Chris@66 58 m_plugin->getParameterDescriptors();
Chris@66 59
Chris@66 60 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@66 61 i != parameters.end(); ++i) {
Chris@66 62 s += QString("param-%1=\"%2\" ")
Chris@66 63 .arg(stripInvalidParameterNameCharacters(QString(i->name.c_str())))
Chris@66 64 .arg(m_plugin->getParameter(i->name));
Chris@66 65 }
Chris@66 66
Chris@75 67 RealTimePluginInstance *rtpi =
Chris@75 68 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 69 if (rtpi) {
Chris@75 70 std::map<std::string, std::string> configurePairs =
Chris@75 71 rtpi->getConfigurePairs();
Chris@75 72 QString config;
Chris@75 73 for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
Chris@75 74 i != configurePairs.end(); ++i) {
Chris@75 75 QString key = i->first.c_str();
Chris@75 76 QString value = i->second.c_str();
Chris@75 77 key.replace(";", "[[SEMICOLON]]");
Chris@75 78 key.replace("=", "[[EQUALS]]");
Chris@75 79 value.replace(";", "[[SEMICOLON]]");
Chris@75 80 value.replace("=", "[[EQUALS]]");
Chris@75 81 if (config != "") config += ";";
Chris@75 82 config += QString("%1=%2").arg(key).arg(value);
Chris@75 83 }
Chris@75 84 if (config != "") {
Chris@75 85 s += QString("configuration=\"%1\" ")
Chris@75 86 .arg(encodeEntities(config));
Chris@75 87 }
Chris@75 88 }
Chris@75 89
Chris@66 90 s += "/>\n";
Chris@66 91 return s;
Chris@66 92 }
Chris@66 93
Chris@66 94 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
Chris@66 95 QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
Chris@66 96 if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
Chris@66 97 std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
Chris@66 98 << #ATTRIBUTE << " does not match (attributes have \"" \
Chris@66 99 << ATTRIBUTE.toStdString() << "\", my " \
Chris@66 100 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
Chris@66 101 }
Chris@66 102
Chris@66 103 void
Chris@66 104 PluginXml::setParameters(const QXmlAttributes &attrs)
Chris@66 105 {
Chris@66 106 CHECK_ATTRIBUTE(name, m_plugin->getName);
Chris@66 107 CHECK_ATTRIBUTE(description, m_plugin->getDescription);
Chris@66 108 CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
Chris@66 109 CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
Chris@66 110
Chris@66 111 bool ok;
Chris@66 112 int version = attrs.value("version").trimmed().toInt(&ok);
Chris@66 113 if (ok && version != m_plugin->getPluginVersion()) {
Chris@66 114 std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
Chris@66 115 }
Chris@66 116
Chris@75 117 RealTimePluginInstance *rtpi =
Chris@75 118 dynamic_cast<RealTimePluginInstance *>(m_plugin);
Chris@75 119 if (rtpi) {
Chris@75 120 QString config = attrs.value("configuration");
Chris@75 121 if (config != "") {
Chris@75 122 QStringList configList = config.split(";");
Chris@75 123 for (QStringList::iterator i = configList.begin();
Chris@75 124 i != configList.end(); ++i) {
Chris@75 125 QStringList kv = i->split("=");
Chris@75 126 if (kv.count() < 2) {
Chris@75 127 std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl;
Chris@75 128 continue;
Chris@75 129 }
Chris@75 130 QString key(kv[0]), value(kv[1]);
Chris@75 131 key.replace("[[SEMICOLON]]", ";");
Chris@75 132 key.replace("[[EQUALS]]", ";");
Chris@75 133 value.replace("[[SEMICOLON]]", ";");
Chris@75 134 value.replace("[[SEMICOLON]]", ";");
Chris@75 135 rtpi->configure(key.toStdString(), value.toStdString());
Chris@75 136 }
Chris@75 137 }
Chris@75 138 }
Chris@75 139
Chris@66 140 if (!m_plugin->getPrograms().empty()) {
Chris@66 141 m_plugin->selectProgram(attrs.value("program").toStdString());
Chris@66 142 }
Chris@66 143
Chris@66 144 Vamp::PluginBase::ParameterList parameters =
Chris@66 145 m_plugin->getParameterDescriptors();
Chris@66 146
Chris@66 147 for (Vamp::PluginBase::ParameterList::const_iterator i =
Chris@66 148 parameters.begin(); i != parameters.end(); ++i) {
Chris@66 149
Chris@66 150 QString name = QString("param-%1")
Chris@66 151 .arg(stripInvalidParameterNameCharacters
Chris@66 152 (QString(i->name.c_str())));
Chris@66 153
Chris@66 154 if (attrs.value(name) == "") {
Chris@66 155 std::cerr << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 156 continue;
Chris@66 157 }
Chris@66 158
Chris@66 159 bool ok;
Chris@66 160 float value = attrs.value(name).trimmed().toFloat(&ok);
Chris@66 161 if (ok) {
Chris@66 162 m_plugin->setParameter(i->name, value);
Chris@66 163 } else {
Chris@66 164 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(name).toStdString() << "\" for parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
Chris@66 165 }
Chris@66 166 }
Chris@66 167 }
Chris@66 168
Chris@66 169 void
Chris@66 170 PluginXml::setParametersFromXml(QString xml)
Chris@66 171 {
Chris@66 172 QDomDocument doc;
Chris@66 173
Chris@66 174 QString error;
Chris@66 175 int errorLine;
Chris@66 176 int errorColumn;
Chris@66 177
Chris@66 178 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@66 179 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
Chris@66 180 std::cerr << "Input follows:" << std::endl;
Chris@66 181 std::cerr << xml.toStdString() << std::endl;
Chris@66 182 std::cerr << "Input ends." << std::endl;
Chris@66 183 return;
Chris@66 184 }
Chris@66 185
Chris@66 186 QDomElement pluginElt = doc.firstChildElement("plugin");
Chris@66 187 QDomNamedNodeMap attrNodes = pluginElt.attributes();
Chris@66 188 QXmlAttributes attrs;
Chris@66 189
Chris@66 190 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@66 191 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@66 192 if (attr.isNull()) continue;
Chris@66 193 std::cerr << "Adding attribute \"" << attr.name().toStdString()
Chris@66 194 << "\" with value \"" << attr.value().toStdString() << "\"" << std::endl;
Chris@66 195 attrs.append(attr.name(), "", "", attr.value());
Chris@66 196 }
Chris@66 197
Chris@66 198 setParameters(attrs);
Chris@66 199 }
Chris@66 200
Chris@66 201 QString
Chris@66 202 PluginXml::stripInvalidParameterNameCharacters(QString s) const
Chris@66 203 {
Chris@66 204 s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
Chris@66 205 return s;
Chris@66 206 }
Chris@66 207