Chris@205
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@205
|
2
|
Chris@205
|
3 /*
|
Chris@205
|
4 Sonic Visualiser
|
Chris@205
|
5 An audio file viewer and annotation editor.
|
Chris@205
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@205
|
7
|
Chris@205
|
8 This program is free software; you can redistribute it and/or
|
Chris@205
|
9 modify it under the terms of the GNU General Public License as
|
Chris@205
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@205
|
11 License, or (at your option) any later version. See the file
|
Chris@205
|
12 COPYING included with this distribution for more information.
|
Chris@205
|
13 */
|
Chris@205
|
14
|
Chris@205
|
15 #include "TransformUserConfigurator.h"
|
Chris@205
|
16
|
Chris@205
|
17 #include "transform/TransformFactory.h"
|
Chris@205
|
18
|
Chris@205
|
19 #include "widgets/PluginParameterDialog.h"
|
Chris@205
|
20
|
Chris@205
|
21 #include "plugin/FeatureExtractionPluginFactory.h"
|
Chris@205
|
22 #include "plugin/RealTimePluginFactory.h"
|
Chris@205
|
23 #include "plugin/RealTimePluginInstance.h"
|
Chris@205
|
24
|
Chris@205
|
25 #include "data/model/DenseTimeValueModel.h"
|
Chris@205
|
26
|
Chris@205
|
27 #include <vamp-hostsdk/Plugin.h>
|
Chris@205
|
28
|
Chris@205
|
29 #include <QStringList>
|
Chris@205
|
30
|
Chris@205
|
31 #include <typeinfo>
|
Chris@205
|
32
|
Chris@395
|
33 static QWidget *parentWidget = 0;
|
Chris@395
|
34
|
Chris@395
|
35 void
|
Chris@395
|
36 TransformUserConfigurator::setParentWidget(QWidget *w)
|
Chris@395
|
37 {
|
Chris@395
|
38 parentWidget = w;
|
Chris@395
|
39 }
|
Chris@395
|
40
|
Chris@205
|
41 bool
|
Chris@205
|
42 TransformUserConfigurator::getChannelRange(TransformId identifier,
|
Chris@205
|
43 Vamp::PluginBase *plugin,
|
Chris@205
|
44 int &minChannels, int &maxChannels)
|
Chris@205
|
45 {
|
Chris@205
|
46 if (plugin && plugin->getType() == "Feature Extraction Plugin") {
|
Chris@205
|
47 Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
|
Chris@233
|
48 SVDEBUG << "TransformUserConfigurator::getChannelRange: is a VP" << endl;
|
Chris@436
|
49 minChannels = int(vp->getMinChannelCount());
|
Chris@436
|
50 maxChannels = int(vp->getMaxChannelCount());
|
Chris@205
|
51 return true;
|
Chris@205
|
52 } else {
|
Chris@233
|
53 SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a VP" << endl;
|
Chris@205
|
54 return TransformFactory::getInstance()->
|
Chris@205
|
55 getTransformChannelRange(identifier, minChannels, maxChannels);
|
Chris@205
|
56 }
|
Chris@205
|
57 }
|
Chris@205
|
58
|
Chris@205
|
59 bool
|
Chris@205
|
60 TransformUserConfigurator::configure(ModelTransformer::Input &input,
|
Chris@205
|
61 Transform &transform,
|
Chris@205
|
62 Vamp::PluginBase *plugin,
|
Chris@214
|
63 Model *&inputModel,
|
Chris@205
|
64 AudioPlaySource *source,
|
Chris@437
|
65 sv_frame_t startFrame,
|
Chris@437
|
66 sv_frame_t duration,
|
Chris@205
|
67 const QMap<QString, Model *> &modelMap,
|
Chris@205
|
68 QStringList candidateModelNames,
|
Chris@205
|
69 QString defaultModelName)
|
Chris@205
|
70 {
|
Chris@205
|
71 bool ok = false;
|
Chris@205
|
72 QString id = transform.getPluginIdentifier();
|
Chris@205
|
73 QString output = transform.getOutput();
|
Chris@205
|
74 QString outputLabel = "";
|
Chris@205
|
75 QString outputDescription = "";
|
Chris@205
|
76
|
Chris@205
|
77 bool frequency = false;
|
Chris@205
|
78 bool effect = false;
|
Chris@205
|
79 bool generator = false;
|
Chris@205
|
80
|
Chris@205
|
81 if (!plugin) return false;
|
Chris@205
|
82
|
Chris@205
|
83 if (FeatureExtractionPluginFactory::instanceFor(id)) {
|
Chris@205
|
84
|
Chris@205
|
85 Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
|
Chris@205
|
86
|
Chris@205
|
87 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
|
Chris@205
|
88
|
Chris@205
|
89 std::vector<Vamp::Plugin::OutputDescriptor> od =
|
Chris@205
|
90 vp->getOutputDescriptors();
|
Chris@205
|
91
|
Chris@293
|
92 cerr << "configure: looking for output: " << output << endl;
|
Chris@205
|
93
|
Chris@205
|
94 if (od.size() > 1) {
|
Chris@205
|
95 for (size_t i = 0; i < od.size(); ++i) {
|
Chris@205
|
96 if (od[i].identifier == output.toStdString()) {
|
Chris@205
|
97 outputLabel = od[i].name.c_str();
|
Chris@205
|
98 outputDescription = od[i].description.c_str();
|
Chris@205
|
99 break;
|
Chris@205
|
100 }
|
Chris@205
|
101 }
|
Chris@205
|
102 }
|
Chris@205
|
103
|
Chris@205
|
104 } else if (RealTimePluginFactory::instanceFor(id)) {
|
Chris@205
|
105
|
Chris@205
|
106 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
|
Chris@205
|
107 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
|
Chris@205
|
108
|
Chris@205
|
109 if (desc->audioInputPortCount > 0 &&
|
Chris@205
|
110 desc->audioOutputPortCount > 0 &&
|
Chris@205
|
111 !desc->isSynth) {
|
Chris@205
|
112 effect = true;
|
Chris@205
|
113 }
|
Chris@205
|
114
|
Chris@205
|
115 if (desc->audioInputPortCount == 0) {
|
Chris@205
|
116 generator = true;
|
Chris@205
|
117 }
|
Chris@205
|
118
|
Chris@205
|
119 if (output != "A") {
|
Chris@205
|
120 int outputNo = output.toInt();
|
Chris@205
|
121 if (outputNo >= 0 && outputNo < int(desc->controlOutputPortCount)) {
|
Chris@205
|
122 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
|
Chris@205
|
123 }
|
Chris@205
|
124 }
|
Chris@205
|
125
|
Chris@205
|
126 RealTimePluginInstance *rtp =
|
Chris@205
|
127 static_cast<RealTimePluginInstance *>(plugin);
|
Chris@205
|
128
|
Chris@205
|
129 if (effect && source) {
|
Chris@233
|
130 SVDEBUG << "Setting auditioning effect" << endl;
|
Chris@205
|
131 source->setAuditioningEffect(rtp);
|
Chris@205
|
132 }
|
Chris@205
|
133 }
|
Chris@205
|
134
|
Chris@205
|
135 int sourceChannels = 1;
|
Chris@205
|
136 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
|
Chris@205
|
137 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
|
Chris@205
|
138 ->getChannelCount();
|
Chris@205
|
139 }
|
Chris@205
|
140
|
Chris@205
|
141 int minChannels = 1, maxChannels = sourceChannels;
|
Chris@205
|
142 getChannelRange(transform.getIdentifier(), plugin,
|
Chris@205
|
143 minChannels, maxChannels);
|
Chris@205
|
144
|
Chris@205
|
145 int targetChannels = sourceChannels;
|
Chris@205
|
146 if (!effect) {
|
Chris@205
|
147 if (sourceChannels < minChannels) targetChannels = minChannels;
|
Chris@205
|
148 if (sourceChannels > maxChannels) targetChannels = maxChannels;
|
Chris@205
|
149 }
|
Chris@205
|
150
|
Chris@205
|
151 int defaultChannel = -1; //!!! no longer saved! [was context.channel]
|
Chris@205
|
152
|
Chris@395
|
153 PluginParameterDialog *dialog = new PluginParameterDialog
|
Chris@395
|
154 (plugin, parentWidget);
|
Chris@205
|
155
|
Chris@205
|
156 dialog->setMoreInfoUrl(TransformFactory::getInstance()->
|
Chris@205
|
157 getTransformInfoUrl(transform.getIdentifier()));
|
Chris@205
|
158
|
Chris@205
|
159 if (candidateModelNames.size() > 1 && !generator) {
|
Chris@205
|
160 dialog->setCandidateInputModels(candidateModelNames,
|
Chris@205
|
161 defaultModelName);
|
Chris@205
|
162 }
|
Chris@205
|
163
|
Chris@205
|
164 if (startFrame != 0 || duration != 0) {
|
Chris@205
|
165 dialog->setShowSelectionOnlyOption(true);
|
Chris@205
|
166 }
|
Chris@205
|
167
|
Chris@205
|
168 if (targetChannels > 0) {
|
Chris@205
|
169 dialog->setChannelArrangement(sourceChannels, targetChannels,
|
Chris@205
|
170 defaultChannel);
|
Chris@205
|
171 }
|
Chris@205
|
172
|
Chris@205
|
173 dialog->setOutputLabel(outputLabel, outputDescription);
|
Chris@205
|
174
|
Chris@205
|
175 dialog->setShowProcessingOptions(true, frequency);
|
Chris@205
|
176
|
Chris@205
|
177 if (dialog->exec() == QDialog::Accepted) {
|
Chris@205
|
178 ok = true;
|
Chris@205
|
179 }
|
Chris@205
|
180
|
Chris@205
|
181 QString selectedInput = dialog->getInputModel();
|
Chris@205
|
182 if (selectedInput != "") {
|
Chris@205
|
183 if (modelMap.contains(selectedInput)) {
|
Chris@205
|
184 inputModel = modelMap.value(selectedInput);
|
Chris@293
|
185 cerr << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << endl;
|
Chris@205
|
186 } else {
|
Chris@293
|
187 cerr << "Failed to find selected input \"" << selectedInput << "\" in model map" << endl;
|
Chris@205
|
188 }
|
Chris@205
|
189 } else {
|
Chris@293
|
190 cerr << "Selected input empty: \"" << selectedInput << "\"" << endl;
|
Chris@205
|
191 }
|
Chris@205
|
192
|
Chris@205
|
193 // Write parameters back to transform object
|
Chris@205
|
194 TransformFactory::getInstance()->
|
Chris@205
|
195 setParametersFromPlugin(transform, plugin);
|
Chris@205
|
196
|
Chris@205
|
197 input.setChannel(dialog->getChannel());
|
Chris@205
|
198
|
Chris@205
|
199 //!!! The dialog ought to be taking & returning transform
|
Chris@205
|
200 //objects and input objects and stuff rather than passing
|
Chris@205
|
201 //around all this misc stuff, but that's for tomorrow
|
Chris@205
|
202 //(whenever that may be)
|
Chris@205
|
203
|
Chris@205
|
204 if (startFrame != 0 || duration != 0) {
|
Chris@205
|
205 if (dialog->getSelectionOnly()) {
|
Chris@205
|
206 transform.setStartTime(RealTime::frame2RealTime
|
Chris@205
|
207 (startFrame, inputModel->getSampleRate()));
|
Chris@205
|
208 transform.setDuration(RealTime::frame2RealTime
|
Chris@205
|
209 (duration, inputModel->getSampleRate()));
|
Chris@205
|
210 }
|
Chris@205
|
211 }
|
Chris@205
|
212
|
Chris@366
|
213 int stepSize = 0, blockSize = 0;
|
Chris@205
|
214 WindowType windowType = HanningWindow;
|
Chris@205
|
215
|
Chris@205
|
216 dialog->getProcessingParameters(stepSize,
|
Chris@205
|
217 blockSize,
|
Chris@205
|
218 windowType);
|
Chris@205
|
219
|
Chris@205
|
220 transform.setStepSize(stepSize);
|
Chris@205
|
221 transform.setBlockSize(blockSize);
|
Chris@205
|
222 transform.setWindowType(windowType);
|
Chris@205
|
223
|
Chris@205
|
224 delete dialog;
|
Chris@205
|
225
|
Chris@205
|
226 if (effect && source) {
|
Chris@205
|
227 source->setAuditioningEffect(0);
|
Chris@205
|
228 }
|
Chris@205
|
229
|
Chris@205
|
230 return ok;
|
Chris@205
|
231 }
|
Chris@205
|
232
|