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
|