PluginXml.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "PluginXml.h"
17 
18 #include <QRegExp>
19 #include <QXmlAttributes>
20 
21 #include <QDomDocument>
22 #include <QDomElement>
23 #include <QDomNamedNodeMap>
24 #include <QDomAttr>
25 
26 #include <QTextStream>
27 
28 #include <vamp-hostsdk/PluginBase.h>
29 #include "RealTimePluginInstance.h"
30 
31 #include <iostream>
32 
33 using std::shared_ptr;
34 using std::dynamic_pointer_cast;
35 
36 PluginXml::PluginXml(shared_ptr<Vamp::PluginBase> plugin) :
37  m_plugin(plugin)
38 {
39 }
40 
42 
43 QString
45 {
46  QString rv(text);
47  rv.replace(";", "[[SEMICOLON]]");
48  rv.replace("=", "[[EQUALS]]");
49  return rv;
50 }
51 
52 QString
54 {
55  QString rv(text);
56  rv.replace("[[SEMICOLON]]", ";");
57  rv.replace("[[EQUALS]]", "=");
58  return rv;
59 }
60 
61 void
62 PluginXml::toXml(QTextStream &stream,
63  QString indent, QString extraAttributes) const
64 {
65  stream << indent;
66 
67  stream << QString("<plugin identifier=\"%1\" name=\"%2\" description=\"%3\" maker=\"%4\" version=\"%5\" copyright=\"%6\" %7 ")
68  .arg(encodeEntities(QString(m_plugin->getIdentifier().c_str())))
69  .arg(encodeEntities(QString(m_plugin->getName().c_str())))
70  .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
71  .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
72  .arg(m_plugin->getPluginVersion())
73  .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
74  .arg(extraAttributes);
75 
76  if (!m_plugin->getPrograms().empty()) {
77  stream << QString("program=\"%1\" ")
78  .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
79  }
80 
81  Vamp::PluginBase::ParameterList parameters =
82  m_plugin->getParameterDescriptors();
83 
84  for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
85  i != parameters.end(); ++i) {
86 
87 // SVDEBUG << "PluginXml::toXml: parameter name \""
88 // << i->name.c_str() << "\" has value "
89 // << m_plugin->getParameter(i->name) << endl;
90 
91  stream << QString("param-%1=\"%2\" ")
92  .arg(stripInvalidParameterNameCharacters(QString(i->identifier.c_str())))
93  .arg(m_plugin->getParameter(i->identifier));
94  }
95 
96  auto rtpi = dynamic_pointer_cast<RealTimePluginInstance>(m_plugin);
97  if (rtpi) {
98  std::map<std::string, std::string> configurePairs =
99  rtpi->getConfigurePairs();
100  QString config;
101  for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
102  i != configurePairs.end(); ++i) {
103  QString key = i->first.c_str();
104  QString value = i->second.c_str();
105  key = encodeConfigurationChars(key);
106  value = encodeConfigurationChars(value);
107  if (config != "") config += ";";
108  config += QString("%1=%2").arg(key).arg(value);
109  }
110  if (config != "") {
111  stream << QString("configuration=\"%1\" ")
112  .arg(encodeEntities(config));
113  }
114  }
115 
116  stream << "/>\n";
117 }
118 
119 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
120  QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
121  if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
122  cerr << "WARNING: PluginXml::setParameters: Plugin " \
123  << #ATTRIBUTE << " does not match (attributes have \"" \
124  << ATTRIBUTE << "\", my " \
125  << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << endl; \
126  }
127 
128 void
129 PluginXml::setParameters(const QXmlAttributes &attrs)
130 {
131  CHECK_ATTRIBUTE(identifier, m_plugin->getIdentifier);
132  CHECK_ATTRIBUTE(name, m_plugin->getName);
133  CHECK_ATTRIBUTE(description, m_plugin->getDescription);
134  CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
135  CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
136 
137  bool ok;
138  int version = attrs.value("version").trimmed().toInt(&ok);
139  if (ok && version != m_plugin->getPluginVersion()) {
140  cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << endl;
141  }
142 
143  auto rtpi = dynamic_pointer_cast<RealTimePluginInstance>(m_plugin);
144  if (rtpi) {
145  QString config = attrs.value("configuration");
146  if (config != "") {
147  QStringList configList = config.split(";");
148  for (QStringList::iterator i = configList.begin();
149  i != configList.end(); ++i) {
150  QStringList kv = i->split("=");
151  if (kv.count() < 2) {
152  cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << *i << "\"" << endl;
153  continue;
154  }
155  QString key(kv[0]), value(kv[1]);
156  key = decodeConfigurationChars(key);
157  value = decodeConfigurationChars(value);
158  rtpi->configure(key.toStdString(), value.toStdString());
159  }
160  }
161  }
162 
163  if (!m_plugin->getPrograms().empty()) {
164  m_plugin->selectProgram(attrs.value("program").toStdString());
165  }
166 
167  Vamp::PluginBase::ParameterList parameters =
168  m_plugin->getParameterDescriptors();
169 
170  for (Vamp::PluginBase::ParameterList::const_iterator i =
171  parameters.begin(); i != parameters.end(); ++i) {
172 
173  QString pname = QString("param-%1")
175  (QString(i->identifier.c_str())));
176 
177  if (attrs.value(pname) == "") {
178 // SVDEBUG << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name << "\")" << endl;
179  continue;
180  }
181 
182  bool ok;
183  float value = attrs.value(pname).trimmed().toFloat(&ok);
184  if (ok) {
185 // SVDEBUG << "PluginXml::setParameters: setting parameter \""
186 // << i->identifier << "\" to value " << value << endl;
187  m_plugin->setParameter(i->identifier, value);
188  } else {
189  cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(pname) << "\" for parameter \"" << i->identifier << "\" (attribute \"" << pname << "\")" << endl;
190  }
191  }
192 }
193 
194 void
196 {
197  QDomDocument doc;
198 
199  QString error;
200  int errorLine;
201  int errorColumn;
202 
203 // SVDEBUG << "PluginXml::setParametersFromXml: XML is \""
204 // << xml << "\"" << endl;
205 
206  if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
207  cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error << " at line " << errorLine << ", column " << errorColumn << endl;
208  cerr << "Input follows:" << endl;
209  cerr << xml << endl;
210  cerr << "Input ends." << endl;
211  return;
212  }
213 
214  QDomElement pluginElt = doc.firstChildElement("plugin");
215  QDomNamedNodeMap attrNodes = pluginElt.attributes();
216  QXmlAttributes attrs;
217 
218  for (int i = 0; i < attrNodes.length(); ++i) {
219  QDomAttr attr = attrNodes.item(i).toAttr();
220  if (attr.isNull()) continue;
221 // SVDEBUG << "PluginXml::setParametersFromXml: Adding attribute \"" << attr.name()// << "\" with value \"" << attr.value() << "\"" << endl;
222  attrs.append(attr.name(), "", "", attr.value());
223  }
224 
225  setParameters(attrs);
226 }
227 
228 QString
230 {
231  s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
232  return s;
233 }
234 
virtual void setParametersFromXml(QString xml)
Set the parameters and program of a plugin from an XML plugin element as returned by toXml...
Definition: PluginXml.cpp:195
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
Export plugin settings to XML.
Definition: PluginXml.cpp:62
QString stripInvalidParameterNameCharacters(QString) const
Definition: PluginXml.cpp:229
static QString encodeEntities(QString)
virtual void setParameters(const QXmlAttributes &)
Set the parameters and program of a plugin from a set of XML attributes.
Definition: PluginXml.cpp:129
virtual ~PluginXml()
Definition: PluginXml.cpp:41
#define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR)
Definition: PluginXml.cpp:119
PluginXml(std::shared_ptr< Vamp::PluginBase > plugin)
Definition: PluginXml.cpp:36
std::shared_ptr< Vamp::PluginBase > m_plugin
Definition: PluginXml.h:58
virtual ConfigurationPairMap getConfigurePairs()
static QString decodeConfigurationChars(QString text)
Definition: PluginXml.cpp:53
static QString encodeConfigurationChars(QString text)
Definition: PluginXml.cpp:44