annotate transform/TransformFactory.cpp @ 57:7439f1696314

* Add editing for auralisation plugin parameters and programs * Rename and reorganise the sample plugin sample set
author Chris Cannam
date Thu, 23 Mar 2006 15:49:41 +0000
parents 2157fa46c1e7
children 3086ff194ea0
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@52 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "TransformFactory.h"
Chris@0 17
Chris@0 18 #include "FeatureExtractionPluginTransform.h"
Chris@0 19
Chris@0 20 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@0 21
Chris@56 22 #include "widgets/PluginParameterDialog.h"
Chris@56 23
Chris@0 24 #include <iostream>
Chris@0 25
Chris@0 26 TransformFactory *
Chris@0 27 TransformFactory::m_instance = new TransformFactory;
Chris@0 28
Chris@0 29 TransformFactory *
Chris@0 30 TransformFactory::instance()
Chris@0 31 {
Chris@0 32 return m_instance;
Chris@0 33 }
Chris@0 34
Chris@0 35 TransformFactory::~TransformFactory()
Chris@0 36 {
Chris@0 37 }
Chris@0 38
Chris@0 39 TransformFactory::TransformList
Chris@0 40 TransformFactory::getAllTransforms()
Chris@0 41 {
Chris@16 42 if (m_transforms.empty()) populateTransforms();
Chris@16 43
Chris@0 44 TransformList list;
Chris@56 45 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@16 46 i != m_transforms.end(); ++i) {
Chris@56 47 list.push_back(i->second);
Chris@16 48 }
Chris@0 49
Chris@16 50 return list;
Chris@16 51 }
Chris@16 52
Chris@16 53 void
Chris@16 54 TransformFactory::populateTransforms()
Chris@16 55 {
Chris@0 56 std::vector<QString> fexplugs =
Chris@0 57 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@0 58
Chris@47 59 std::map<QString, QString> makers;
Chris@47 60
Chris@0 61 for (size_t i = 0; i < fexplugs.size(); ++i) {
Chris@0 62
Chris@0 63 QString pluginId = fexplugs[i];
Chris@0 64
Chris@0 65 FeatureExtractionPluginFactory *factory =
Chris@0 66 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@0 67
Chris@20 68 if (!factory) {
Chris@20 69 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@20 70 continue;
Chris@20 71 }
Chris@0 72
Chris@20 73 FeatureExtractionPlugin *plugin =
Chris@20 74 factory->instantiatePlugin(pluginId, 48000);
Chris@0 75
Chris@20 76 if (!plugin) {
Chris@20 77 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@20 78 continue;
Chris@20 79 }
Chris@20 80
Chris@20 81 QString pluginDescription = plugin->getDescription().c_str();
Chris@20 82 FeatureExtractionPlugin::OutputList outputs =
Chris@20 83 plugin->getOutputDescriptors();
Chris@0 84
Chris@20 85 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@0 86
Chris@20 87 QString transformName = QString("%1:%2")
Chris@20 88 .arg(pluginId).arg(outputs[j].name.c_str());
Chris@20 89
Chris@20 90 QString userDescription;
Chris@20 91
Chris@20 92 if (outputs.size() == 1) {
Chris@20 93 userDescription = pluginDescription;
Chris@20 94 } else {
Chris@20 95 userDescription = QString("%1: %2")
Chris@20 96 .arg(pluginDescription)
Chris@20 97 .arg(outputs[j].description.c_str());
Chris@0 98 }
Chris@20 99
Chris@56 100 bool configurable = (!plugin->getPrograms().empty() ||
Chris@56 101 !plugin->getParameterDescriptors().empty());
Chris@56 102
Chris@56 103 m_transforms[transformName] =
Chris@56 104 TransformDesc(transformName,
Chris@56 105 userDescription,
Chris@56 106 configurable);
Chris@47 107
Chris@47 108 makers[transformName] = plugin->getMaker().c_str();
Chris@0 109 }
Chris@0 110 }
Chris@47 111
Chris@47 112 // disambiguate plugins with similar descriptions
Chris@47 113
Chris@47 114 std::map<QString, int> descriptions;
Chris@47 115
Chris@56 116 for (TransformDescriptionMap::iterator i = m_transforms.begin();
Chris@56 117 i != m_transforms.end(); ++i) {
Chris@47 118
Chris@56 119 TransformDesc desc = i->second;
Chris@47 120
Chris@56 121 ++descriptions[desc.description];
Chris@56 122 ++descriptions[QString("%1 [%2]").arg(desc.description).arg(makers[desc.name])];
Chris@47 123 }
Chris@47 124
Chris@47 125 std::map<QString, int> counts;
Chris@56 126 TransformDescriptionMap newMap;
Chris@47 127
Chris@56 128 for (TransformDescriptionMap::iterator i = m_transforms.begin();
Chris@56 129 i != m_transforms.end(); ++i) {
Chris@47 130
Chris@56 131 TransformDesc desc = i->second;
Chris@56 132 QString name = desc.name, description = desc.description;
Chris@47 133
Chris@47 134 if (descriptions[description] > 1) {
Chris@47 135 description = QString("%1 [%2]").arg(description).arg(makers[name]);
Chris@47 136 if (descriptions[description] > 1) {
Chris@47 137 description = QString("%1 <%2>")
Chris@47 138 .arg(description).arg(++counts[description]);
Chris@47 139 }
Chris@47 140 }
Chris@47 141
Chris@56 142 desc.description = description;
Chris@56 143 newMap[name] = desc;
Chris@47 144 }
Chris@47 145
Chris@47 146 m_transforms = newMap;
Chris@16 147 }
Chris@16 148
Chris@16 149 QString
Chris@16 150 TransformFactory::getTransformDescription(TransformName name)
Chris@16 151 {
Chris@16 152 if (m_transforms.find(name) != m_transforms.end()) {
Chris@56 153 return m_transforms[name].description;
Chris@16 154 } else return "";
Chris@0 155 }
Chris@0 156
Chris@18 157 QString
Chris@18 158 TransformFactory::getTransformFriendlyName(TransformName name)
Chris@18 159 {
Chris@18 160 QString description = getTransformDescription(name);
Chris@18 161
Chris@18 162 int i = description.indexOf(':');
Chris@18 163 if (i >= 0) {
Chris@18 164 return description.remove(0, i + 2);
Chris@18 165 } else {
Chris@18 166 return description;
Chris@18 167 }
Chris@18 168 }
Chris@18 169
Chris@56 170 bool
Chris@57 171 TransformFactory::isTransformConfigurable(TransformName name)
Chris@57 172 {
Chris@57 173 if (m_transforms.find(name) != m_transforms.end()) {
Chris@57 174 return m_transforms[name].configurable;
Chris@57 175 } else return false;
Chris@57 176 }
Chris@57 177
Chris@57 178 bool
Chris@56 179 TransformFactory::getConfigurationForTransform(TransformName name,
Chris@56 180 Model *inputModel,
Chris@56 181 QString &configurationXml)
Chris@0 182 {
Chris@56 183 QString id = name.section(':', 0, 2);
Chris@56 184 QString output = name.section(':', 3);
Chris@56 185
Chris@56 186 bool ok = false;
Chris@56 187 configurationXml = m_lastConfigurations[name];
Chris@56 188
Chris@56 189 std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
Chris@56 190
Chris@56 191 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@56 192 FeatureExtractionPlugin *plugin =
Chris@56 193 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@56 194 (id, inputModel->getSampleRate());
Chris@56 195 if (plugin) {
Chris@56 196 if (configurationXml != "") {
Chris@56 197 plugin->setParametersFromXml(configurationXml);
Chris@56 198 }
Chris@56 199 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
Chris@56 200 if (dialog->exec() == QDialog::Accepted) {
Chris@56 201 ok = true;
Chris@56 202 }
Chris@56 203 configurationXml = plugin->toXmlString();
Chris@57 204 delete dialog;
Chris@56 205 delete plugin;
Chris@56 206 }
Chris@56 207 }
Chris@56 208
Chris@56 209 if (ok) m_lastConfigurations[name] = configurationXml;
Chris@56 210
Chris@56 211 return ok;
Chris@0 212 }
Chris@0 213
Chris@0 214 Transform *
Chris@0 215 TransformFactory::createTransform(TransformName name, Model *inputModel,
Chris@56 216 QString configurationXml, bool start)
Chris@0 217 {
Chris@0 218 Transform *transform = 0;
Chris@0 219
Chris@56 220 // The only transform type we support at the moment is the
Chris@56 221 // FeatureExtractionPluginTransform. In future we may wish to
Chris@56 222 // support e.g. RealTimePluginTransform for audio->audio or
Chris@56 223 // audio->midi transforms using standard effects plugins.
Chris@56 224
Chris@56 225 QString id = name.section(':', 0, 2);
Chris@56 226 QString output = name.section(':', 3);
Chris@56 227
Chris@56 228 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@56 229 transform = new FeatureExtractionPluginTransform(inputModel,
Chris@56 230 id,
Chris@56 231 configurationXml,
Chris@56 232 output);
Chris@0 233 } else {
Chris@56 234 std::cerr << "TransformFactory::createTransform: Unknown transform "
Chris@56 235 << name.toStdString() << std::endl;
Chris@0 236 }
Chris@0 237
Chris@0 238 if (start && transform) transform->start();
Chris@16 239 transform->setObjectName(name);
Chris@0 240 return transform;
Chris@0 241 }
Chris@0 242
Chris@0 243 Model *
Chris@56 244 TransformFactory::transform(TransformName name, Model *inputModel,
Chris@56 245 QString configurationXml)
Chris@0 246 {
Chris@56 247 Transform *t = createTransform(name, inputModel, configurationXml, false);
Chris@0 248
Chris@0 249 if (!t) return 0;
Chris@0 250
Chris@0 251 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
Chris@0 252
Chris@0 253 t->start();
Chris@0 254 return t->detachOutputModel();
Chris@0 255 }
Chris@0 256
Chris@0 257 void
Chris@0 258 TransformFactory::transformFinished()
Chris@0 259 {
Chris@0 260 QObject *s = sender();
Chris@0 261 Transform *transform = dynamic_cast<Transform *>(s);
Chris@0 262
Chris@0 263 if (!transform) {
Chris@0 264 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
Chris@0 265 return;
Chris@0 266 }
Chris@0 267
Chris@0 268 transform->wait(); // unnecessary but reassuring
Chris@0 269 delete transform;
Chris@0 270 }
Chris@0 271