00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "PluginXml.h"
00017
00018 #include <QRegExp>
00019 #include <QXmlAttributes>
00020
00021 #include <QDomDocument>
00022 #include <QDomElement>
00023 #include <QDomNamedNodeMap>
00024 #include <QDomAttr>
00025
00026 #include <QTextStream>
00027
00028 #include "vamp-sdk/PluginBase.h"
00029 #include "RealTimePluginInstance.h"
00030
00031 #include <iostream>
00032
00033 PluginXml::PluginXml(Vamp::PluginBase *plugin) :
00034 m_plugin(plugin)
00035 {
00036 }
00037
00038 PluginXml::~PluginXml() { }
00039
00040 QString
00041 PluginXml::encodeConfigurationChars(QString text)
00042 {
00043 QString rv(text);
00044 rv.replace(";", "[[SEMICOLON]]");
00045 rv.replace("=", "[[EQUALS]]");
00046 return rv;
00047 }
00048
00049 QString
00050 PluginXml::decodeConfigurationChars(QString text)
00051 {
00052 QString rv(text);
00053 rv.replace("[[SEMICOLON]]", ";");
00054 rv.replace("[[EQUALS]]", "=");
00055 return rv;
00056 }
00057
00058 void
00059 PluginXml::toXml(QTextStream &stream,
00060 QString indent, QString extraAttributes) const
00061 {
00062 stream << indent;
00063
00064 stream << QString("<plugin identifier=\"%1\" name=\"%2\" description=\"%3\" maker=\"%4\" version=\"%5\" copyright=\"%6\" %7 ")
00065 .arg(encodeEntities(QString(m_plugin->getIdentifier().c_str())))
00066 .arg(encodeEntities(QString(m_plugin->getName().c_str())))
00067 .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
00068 .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
00069 .arg(m_plugin->getPluginVersion())
00070 .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
00071 .arg(extraAttributes);
00072
00073 if (!m_plugin->getPrograms().empty()) {
00074 stream << QString("program=\"%1\" ")
00075 .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
00076 }
00077
00078 Vamp::PluginBase::ParameterList parameters =
00079 m_plugin->getParameterDescriptors();
00080
00081 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
00082 i != parameters.end(); ++i) {
00083
00084
00085
00086
00087
00088 stream << QString("param-%1=\"%2\" ")
00089 .arg(stripInvalidParameterNameCharacters(QString(i->identifier.c_str())))
00090 .arg(m_plugin->getParameter(i->identifier));
00091 }
00092
00093 RealTimePluginInstance *rtpi =
00094 dynamic_cast<RealTimePluginInstance *>(m_plugin);
00095 if (rtpi) {
00096 std::map<std::string, std::string> configurePairs =
00097 rtpi->getConfigurePairs();
00098 QString config;
00099 for (std::map<std::string, std::string>::iterator i = configurePairs.begin();
00100 i != configurePairs.end(); ++i) {
00101 QString key = i->first.c_str();
00102 QString value = i->second.c_str();
00103 key = encodeConfigurationChars(key);
00104 value = encodeConfigurationChars(value);
00105 if (config != "") config += ";";
00106 config += QString("%1=%2").arg(key).arg(value);
00107 }
00108 if (config != "") {
00109 stream << QString("configuration=\"%1\" ")
00110 .arg(encodeEntities(config));
00111 }
00112 }
00113
00114 stream << "/>\n";
00115 }
00116
00117 #define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
00118 QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
00119 if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
00120 std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
00121 << #ATTRIBUTE << " does not match (attributes have \"" \
00122 << ATTRIBUTE.toStdString() << "\", my " \
00123 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
00124 }
00125
00126 void
00127 PluginXml::setParameters(const QXmlAttributes &attrs)
00128 {
00129 CHECK_ATTRIBUTE(identifier, m_plugin->getIdentifier);
00130 CHECK_ATTRIBUTE(name, m_plugin->getName);
00131 CHECK_ATTRIBUTE(description, m_plugin->getDescription);
00132 CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
00133 CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
00134
00135 bool ok;
00136 int version = attrs.value("version").trimmed().toInt(&ok);
00137 if (ok && version != m_plugin->getPluginVersion()) {
00138 std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
00139 }
00140
00141 RealTimePluginInstance *rtpi =
00142 dynamic_cast<RealTimePluginInstance *>(m_plugin);
00143 if (rtpi) {
00144 QString config = attrs.value("configuration");
00145 if (config != "") {
00146 QStringList configList = config.split(";");
00147 for (QStringList::iterator i = configList.begin();
00148 i != configList.end(); ++i) {
00149 QStringList kv = i->split("=");
00150 if (kv.count() < 2) {
00151 std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl;
00152 continue;
00153 }
00154 QString key(kv[0]), value(kv[1]);
00155 key = decodeConfigurationChars(key);
00156 value = decodeConfigurationChars(value);
00157 rtpi->configure(key.toStdString(), value.toStdString());
00158 }
00159 }
00160 }
00161
00162 if (!m_plugin->getPrograms().empty()) {
00163 m_plugin->selectProgram(attrs.value("program").toStdString());
00164 }
00165
00166 Vamp::PluginBase::ParameterList parameters =
00167 m_plugin->getParameterDescriptors();
00168
00169 for (Vamp::PluginBase::ParameterList::const_iterator i =
00170 parameters.begin(); i != parameters.end(); ++i) {
00171
00172 QString pname = QString("param-%1")
00173 .arg(stripInvalidParameterNameCharacters
00174 (QString(i->identifier.c_str())));
00175
00176 if (attrs.value(pname) == "") {
00177
00178 continue;
00179 }
00180
00181 bool ok;
00182 float value = attrs.value(pname).trimmed().toFloat(&ok);
00183 if (ok) {
00184
00185
00186 m_plugin->setParameter(i->identifier, value);
00187 } else {
00188 std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(pname).toStdString() << "\" for parameter \"" << i->identifier << "\" (attribute \"" << pname.toStdString() << "\")" << std::endl;
00189 }
00190 }
00191 }
00192
00193 void
00194 PluginXml::setParametersFromXml(QString xml)
00195 {
00196 QDomDocument doc;
00197
00198 QString error;
00199 int errorLine;
00200 int errorColumn;
00201
00202
00203
00204
00205 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
00206 std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
00207 std::cerr << "Input follows:" << std::endl;
00208 std::cerr << xml.toStdString() << std::endl;
00209 std::cerr << "Input ends." << std::endl;
00210 return;
00211 }
00212
00213 QDomElement pluginElt = doc.firstChildElement("plugin");
00214 QDomNamedNodeMap attrNodes = pluginElt.attributes();
00215 QXmlAttributes attrs;
00216
00217 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
00218 QDomAttr attr = attrNodes.item(i).toAttr();
00219 if (attr.isNull()) continue;
00220
00221
00222 attrs.append(attr.name(), "", "", attr.value());
00223 }
00224
00225 setParameters(attrs);
00226 }
00227
00228 QString
00229 PluginXml::stripInvalidParameterNameCharacters(QString s) const
00230 {
00231 s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
00232 return s;
00233 }
00234