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@0
|
4 A waveform viewer and audio annotation editor.
|
Chris@2
|
5 Chris Cannam, Queen Mary University of London, 2005-2006
|
Chris@0
|
6
|
Chris@0
|
7 This is experimental software. Not for distribution.
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 #include "TransformFactory.h"
|
Chris@0
|
11
|
Chris@0
|
12 #include "BeatDetectTransform.h"
|
Chris@0
|
13 #include "BeatDetectionFunctionTransform.h"
|
Chris@0
|
14 #include "FeatureExtractionPluginTransform.h"
|
Chris@0
|
15
|
Chris@0
|
16 #include "plugin/FeatureExtractionPluginFactory.h"
|
Chris@0
|
17
|
Chris@0
|
18 #include <iostream>
|
Chris@0
|
19
|
Chris@0
|
20 TransformFactory *
|
Chris@0
|
21 TransformFactory::m_instance = new TransformFactory;
|
Chris@0
|
22
|
Chris@0
|
23 TransformFactory *
|
Chris@0
|
24 TransformFactory::instance()
|
Chris@0
|
25 {
|
Chris@0
|
26 return m_instance;
|
Chris@0
|
27 }
|
Chris@0
|
28
|
Chris@0
|
29 TransformFactory::~TransformFactory()
|
Chris@0
|
30 {
|
Chris@0
|
31 }
|
Chris@0
|
32
|
Chris@0
|
33 TransformFactory::TransformList
|
Chris@0
|
34 TransformFactory::getAllTransforms()
|
Chris@0
|
35 {
|
Chris@16
|
36 if (m_transforms.empty()) populateTransforms();
|
Chris@16
|
37
|
Chris@0
|
38 TransformList list;
|
Chris@16
|
39 for (TransformMap::const_iterator i = m_transforms.begin();
|
Chris@16
|
40 i != m_transforms.end(); ++i) {
|
Chris@16
|
41 list.push_back(TransformDesc(i->first, i->second));
|
Chris@16
|
42 }
|
Chris@0
|
43
|
Chris@16
|
44 return list;
|
Chris@16
|
45 }
|
Chris@16
|
46
|
Chris@16
|
47 void
|
Chris@16
|
48 TransformFactory::populateTransforms()
|
Chris@16
|
49 {
|
Chris@0
|
50 std::vector<QString> fexplugs =
|
Chris@0
|
51 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
|
Chris@0
|
52
|
Chris@47
|
53 std::map<QString, QString> makers;
|
Chris@47
|
54
|
Chris@0
|
55 for (size_t i = 0; i < fexplugs.size(); ++i) {
|
Chris@0
|
56
|
Chris@0
|
57 QString pluginId = fexplugs[i];
|
Chris@0
|
58
|
Chris@0
|
59 FeatureExtractionPluginFactory *factory =
|
Chris@0
|
60 FeatureExtractionPluginFactory::instanceFor(pluginId);
|
Chris@0
|
61
|
Chris@20
|
62 if (!factory) {
|
Chris@20
|
63 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
|
Chris@20
|
64 continue;
|
Chris@20
|
65 }
|
Chris@0
|
66
|
Chris@20
|
67 FeatureExtractionPlugin *plugin =
|
Chris@20
|
68 factory->instantiatePlugin(pluginId, 48000);
|
Chris@0
|
69
|
Chris@20
|
70 if (!plugin) {
|
Chris@20
|
71 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
|
Chris@20
|
72 continue;
|
Chris@20
|
73 }
|
Chris@20
|
74
|
Chris@20
|
75 QString pluginDescription = plugin->getDescription().c_str();
|
Chris@20
|
76 FeatureExtractionPlugin::OutputList outputs =
|
Chris@20
|
77 plugin->getOutputDescriptors();
|
Chris@0
|
78
|
Chris@20
|
79 for (size_t j = 0; j < outputs.size(); ++j) {
|
Chris@0
|
80
|
Chris@20
|
81 QString transformName = QString("%1:%2")
|
Chris@20
|
82 .arg(pluginId).arg(outputs[j].name.c_str());
|
Chris@20
|
83
|
Chris@20
|
84 QString userDescription;
|
Chris@20
|
85
|
Chris@20
|
86 if (outputs.size() == 1) {
|
Chris@20
|
87 userDescription = pluginDescription;
|
Chris@20
|
88 } else {
|
Chris@20
|
89 userDescription = QString("%1: %2")
|
Chris@20
|
90 .arg(pluginDescription)
|
Chris@20
|
91 .arg(outputs[j].description.c_str());
|
Chris@0
|
92 }
|
Chris@20
|
93
|
Chris@20
|
94 m_transforms[transformName] = userDescription;
|
Chris@47
|
95
|
Chris@47
|
96 makers[transformName] = plugin->getMaker().c_str();
|
Chris@0
|
97 }
|
Chris@0
|
98 }
|
Chris@47
|
99
|
Chris@47
|
100 // disambiguate plugins with similar descriptions
|
Chris@47
|
101
|
Chris@47
|
102 std::map<QString, int> descriptions;
|
Chris@47
|
103
|
Chris@47
|
104 for (TransformMap::iterator i = m_transforms.begin(); i != m_transforms.end();
|
Chris@47
|
105 ++i) {
|
Chris@47
|
106
|
Chris@47
|
107 QString name = i->first, description = i->second;
|
Chris@47
|
108
|
Chris@47
|
109 ++descriptions[description];
|
Chris@47
|
110 ++descriptions[QString("%1 [%2]").arg(description).arg(makers[name])];
|
Chris@47
|
111 }
|
Chris@47
|
112
|
Chris@47
|
113 std::map<QString, int> counts;
|
Chris@47
|
114 TransformMap newMap;
|
Chris@47
|
115
|
Chris@47
|
116 for (TransformMap::iterator i = m_transforms.begin(); i != m_transforms.end();
|
Chris@47
|
117 ++i) {
|
Chris@47
|
118
|
Chris@47
|
119 QString name = i->first, description = i->second;
|
Chris@47
|
120
|
Chris@47
|
121 if (descriptions[description] > 1) {
|
Chris@47
|
122 description = QString("%1 [%2]").arg(description).arg(makers[name]);
|
Chris@47
|
123 if (descriptions[description] > 1) {
|
Chris@47
|
124 description = QString("%1 <%2>")
|
Chris@47
|
125 .arg(description).arg(++counts[description]);
|
Chris@47
|
126 }
|
Chris@47
|
127 }
|
Chris@47
|
128
|
Chris@47
|
129 newMap[name] = description;
|
Chris@47
|
130 }
|
Chris@47
|
131
|
Chris@47
|
132 m_transforms = newMap;
|
Chris@16
|
133 }
|
Chris@16
|
134
|
Chris@16
|
135 QString
|
Chris@16
|
136 TransformFactory::getTransformDescription(TransformName name)
|
Chris@16
|
137 {
|
Chris@16
|
138 if (m_transforms.find(name) != m_transforms.end()) {
|
Chris@16
|
139 return m_transforms[name];
|
Chris@16
|
140 } else return "";
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@18
|
143 QString
|
Chris@18
|
144 TransformFactory::getTransformFriendlyName(TransformName name)
|
Chris@18
|
145 {
|
Chris@18
|
146 QString description = getTransformDescription(name);
|
Chris@18
|
147
|
Chris@18
|
148 int i = description.indexOf(':');
|
Chris@18
|
149 if (i >= 0) {
|
Chris@18
|
150 return description.remove(0, i + 2);
|
Chris@18
|
151 } else {
|
Chris@18
|
152 return description;
|
Chris@18
|
153 }
|
Chris@18
|
154 }
|
Chris@18
|
155
|
Chris@0
|
156 Transform *
|
Chris@0
|
157 TransformFactory::createTransform(TransformName name, Model *inputModel)
|
Chris@0
|
158 {
|
Chris@0
|
159 return createTransform(name, inputModel, true);
|
Chris@0
|
160 }
|
Chris@0
|
161
|
Chris@0
|
162 Transform *
|
Chris@0
|
163 TransformFactory::createTransform(TransformName name, Model *inputModel,
|
Chris@0
|
164 bool start)
|
Chris@0
|
165 {
|
Chris@0
|
166 Transform *transform = 0;
|
Chris@0
|
167
|
Chris@0
|
168 if (name == BeatDetectTransform::getName()) {
|
Chris@0
|
169 transform = new BeatDetectTransform(inputModel);
|
Chris@0
|
170 } else if (name == BeatDetectionFunctionTransform::getName()) {
|
Chris@0
|
171 transform = new BeatDetectionFunctionTransform(inputModel);
|
Chris@0
|
172 } else {
|
Chris@0
|
173 QString id = name.section(':', 0, 2);
|
Chris@0
|
174 QString output = name.section(':', 3);
|
Chris@0
|
175 if (FeatureExtractionPluginFactory::instanceFor(id)) {
|
Chris@0
|
176 transform = new FeatureExtractionPluginTransform(inputModel,
|
Chris@0
|
177 id, output);
|
Chris@0
|
178 } else {
|
Chris@0
|
179 std::cerr << "TransformFactory::createTransform: Unknown transform "
|
Chris@0
|
180 << name.toStdString() << std::endl;
|
Chris@0
|
181 }
|
Chris@0
|
182 }
|
Chris@0
|
183
|
Chris@0
|
184 if (start && transform) transform->start();
|
Chris@16
|
185 transform->setObjectName(name);
|
Chris@0
|
186 return transform;
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 Model *
|
Chris@0
|
190 TransformFactory::transform(TransformName name, Model *inputModel)
|
Chris@0
|
191 {
|
Chris@0
|
192 Transform *t = createTransform(name, inputModel, false);
|
Chris@0
|
193
|
Chris@0
|
194 if (!t) return 0;
|
Chris@0
|
195
|
Chris@0
|
196 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
|
Chris@0
|
197
|
Chris@0
|
198 t->start();
|
Chris@0
|
199 return t->detachOutputModel();
|
Chris@0
|
200 }
|
Chris@0
|
201
|
Chris@0
|
202 void
|
Chris@0
|
203 TransformFactory::transformFinished()
|
Chris@0
|
204 {
|
Chris@0
|
205 QObject *s = sender();
|
Chris@0
|
206 Transform *transform = dynamic_cast<Transform *>(s);
|
Chris@0
|
207
|
Chris@0
|
208 if (!transform) {
|
Chris@0
|
209 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
|
Chris@0
|
210 return;
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 transform->wait(); // unnecessary but reassuring
|
Chris@0
|
214 delete transform;
|
Chris@0
|
215 }
|
Chris@0
|
216
|