comparison transform/TransformFactory.cpp @ 60:3086ff194ea0

* More structural work on feature extraction plugin C <-> C++ adapter * Allow use of LADSPA/DSSI plugins with control outputs as feature extraction plugins (DSSI with MIDI output still to come) * Reorder labels on spectrogram status box * Minor tweaks in doc etc.
author Chris Cannam
date Mon, 27 Mar 2006 15:03:02 +0000
parents 7439f1696314
children ba405e5e69d3
comparison
equal deleted inserted replaced
59:9705a1978ecc 60:3086ff194ea0
14 */ 14 */
15 15
16 #include "TransformFactory.h" 16 #include "TransformFactory.h"
17 17
18 #include "FeatureExtractionPluginTransform.h" 18 #include "FeatureExtractionPluginTransform.h"
19 #include "RealTimePluginTransform.h"
19 20
20 #include "plugin/FeatureExtractionPluginFactory.h" 21 #include "plugin/FeatureExtractionPluginFactory.h"
22 #include "plugin/RealTimePluginFactory.h"
21 23
22 #include "widgets/PluginParameterDialog.h" 24 #include "widgets/PluginParameterDialog.h"
23 25
24 #include <iostream> 26 #include <iostream>
25 27
51 } 53 }
52 54
53 void 55 void
54 TransformFactory::populateTransforms() 56 TransformFactory::populateTransforms()
55 { 57 {
56 std::vector<QString> fexplugs = 58 TransformDescriptionMap transforms;
59
60 populateFeatureExtractionPlugins(transforms);
61 populateRealTimePlugins(transforms);
62
63 // disambiguate plugins with similar descriptions
64
65 std::map<QString, int> descriptions;
66
67 for (TransformDescriptionMap::iterator i = transforms.begin();
68 i != transforms.end(); ++i) {
69
70 TransformDesc desc = i->second;
71
72 ++descriptions[desc.description];
73 ++descriptions[QString("%1 [%2]").arg(desc.description).arg(desc.maker)];
74 }
75
76 std::map<QString, int> counts;
77 m_transforms.clear();
78
79 for (TransformDescriptionMap::iterator i = transforms.begin();
80 i != transforms.end(); ++i) {
81
82 TransformDesc desc = i->second;
83 QString name = desc.name;
84 QString description = desc.description;
85 QString maker = desc.maker;
86
87 if (descriptions[description] > 1) {
88 description = QString("%1 [%2]").arg(description).arg(maker);
89 if (descriptions[description] > 1) {
90 description = QString("%1 <%2>")
91 .arg(description).arg(++counts[description]);
92 }
93 }
94
95 desc.description = description;
96 m_transforms[name] = desc;
97 }
98 }
99
100 void
101 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
102 {
103 std::vector<QString> plugs =
57 FeatureExtractionPluginFactory::getAllPluginIdentifiers(); 104 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
58 105
59 std::map<QString, QString> makers; 106 for (size_t i = 0; i < plugs.size(); ++i) {
60 107
61 for (size_t i = 0; i < fexplugs.size(); ++i) { 108 QString pluginId = plugs[i];
62
63 QString pluginId = fexplugs[i];
64 109
65 FeatureExtractionPluginFactory *factory = 110 FeatureExtractionPluginFactory *factory =
66 FeatureExtractionPluginFactory::instanceFor(pluginId); 111 FeatureExtractionPluginFactory::instanceFor(pluginId);
67 112
68 if (!factory) { 113 if (!factory) {
86 131
87 QString transformName = QString("%1:%2") 132 QString transformName = QString("%1:%2")
88 .arg(pluginId).arg(outputs[j].name.c_str()); 133 .arg(pluginId).arg(outputs[j].name.c_str());
89 134
90 QString userDescription; 135 QString userDescription;
136 QString friendlyName;
91 137
92 if (outputs.size() == 1) { 138 if (outputs.size() == 1) {
93 userDescription = pluginDescription; 139 userDescription = pluginDescription;
140 friendlyName = pluginDescription;
94 } else { 141 } else {
95 userDescription = QString("%1: %2") 142 userDescription = QString("%1: %2")
96 .arg(pluginDescription) 143 .arg(pluginDescription)
97 .arg(outputs[j].description.c_str()); 144 .arg(outputs[j].description.c_str());
145 friendlyName = outputs[j].description.c_str();
98 } 146 }
99 147
100 bool configurable = (!plugin->getPrograms().empty() || 148 bool configurable = (!plugin->getPrograms().empty() ||
101 !plugin->getParameterDescriptors().empty()); 149 !plugin->getParameterDescriptors().empty());
102 150
103 m_transforms[transformName] = 151 transforms[transformName] =
104 TransformDesc(transformName, 152 TransformDesc(transformName,
105 userDescription, 153 userDescription,
154 friendlyName,
155 plugin->getMaker().c_str(),
106 configurable); 156 configurable);
107 157 }
108 makers[transformName] = plugin->getMaker().c_str(); 158 }
109 } 159 }
110 } 160
111 161 void
112 // disambiguate plugins with similar descriptions 162 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
113 163 {
114 std::map<QString, int> descriptions; 164 std::vector<QString> plugs =
115 165 RealTimePluginFactory::getAllPluginIdentifiers();
116 for (TransformDescriptionMap::iterator i = m_transforms.begin(); 166
117 i != m_transforms.end(); ++i) { 167 for (size_t i = 0; i < plugs.size(); ++i) {
118 168
119 TransformDesc desc = i->second; 169 QString pluginId = plugs[i];
120 170
121 ++descriptions[desc.description]; 171 RealTimePluginFactory *factory =
122 ++descriptions[QString("%1 [%2]").arg(desc.description).arg(makers[desc.name])]; 172 RealTimePluginFactory::instanceFor(pluginId);
123 } 173
124 174 if (!factory) {
125 std::map<QString, int> counts; 175 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
126 TransformDescriptionMap newMap; 176 continue;
127 177 }
128 for (TransformDescriptionMap::iterator i = m_transforms.begin(); 178
129 i != m_transforms.end(); ++i) { 179 const RealTimePluginDescriptor *descriptor =
130 180 factory->getPluginDescriptor(pluginId);
131 TransformDesc desc = i->second; 181
132 QString name = desc.name, description = desc.description; 182 if (!descriptor) {
133 183 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
134 if (descriptions[description] > 1) { 184 continue;
135 description = QString("%1 [%2]").arg(description).arg(makers[name]); 185 }
136 if (descriptions[description] > 1) { 186
137 description = QString("%1 <%2>") 187 if (descriptor->controlOutputPortCount == 0 ||
138 .arg(description).arg(++counts[description]); 188 descriptor->audioInputPortCount == 0) continue;
139 } 189
140 } 190 std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " output ports" << std::endl;
141 191
142 desc.description = description; 192 QString pluginDescription = descriptor->name.c_str();
143 newMap[name] = desc; 193
144 } 194 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
145 195
146 m_transforms = newMap; 196 QString transformName = QString("%1:%2").arg(pluginId).arg(j);
197 QString userDescription;
198
199 if (j < descriptor->controlOutputPortNames.size() &&
200 descriptor->controlOutputPortNames[j] != "") {
201 userDescription = tr("%1: %2")
202 .arg(pluginDescription)
203 .arg(descriptor->controlOutputPortNames[j].c_str());
204 } else if (descriptor->controlOutputPortCount > 1) {
205 userDescription = tr("%1: Output %2")
206 .arg(pluginDescription)
207 .arg(j + 1);
208 } else {
209 userDescription = pluginDescription;
210 }
211
212 bool configurable = (descriptor->parameterCount > 0);
213
214 transforms[transformName] =
215 TransformDesc(transformName,
216 userDescription,
217 userDescription,
218 descriptor->maker.c_str(),
219 configurable);
220 }
221 }
147 } 222 }
148 223
149 QString 224 QString
150 TransformFactory::getTransformDescription(TransformName name) 225 TransformFactory::getTransformDescription(TransformName name)
151 { 226 {
155 } 230 }
156 231
157 QString 232 QString
158 TransformFactory::getTransformFriendlyName(TransformName name) 233 TransformFactory::getTransformFriendlyName(TransformName name)
159 { 234 {
160 QString description = getTransformDescription(name); 235 if (m_transforms.find(name) != m_transforms.end()) {
161 236 return m_transforms[name].friendlyName;
162 int i = description.indexOf(':'); 237 } else return "";
163 if (i >= 0) {
164 return description.remove(0, i + 2);
165 } else {
166 return description;
167 }
168 } 238 }
169 239
170 bool 240 bool
171 TransformFactory::isTransformConfigurable(TransformName name) 241 TransformFactory::isTransformConfigurable(TransformName name)
172 { 242 {
186 bool ok = false; 256 bool ok = false;
187 configurationXml = m_lastConfigurations[name]; 257 configurationXml = m_lastConfigurations[name];
188 258
189 std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl; 259 std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
190 260
261 PluginInstance *plugin = 0;
262
191 if (FeatureExtractionPluginFactory::instanceFor(id)) { 263 if (FeatureExtractionPluginFactory::instanceFor(id)) {
192 FeatureExtractionPlugin *plugin = 264
193 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin 265 plugin = FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
194 (id, inputModel->getSampleRate()); 266 (id, inputModel->getSampleRate());
195 if (plugin) { 267
196 if (configurationXml != "") { 268 } else if (RealTimePluginFactory::instanceFor(id)) {
197 plugin->setParametersFromXml(configurationXml); 269
198 } 270 plugin = RealTimePluginFactory::instanceFor(id)->instantiatePlugin
199 PluginParameterDialog *dialog = new PluginParameterDialog(plugin); 271 (id, 0, 0, inputModel->getSampleRate(), 1024, 1);
200 if (dialog->exec() == QDialog::Accepted) { 272 }
201 ok = true; 273
202 } 274 if (plugin) {
203 configurationXml = plugin->toXmlString(); 275 if (configurationXml != "") {
204 delete dialog; 276 plugin->setParametersFromXml(configurationXml);
205 delete plugin;
206 } 277 }
278 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
279 if (dialog->exec() == QDialog::Accepted) {
280 ok = true;
281 }
282 configurationXml = plugin->toXmlString();
283 delete dialog;
284 delete plugin;
207 } 285 }
208 286
209 if (ok) m_lastConfigurations[name] = configurationXml; 287 if (ok) m_lastConfigurations[name] = configurationXml;
210 288
211 return ok; 289 return ok;
214 Transform * 292 Transform *
215 TransformFactory::createTransform(TransformName name, Model *inputModel, 293 TransformFactory::createTransform(TransformName name, Model *inputModel,
216 QString configurationXml, bool start) 294 QString configurationXml, bool start)
217 { 295 {
218 Transform *transform = 0; 296 Transform *transform = 0;
219
220 // The only transform type we support at the moment is the
221 // FeatureExtractionPluginTransform. In future we may wish to
222 // support e.g. RealTimePluginTransform for audio->audio or
223 // audio->midi transforms using standard effects plugins.
224 297
225 QString id = name.section(':', 0, 2); 298 QString id = name.section(':', 0, 2);
226 QString output = name.section(':', 3); 299 QString output = name.section(':', 3);
227 300
228 if (FeatureExtractionPluginFactory::instanceFor(id)) { 301 if (FeatureExtractionPluginFactory::instanceFor(id)) {
229 transform = new FeatureExtractionPluginTransform(inputModel, 302 transform = new FeatureExtractionPluginTransform(inputModel,
230 id, 303 id,
231 configurationXml, 304 configurationXml,
232 output); 305 output);
306 } else if (RealTimePluginFactory::instanceFor(id)) {
307 transform = new RealTimePluginTransform(inputModel,
308 id,
309 configurationXml,
310 output.toInt());
233 } else { 311 } else {
234 std::cerr << "TransformFactory::createTransform: Unknown transform " 312 std::cerr << "TransformFactory::createTransform: Unknown transform "
235 << name.toStdString() << std::endl; 313 << name.toStdString() << std::endl;
236 } 314 }
237 315