Mercurial > hg > svcore
comparison transform/TransformFactory.cpp @ 388:370aa9714ef5
* Move plugin/transform to plain transform. This way transform can depend on
model and GUI classes, but plugin doesn't have to.
author | Chris Cannam |
---|---|
date | Wed, 12 Mar 2008 18:02:17 +0000 |
parents | plugin/transform/TransformFactory.cpp@4bb19132da23 |
children | beb2948baa77 |
comparison
equal
deleted
inserted
replaced
387:7aa1de571880 | 388:370aa9714ef5 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam and QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "TransformFactory.h" | |
17 | |
18 #include "plugin/FeatureExtractionPluginFactory.h" | |
19 #include "plugin/RealTimePluginFactory.h" | |
20 #include "plugin/RealTimePluginInstance.h" | |
21 #include "plugin/PluginXml.h" | |
22 | |
23 #include "vamp-sdk/Plugin.h" | |
24 #include "vamp-sdk/PluginHostAdapter.h" | |
25 #include "vamp-sdk/hostext/PluginWrapper.h" | |
26 | |
27 #include <iostream> | |
28 #include <set> | |
29 | |
30 #include <QRegExp> | |
31 #include <QTextStream> | |
32 | |
33 TransformFactory * | |
34 TransformFactory::m_instance = new TransformFactory; | |
35 | |
36 TransformFactory * | |
37 TransformFactory::getInstance() | |
38 { | |
39 return m_instance; | |
40 } | |
41 | |
42 TransformFactory::~TransformFactory() | |
43 { | |
44 } | |
45 | |
46 TransformList | |
47 TransformFactory::getAllTransformDescriptions() | |
48 { | |
49 if (m_transforms.empty()) populateTransforms(); | |
50 | |
51 std::set<TransformDescription> dset; | |
52 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | |
53 i != m_transforms.end(); ++i) { | |
54 // std::cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << std::endl; | |
55 dset.insert(i->second); | |
56 } | |
57 | |
58 TransformList list; | |
59 for (std::set<TransformDescription>::const_iterator i = dset.begin(); | |
60 i != dset.end(); ++i) { | |
61 // std::cerr << "inserting transform into list: id = " << i->identifier.toStdString() << std::endl; | |
62 list.push_back(*i); | |
63 } | |
64 | |
65 return list; | |
66 } | |
67 | |
68 TransformDescription | |
69 TransformFactory::getTransformDescription(TransformId id) | |
70 { | |
71 if (m_transforms.empty()) populateTransforms(); | |
72 | |
73 if (m_transforms.find(id) == m_transforms.end()) { | |
74 return TransformDescription(); | |
75 } | |
76 | |
77 return m_transforms[id]; | |
78 } | |
79 | |
80 std::vector<QString> | |
81 TransformFactory::getAllTransformTypes() | |
82 { | |
83 if (m_transforms.empty()) populateTransforms(); | |
84 | |
85 std::set<QString> types; | |
86 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | |
87 i != m_transforms.end(); ++i) { | |
88 types.insert(i->second.type); | |
89 } | |
90 | |
91 std::vector<QString> rv; | |
92 for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) { | |
93 rv.push_back(*i); | |
94 } | |
95 | |
96 return rv; | |
97 } | |
98 | |
99 std::vector<QString> | |
100 TransformFactory::getTransformCategories(QString transformType) | |
101 { | |
102 if (m_transforms.empty()) populateTransforms(); | |
103 | |
104 std::set<QString> categories; | |
105 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | |
106 i != m_transforms.end(); ++i) { | |
107 if (i->second.type == transformType) { | |
108 categories.insert(i->second.category); | |
109 } | |
110 } | |
111 | |
112 bool haveEmpty = false; | |
113 | |
114 std::vector<QString> rv; | |
115 for (std::set<QString>::iterator i = categories.begin(); | |
116 i != categories.end(); ++i) { | |
117 if (*i != "") rv.push_back(*i); | |
118 else haveEmpty = true; | |
119 } | |
120 | |
121 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last | |
122 | |
123 return rv; | |
124 } | |
125 | |
126 std::vector<QString> | |
127 TransformFactory::getTransformMakers(QString transformType) | |
128 { | |
129 if (m_transforms.empty()) populateTransforms(); | |
130 | |
131 std::set<QString> makers; | |
132 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | |
133 i != m_transforms.end(); ++i) { | |
134 if (i->second.type == transformType) { | |
135 makers.insert(i->second.maker); | |
136 } | |
137 } | |
138 | |
139 bool haveEmpty = false; | |
140 | |
141 std::vector<QString> rv; | |
142 for (std::set<QString>::iterator i = makers.begin(); | |
143 i != makers.end(); ++i) { | |
144 if (*i != "") rv.push_back(*i); | |
145 else haveEmpty = true; | |
146 } | |
147 | |
148 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last | |
149 | |
150 return rv; | |
151 } | |
152 | |
153 void | |
154 TransformFactory::populateTransforms() | |
155 { | |
156 TransformDescriptionMap transforms; | |
157 | |
158 populateFeatureExtractionPlugins(transforms); | |
159 populateRealTimePlugins(transforms); | |
160 | |
161 // disambiguate plugins with similar names | |
162 | |
163 std::map<QString, int> names; | |
164 std::map<QString, QString> pluginSources; | |
165 std::map<QString, QString> pluginMakers; | |
166 | |
167 for (TransformDescriptionMap::iterator i = transforms.begin(); | |
168 i != transforms.end(); ++i) { | |
169 | |
170 TransformDescription desc = i->second; | |
171 | |
172 QString td = desc.name; | |
173 QString tn = td.section(": ", 0, 0); | |
174 QString pn = desc.identifier.section(":", 1, 1); | |
175 | |
176 if (pluginSources.find(tn) != pluginSources.end()) { | |
177 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) { | |
178 ++names[tn]; | |
179 } | |
180 } else { | |
181 ++names[tn]; | |
182 pluginSources[tn] = pn; | |
183 pluginMakers[tn] = desc.maker; | |
184 } | |
185 } | |
186 | |
187 std::map<QString, int> counts; | |
188 m_transforms.clear(); | |
189 | |
190 for (TransformDescriptionMap::iterator i = transforms.begin(); | |
191 i != transforms.end(); ++i) { | |
192 | |
193 TransformDescription desc = i->second; | |
194 QString identifier = desc.identifier; | |
195 QString maker = desc.maker; | |
196 | |
197 QString td = desc.name; | |
198 QString tn = td.section(": ", 0, 0); | |
199 QString to = td.section(": ", 1); | |
200 | |
201 if (names[tn] > 1) { | |
202 maker.replace(QRegExp(tr(" [\\(<].*$")), ""); | |
203 tn = QString("%1 [%2]").arg(tn).arg(maker); | |
204 } | |
205 | |
206 if (to != "") { | |
207 desc.name = QString("%1: %2").arg(tn).arg(to); | |
208 } else { | |
209 desc.name = tn; | |
210 } | |
211 | |
212 m_transforms[identifier] = desc; | |
213 } | |
214 } | |
215 | |
216 void | |
217 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms) | |
218 { | |
219 std::vector<QString> plugs = | |
220 FeatureExtractionPluginFactory::getAllPluginIdentifiers(); | |
221 | |
222 for (size_t i = 0; i < plugs.size(); ++i) { | |
223 | |
224 QString pluginId = plugs[i]; | |
225 | |
226 FeatureExtractionPluginFactory *factory = | |
227 FeatureExtractionPluginFactory::instanceFor(pluginId); | |
228 | |
229 if (!factory) { | |
230 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl; | |
231 continue; | |
232 } | |
233 | |
234 Vamp::Plugin *plugin = | |
235 factory->instantiatePlugin(pluginId, 44100); | |
236 | |
237 if (!plugin) { | |
238 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl; | |
239 continue; | |
240 } | |
241 | |
242 QString pluginName = plugin->getName().c_str(); | |
243 QString category = factory->getPluginCategory(pluginId); | |
244 | |
245 Vamp::Plugin::OutputList outputs = | |
246 plugin->getOutputDescriptors(); | |
247 | |
248 for (size_t j = 0; j < outputs.size(); ++j) { | |
249 | |
250 QString transformId = QString("%1:%2") | |
251 .arg(pluginId).arg(outputs[j].identifier.c_str()); | |
252 | |
253 QString userName; | |
254 QString friendlyName; | |
255 QString units = outputs[j].unit.c_str(); | |
256 QString description = plugin->getDescription().c_str(); | |
257 QString maker = plugin->getMaker().c_str(); | |
258 if (maker == "") maker = tr("<unknown maker>"); | |
259 | |
260 if (description == "") { | |
261 if (outputs.size() == 1) { | |
262 description = tr("Extract features using \"%1\" plugin (from %2)") | |
263 .arg(pluginName).arg(maker); | |
264 } else { | |
265 description = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)") | |
266 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker); | |
267 } | |
268 } else { | |
269 if (outputs.size() == 1) { | |
270 description = tr("%1 using \"%2\" plugin (from %3)") | |
271 .arg(description).arg(pluginName).arg(maker); | |
272 } else { | |
273 description = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)") | |
274 .arg(description).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker); | |
275 } | |
276 } | |
277 | |
278 if (outputs.size() == 1) { | |
279 userName = pluginName; | |
280 friendlyName = pluginName; | |
281 } else { | |
282 userName = QString("%1: %2") | |
283 .arg(pluginName) | |
284 .arg(outputs[j].name.c_str()); | |
285 friendlyName = outputs[j].name.c_str(); | |
286 } | |
287 | |
288 bool configurable = (!plugin->getPrograms().empty() || | |
289 !plugin->getParameterDescriptors().empty()); | |
290 | |
291 // std::cerr << "Feature extraction plugin transform: " << transformId.toStdString() << " friendly name: " << friendlyName.toStdString() << std::endl; | |
292 | |
293 transforms[transformId] = | |
294 TransformDescription(tr("Analysis"), | |
295 category, | |
296 transformId, | |
297 userName, | |
298 friendlyName, | |
299 description, | |
300 maker, | |
301 units, | |
302 configurable); | |
303 } | |
304 | |
305 delete plugin; | |
306 } | |
307 } | |
308 | |
309 void | |
310 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms) | |
311 { | |
312 std::vector<QString> plugs = | |
313 RealTimePluginFactory::getAllPluginIdentifiers(); | |
314 | |
315 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$"); | |
316 | |
317 for (size_t i = 0; i < plugs.size(); ++i) { | |
318 | |
319 QString pluginId = plugs[i]; | |
320 | |
321 RealTimePluginFactory *factory = | |
322 RealTimePluginFactory::instanceFor(pluginId); | |
323 | |
324 if (!factory) { | |
325 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl; | |
326 continue; | |
327 } | |
328 | |
329 const RealTimePluginDescriptor *descriptor = | |
330 factory->getPluginDescriptor(pluginId); | |
331 | |
332 if (!descriptor) { | |
333 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl; | |
334 continue; | |
335 } | |
336 | |
337 //!!! if (descriptor->controlOutputPortCount == 0 || | |
338 // descriptor->audioInputPortCount == 0) continue; | |
339 | |
340 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl; | |
341 | |
342 QString pluginName = descriptor->name.c_str(); | |
343 QString category = factory->getPluginCategory(pluginId); | |
344 bool configurable = (descriptor->parameterCount > 0); | |
345 QString maker = descriptor->maker.c_str(); | |
346 if (maker == "") maker = tr("<unknown maker>"); | |
347 | |
348 if (descriptor->audioInputPortCount > 0) { | |
349 | |
350 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) { | |
351 | |
352 QString transformId = QString("%1:%2").arg(pluginId).arg(j); | |
353 QString userName; | |
354 QString units; | |
355 QString portName; | |
356 | |
357 if (j < descriptor->controlOutputPortNames.size() && | |
358 descriptor->controlOutputPortNames[j] != "") { | |
359 | |
360 portName = descriptor->controlOutputPortNames[j].c_str(); | |
361 | |
362 userName = tr("%1: %2") | |
363 .arg(pluginName) | |
364 .arg(portName); | |
365 | |
366 if (unitRE.indexIn(portName) >= 0) { | |
367 units = unitRE.cap(1); | |
368 } | |
369 | |
370 } else if (descriptor->controlOutputPortCount > 1) { | |
371 | |
372 userName = tr("%1: Output %2") | |
373 .arg(pluginName) | |
374 .arg(j + 1); | |
375 | |
376 } else { | |
377 | |
378 userName = pluginName; | |
379 } | |
380 | |
381 QString description; | |
382 | |
383 if (portName != "") { | |
384 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)") | |
385 .arg(portName) | |
386 .arg(pluginName) | |
387 .arg(maker); | |
388 } else { | |
389 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)") | |
390 .arg(j + 1) | |
391 .arg(pluginName) | |
392 .arg(maker); | |
393 } | |
394 | |
395 transforms[transformId] = | |
396 TransformDescription(tr("Effects Data"), | |
397 category, | |
398 transformId, | |
399 userName, | |
400 userName, | |
401 description, | |
402 maker, | |
403 units, | |
404 configurable); | |
405 } | |
406 } | |
407 | |
408 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) { | |
409 | |
410 if (descriptor->audioOutputPortCount > 0) { | |
411 | |
412 QString transformId = QString("%1:A").arg(pluginId); | |
413 QString type = tr("Effects"); | |
414 | |
415 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)") | |
416 .arg(pluginName) | |
417 .arg(maker); | |
418 | |
419 if (descriptor->audioInputPortCount == 0) { | |
420 type = tr("Generators"); | |
421 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)") | |
422 .arg(pluginName) | |
423 .arg(maker); | |
424 } | |
425 | |
426 transforms[transformId] = | |
427 TransformDescription(type, | |
428 category, | |
429 transformId, | |
430 pluginName, | |
431 pluginName, | |
432 description, | |
433 maker, | |
434 "", | |
435 configurable); | |
436 } | |
437 } | |
438 } | |
439 } | |
440 | |
441 | |
442 Transform | |
443 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate) | |
444 { | |
445 Transform t; | |
446 t.setIdentifier(id); | |
447 if (rate != 0) t.setSampleRate(rate); | |
448 | |
449 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate); | |
450 | |
451 if (plugin) { | |
452 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion())); | |
453 setParametersFromPlugin(t, plugin); | |
454 makeContextConsistentWithPlugin(t, plugin); | |
455 delete plugin; | |
456 } | |
457 | |
458 return t; | |
459 } | |
460 | |
461 Vamp::PluginBase * | |
462 TransformFactory::instantiatePluginFor(const Transform &transform) | |
463 { | |
464 Vamp::PluginBase *plugin = instantiateDefaultPluginFor | |
465 (transform.getIdentifier(), transform.getSampleRate()); | |
466 if (plugin) { | |
467 setPluginParameters(transform, plugin); | |
468 } | |
469 return plugin; | |
470 } | |
471 | |
472 Vamp::PluginBase * | |
473 TransformFactory::instantiateDefaultPluginFor(TransformId identifier, size_t rate) | |
474 { | |
475 Transform t; | |
476 t.setIdentifier(identifier); | |
477 if (rate == 0) rate = 44100; | |
478 QString pluginId = t.getPluginIdentifier(); | |
479 | |
480 Vamp::PluginBase *plugin = 0; | |
481 | |
482 if (t.getType() == Transform::FeatureExtraction) { | |
483 | |
484 FeatureExtractionPluginFactory *factory = | |
485 FeatureExtractionPluginFactory::instanceFor(pluginId); | |
486 | |
487 plugin = factory->instantiatePlugin(pluginId, rate); | |
488 | |
489 } else { | |
490 | |
491 RealTimePluginFactory *factory = | |
492 RealTimePluginFactory::instanceFor(pluginId); | |
493 | |
494 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1); | |
495 } | |
496 | |
497 return plugin; | |
498 } | |
499 | |
500 Vamp::Plugin * | |
501 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin) | |
502 { | |
503 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin); | |
504 if (!vp) { | |
505 // std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl; | |
506 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why? | |
507 } | |
508 if (!vp) { | |
509 // std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl; | |
510 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why? | |
511 } | |
512 if (!vp) { | |
513 // std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl; | |
514 } | |
515 return vp; | |
516 } | |
517 | |
518 bool | |
519 TransformFactory::haveTransform(TransformId identifier) | |
520 { | |
521 if (m_transforms.empty()) populateTransforms(); | |
522 return (m_transforms.find(identifier) != m_transforms.end()); | |
523 } | |
524 | |
525 QString | |
526 TransformFactory::getTransformName(TransformId identifier) | |
527 { | |
528 if (m_transforms.find(identifier) != m_transforms.end()) { | |
529 return m_transforms[identifier].name; | |
530 } else return ""; | |
531 } | |
532 | |
533 QString | |
534 TransformFactory::getTransformFriendlyName(TransformId identifier) | |
535 { | |
536 if (m_transforms.find(identifier) != m_transforms.end()) { | |
537 return m_transforms[identifier].friendlyName; | |
538 } else return ""; | |
539 } | |
540 | |
541 QString | |
542 TransformFactory::getTransformUnits(TransformId identifier) | |
543 { | |
544 if (m_transforms.find(identifier) != m_transforms.end()) { | |
545 return m_transforms[identifier].units; | |
546 } else return ""; | |
547 } | |
548 | |
549 Vamp::Plugin::InputDomain | |
550 TransformFactory::getTransformInputDomain(TransformId identifier) | |
551 { | |
552 Transform transform; | |
553 transform.setIdentifier(identifier); | |
554 | |
555 if (transform.getType() != Transform::FeatureExtraction) { | |
556 return Vamp::Plugin::TimeDomain; | |
557 } | |
558 | |
559 Vamp::Plugin *plugin = | |
560 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0)); | |
561 | |
562 if (plugin) { | |
563 Vamp::Plugin::InputDomain d = plugin->getInputDomain(); | |
564 delete plugin; | |
565 return d; | |
566 } | |
567 | |
568 return Vamp::Plugin::TimeDomain; | |
569 } | |
570 | |
571 bool | |
572 TransformFactory::isTransformConfigurable(TransformId identifier) | |
573 { | |
574 if (m_transforms.find(identifier) != m_transforms.end()) { | |
575 return m_transforms[identifier].configurable; | |
576 } else return false; | |
577 } | |
578 | |
579 bool | |
580 TransformFactory::getTransformChannelRange(TransformId identifier, | |
581 int &min, int &max) | |
582 { | |
583 QString id = identifier.section(':', 0, 2); | |
584 | |
585 if (FeatureExtractionPluginFactory::instanceFor(id)) { | |
586 | |
587 Vamp::Plugin *plugin = | |
588 FeatureExtractionPluginFactory::instanceFor(id)-> | |
589 instantiatePlugin(id, 44100); | |
590 if (!plugin) return false; | |
591 | |
592 min = plugin->getMinChannelCount(); | |
593 max = plugin->getMaxChannelCount(); | |
594 delete plugin; | |
595 | |
596 return true; | |
597 | |
598 } else if (RealTimePluginFactory::instanceFor(id)) { | |
599 | |
600 // don't need to instantiate | |
601 | |
602 const RealTimePluginDescriptor *descriptor = | |
603 RealTimePluginFactory::instanceFor(id)-> | |
604 getPluginDescriptor(id); | |
605 if (!descriptor) return false; | |
606 | |
607 min = descriptor->audioInputPortCount; | |
608 max = descriptor->audioInputPortCount; | |
609 | |
610 return true; | |
611 } | |
612 | |
613 return false; | |
614 } | |
615 | |
616 void | |
617 TransformFactory::setParametersFromPlugin(Transform &transform, | |
618 Vamp::PluginBase *plugin) | |
619 { | |
620 Transform::ParameterMap pmap; | |
621 | |
622 //!!! record plugin & API version | |
623 | |
624 //!!! check that this is the right plugin! | |
625 | |
626 Vamp::PluginBase::ParameterList parameters = | |
627 plugin->getParameterDescriptors(); | |
628 | |
629 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin(); | |
630 i != parameters.end(); ++i) { | |
631 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier); | |
632 } | |
633 | |
634 transform.setParameters(pmap); | |
635 | |
636 if (plugin->getPrograms().empty()) { | |
637 transform.setProgram(""); | |
638 } else { | |
639 transform.setProgram(plugin->getCurrentProgram().c_str()); | |
640 } | |
641 | |
642 RealTimePluginInstance *rtpi = | |
643 dynamic_cast<RealTimePluginInstance *>(plugin); | |
644 | |
645 Transform::ConfigurationMap cmap; | |
646 | |
647 if (rtpi) { | |
648 | |
649 RealTimePluginInstance::ConfigurationPairMap configurePairs = | |
650 rtpi->getConfigurePairs(); | |
651 | |
652 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i | |
653 = configurePairs.begin(); i != configurePairs.end(); ++i) { | |
654 cmap[i->first.c_str()] = i->second.c_str(); | |
655 } | |
656 } | |
657 | |
658 transform.setConfiguration(cmap); | |
659 } | |
660 | |
661 void | |
662 TransformFactory::setPluginParameters(const Transform &transform, | |
663 Vamp::PluginBase *plugin) | |
664 { | |
665 //!!! check plugin & API version (see e.g. PluginXml::setParameters) | |
666 | |
667 //!!! check that this is the right plugin! | |
668 | |
669 RealTimePluginInstance *rtpi = | |
670 dynamic_cast<RealTimePluginInstance *>(plugin); | |
671 | |
672 if (rtpi) { | |
673 const Transform::ConfigurationMap &cmap = transform.getConfiguration(); | |
674 for (Transform::ConfigurationMap::const_iterator i = cmap.begin(); | |
675 i != cmap.end(); ++i) { | |
676 rtpi->configure(i->first.toStdString(), i->second.toStdString()); | |
677 } | |
678 } | |
679 | |
680 if (transform.getProgram() != "") { | |
681 plugin->selectProgram(transform.getProgram().toStdString()); | |
682 } | |
683 | |
684 const Transform::ParameterMap &pmap = transform.getParameters(); | |
685 | |
686 Vamp::PluginBase::ParameterList parameters = | |
687 plugin->getParameterDescriptors(); | |
688 | |
689 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin(); | |
690 i != parameters.end(); ++i) { | |
691 QString key = i->identifier.c_str(); | |
692 Transform::ParameterMap::const_iterator pmi = pmap.find(key); | |
693 if (pmi != pmap.end()) { | |
694 plugin->setParameter(i->identifier, pmi->second); | |
695 } | |
696 } | |
697 } | |
698 | |
699 void | |
700 TransformFactory::makeContextConsistentWithPlugin(Transform &transform, | |
701 Vamp::PluginBase *plugin) | |
702 { | |
703 const Vamp::Plugin *vp = downcastVampPlugin(plugin); | |
704 | |
705 if (!vp) { | |
706 // time domain input for real-time effects plugin | |
707 if (!transform.getBlockSize()) { | |
708 if (!transform.getStepSize()) transform.setStepSize(1024); | |
709 transform.setBlockSize(transform.getStepSize()); | |
710 } else { | |
711 transform.setStepSize(transform.getBlockSize()); | |
712 } | |
713 } else { | |
714 Vamp::Plugin::InputDomain domain = vp->getInputDomain(); | |
715 if (!transform.getStepSize()) { | |
716 transform.setStepSize(vp->getPreferredStepSize()); | |
717 } | |
718 if (!transform.getBlockSize()) { | |
719 transform.setBlockSize(vp->getPreferredBlockSize()); | |
720 } | |
721 if (!transform.getBlockSize()) { | |
722 transform.setBlockSize(1024); | |
723 } | |
724 if (!transform.getStepSize()) { | |
725 if (domain == Vamp::Plugin::FrequencyDomain) { | |
726 // std::cerr << "frequency domain, step = " << blockSize/2 << std::endl; | |
727 transform.setStepSize(transform.getBlockSize()/2); | |
728 } else { | |
729 // std::cerr << "time domain, step = " << blockSize/2 << std::endl; | |
730 transform.setStepSize(transform.getBlockSize()); | |
731 } | |
732 } | |
733 } | |
734 } | |
735 | |
736 QString | |
737 TransformFactory::getPluginConfigurationXml(const Transform &t) | |
738 { | |
739 QString xml; | |
740 | |
741 Vamp::PluginBase *plugin = instantiateDefaultPluginFor | |
742 (t.getIdentifier(), 0); | |
743 if (!plugin) { | |
744 std::cerr << "TransformFactory::getPluginConfigurationXml: " | |
745 << "Unable to instantiate plugin for transform \"" | |
746 << t.getIdentifier().toStdString() << "\"" << std::endl; | |
747 return xml; | |
748 } | |
749 | |
750 setPluginParameters(t, plugin); | |
751 | |
752 QTextStream out(&xml); | |
753 PluginXml(plugin).toXml(out); | |
754 delete plugin; | |
755 | |
756 return xml; | |
757 } | |
758 | |
759 void | |
760 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t, | |
761 QString xml) | |
762 { | |
763 Vamp::PluginBase *plugin = instantiateDefaultPluginFor | |
764 (t.getIdentifier(), 0); | |
765 if (!plugin) { | |
766 std::cerr << "TransformFactory::setParametersFromPluginConfigurationXml: " | |
767 << "Unable to instantiate plugin for transform \"" | |
768 << t.getIdentifier().toStdString() << "\"" << std::endl; | |
769 return; | |
770 } | |
771 | |
772 PluginXml(plugin).setParametersFromXml(xml); | |
773 setParametersFromPlugin(t, plugin); | |
774 delete plugin; | |
775 } | |
776 |