Mercurial > hg > svcore
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 |