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 "BeatDetectTransform.h"
|
Chris@0
|
19 #include "BeatDetectionFunctionTransform.h"
|
Chris@0
|
20 #include "FeatureExtractionPluginTransform.h"
|
Chris@0
|
21
|
Chris@0
|
22 #include "plugin/FeatureExtractionPluginFactory.h"
|
Chris@0
|
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@16
|
45 for (TransformMap::const_iterator i = m_transforms.begin();
|
Chris@16
|
46 i != m_transforms.end(); ++i) {
|
Chris@16
|
47 list.push_back(TransformDesc(i->first, 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@20
|
100 m_transforms[transformName] = userDescription;
|
Chris@47
|
101
|
Chris@47
|
102 makers[transformName] = plugin->getMaker().c_str();
|
Chris@0
|
103 }
|
Chris@0
|
104 }
|
Chris@47
|
105
|
Chris@47
|
106 // disambiguate plugins with similar descriptions
|
Chris@47
|
107
|
Chris@47
|
108 std::map<QString, int> descriptions;
|
Chris@47
|
109
|
Chris@47
|
110 for (TransformMap::iterator i = m_transforms.begin(); i != m_transforms.end();
|
Chris@47
|
111 ++i) {
|
Chris@47
|
112
|
Chris@47
|
113 QString name = i->first, description = i->second;
|
Chris@47
|
114
|
Chris@47
|
115 ++descriptions[description];
|
Chris@47
|
116 ++descriptions[QString("%1 [%2]").arg(description).arg(makers[name])];
|
Chris@47
|
117 }
|
Chris@47
|
118
|
Chris@47
|
119 std::map<QString, int> counts;
|
Chris@47
|
120 TransformMap newMap;
|
Chris@47
|
121
|
Chris@47
|
122 for (TransformMap::iterator i = m_transforms.begin(); i != m_transforms.end();
|
Chris@47
|
123 ++i) {
|
Chris@47
|
124
|
Chris@47
|
125 QString name = i->first, description = i->second;
|
Chris@47
|
126
|
Chris@47
|
127 if (descriptions[description] > 1) {
|
Chris@47
|
128 description = QString("%1 [%2]").arg(description).arg(makers[name]);
|
Chris@47
|
129 if (descriptions[description] > 1) {
|
Chris@47
|
130 description = QString("%1 <%2>")
|
Chris@47
|
131 .arg(description).arg(++counts[description]);
|
Chris@47
|
132 }
|
Chris@47
|
133 }
|
Chris@47
|
134
|
Chris@47
|
135 newMap[name] = description;
|
Chris@47
|
136 }
|
Chris@47
|
137
|
Chris@47
|
138 m_transforms = newMap;
|
Chris@16
|
139 }
|
Chris@16
|
140
|
Chris@16
|
141 QString
|
Chris@16
|
142 TransformFactory::getTransformDescription(TransformName name)
|
Chris@16
|
143 {
|
Chris@16
|
144 if (m_transforms.find(name) != m_transforms.end()) {
|
Chris@16
|
145 return m_transforms[name];
|
Chris@16
|
146 } else return "";
|
Chris@0
|
147 }
|
Chris@0
|
148
|
Chris@18
|
149 QString
|
Chris@18
|
150 TransformFactory::getTransformFriendlyName(TransformName name)
|
Chris@18
|
151 {
|
Chris@18
|
152 QString description = getTransformDescription(name);
|
Chris@18
|
153
|
Chris@18
|
154 int i = description.indexOf(':');
|
Chris@18
|
155 if (i >= 0) {
|
Chris@18
|
156 return description.remove(0, i + 2);
|
Chris@18
|
157 } else {
|
Chris@18
|
158 return description;
|
Chris@18
|
159 }
|
Chris@18
|
160 }
|
Chris@18
|
161
|
Chris@0
|
162 Transform *
|
Chris@0
|
163 TransformFactory::createTransform(TransformName name, Model *inputModel)
|
Chris@0
|
164 {
|
Chris@0
|
165 return createTransform(name, inputModel, true);
|
Chris@0
|
166 }
|
Chris@0
|
167
|
Chris@0
|
168 Transform *
|
Chris@0
|
169 TransformFactory::createTransform(TransformName name, Model *inputModel,
|
Chris@0
|
170 bool start)
|
Chris@0
|
171 {
|
Chris@0
|
172 Transform *transform = 0;
|
Chris@0
|
173
|
Chris@0
|
174 if (name == BeatDetectTransform::getName()) {
|
Chris@0
|
175 transform = new BeatDetectTransform(inputModel);
|
Chris@0
|
176 } else if (name == BeatDetectionFunctionTransform::getName()) {
|
Chris@0
|
177 transform = new BeatDetectionFunctionTransform(inputModel);
|
Chris@0
|
178 } else {
|
Chris@0
|
179 QString id = name.section(':', 0, 2);
|
Chris@0
|
180 QString output = name.section(':', 3);
|
Chris@0
|
181 if (FeatureExtractionPluginFactory::instanceFor(id)) {
|
Chris@0
|
182 transform = new FeatureExtractionPluginTransform(inputModel,
|
Chris@0
|
183 id, output);
|
Chris@0
|
184 } else {
|
Chris@0
|
185 std::cerr << "TransformFactory::createTransform: Unknown transform "
|
Chris@0
|
186 << name.toStdString() << std::endl;
|
Chris@0
|
187 }
|
Chris@0
|
188 }
|
Chris@0
|
189
|
Chris@0
|
190 if (start && transform) transform->start();
|
Chris@16
|
191 transform->setObjectName(name);
|
Chris@0
|
192 return transform;
|
Chris@0
|
193 }
|
Chris@0
|
194
|
Chris@0
|
195 Model *
|
Chris@0
|
196 TransformFactory::transform(TransformName name, Model *inputModel)
|
Chris@0
|
197 {
|
Chris@0
|
198 Transform *t = createTransform(name, inputModel, false);
|
Chris@0
|
199
|
Chris@0
|
200 if (!t) return 0;
|
Chris@0
|
201
|
Chris@0
|
202 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
|
Chris@0
|
203
|
Chris@0
|
204 t->start();
|
Chris@0
|
205 return t->detachOutputModel();
|
Chris@0
|
206 }
|
Chris@0
|
207
|
Chris@0
|
208 void
|
Chris@0
|
209 TransformFactory::transformFinished()
|
Chris@0
|
210 {
|
Chris@0
|
211 QObject *s = sender();
|
Chris@0
|
212 Transform *transform = dynamic_cast<Transform *>(s);
|
Chris@0
|
213
|
Chris@0
|
214 if (!transform) {
|
Chris@0
|
215 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
|
Chris@0
|
216 return;
|
Chris@0
|
217 }
|
Chris@0
|
218
|
Chris@0
|
219 transform->wait(); // unnecessary but reassuring
|
Chris@0
|
220 delete transform;
|
Chris@0
|
221 }
|
Chris@0
|
222
|