comparison plugin/PluginXml.cpp @ 0:fc9323a41f5a

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