svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 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-hostsdk/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 // SVDEBUG << "PluginXml::toXml: parameter name \"" 00085 // << i->name.c_str() << "\" has value " 00086 // << m_plugin->getParameter(i->name) << endl; 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 cerr << "WARNING: PluginXml::setParameters: Plugin " \ 00121 << #ATTRIBUTE << " does not match (attributes have \"" \ 00122 << ATTRIBUTE << "\", my " \ 00123 << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << 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 cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << 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 cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << *i << "\"" << 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 // SVDEBUG << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name << "\")" << endl; 00178 continue; 00179 } 00180 00181 bool ok; 00182 float value = attrs.value(pname).trimmed().toFloat(&ok); 00183 if (ok) { 00184 // SVDEBUG << "PluginXml::setParameters: setting parameter \"" 00185 // << i->identifier << "\" to value " << value << endl; 00186 m_plugin->setParameter(i->identifier, value); 00187 } else { 00188 cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(pname) << "\" for parameter \"" << i->identifier << "\" (attribute \"" << pname << "\")" << 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 // SVDEBUG << "PluginXml::setParametersFromXml: XML is \"" 00203 // << xml << "\"" << endl; 00204 00205 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) { 00206 cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error << " at line " << errorLine << ", column " << errorColumn << endl; 00207 cerr << "Input follows:" << endl; 00208 cerr << xml << endl; 00209 cerr << "Input ends." << endl; 00210 return; 00211 } 00212 00213 QDomElement pluginElt = doc.firstChildElement("plugin"); 00214 QDomNamedNodeMap attrNodes = pluginElt.attributes(); 00215 QXmlAttributes attrs; 00216 00217 for (int i = 0; i < attrNodes.length(); ++i) { 00218 QDomAttr attr = attrNodes.item(i).toAttr(); 00219 if (attr.isNull()) continue; 00220 // SVDEBUG << "PluginXml::setParametersFromXml: Adding attribute \"" << attr.name()// << "\" with value \"" << attr.value() << "\"" << endl; 00221 attrs.append(attr.name(), "", "", attr.value()); 00222 } 00223 00224 setParameters(attrs); 00225 } 00226 00227 QString 00228 PluginXml::stripInvalidParameterNameCharacters(QString s) const 00229 { 00230 s.replace(QRegExp("[^a-zA-Z0-9_]*"), ""); 00231 return s; 00232 } 00233