comparison VamPipePluginLibrary.cpp @ 100:708bd44f8019

Merge from noexcept branch
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 23 Sep 2016 14:23:10 +0100
parents dfd107ef991f
children 30028b3c95e4
comparison
equal deleted inserted replaced
98:22a09aca4b4a 100:708bd44f8019
42 namespace vampipe { 42 namespace vampipe {
43 43
44 //!!! too many explicit namespaces here 44 //!!! too many explicit namespaces here
45 45
46 //!!! dup with vampipe-convert 46 //!!! dup with vampipe-convert
47 static Json 47 Json
48 convertRequestJson(string input) 48 convertRequestJson(string input, string &err)
49 { 49 {
50 string err;
51 Json j = Json::parse(input, err); 50 Json j = Json::parse(input, err);
52 if (err != "") { 51 if (err != "") {
53 throw VampJson::Failure("invalid json: " + err); 52 err = "invalid json: " + err;
53 return {};
54 } 54 }
55 if (!j.is_object()) { 55 if (!j.is_object()) {
56 throw VampJson::Failure("object expected at top level"); 56 err = "object expected at top level";
57 } 57 } else if (!j["type"].is_string()) {
58 if (!j["type"].is_string()) { 58 err = "string expected for type field";
59 throw VampJson::Failure("string expected for type field"); 59 } else if (!j["content"].is_null() && !j["content"].is_object()) {
60 } 60 err = "object expected for content field";
61 if (!j["content"].is_null() && !j["content"].is_object()) {
62 throw VampJson::Failure("object expected for content field");
63 } 61 }
64 return j; 62 return j;
65 } 63 }
66 64
67 VamPipePluginLibrary::VamPipePluginLibrary(vector<VamPipeAdapterInterface *> pp) : 65 VamPipePluginLibrary::VamPipePluginLibrary(vector<VamPipeAdapterInterface *> pp) :
82 } 80 }
83 return resp; 81 return resp;
84 } 82 }
85 83
86 Vamp::HostExt::LoadResponse 84 Vamp::HostExt::LoadResponse
87 VamPipePluginLibrary::loadPlugin(Vamp::HostExt::LoadRequest req) const 85 VamPipePluginLibrary::loadPlugin(Vamp::HostExt::LoadRequest req, string &err) const
88 { 86 {
89 string key = req.pluginKey; 87 string key = req.pluginKey;
90 if (m_adapters.find(key) != m_adapters.end()) { 88 if (m_adapters.find(key) != m_adapters.end()) {
91 return m_adapters.at(key)->loadPlugin(req); 89 auto resp = m_adapters.at(key)->loadPlugin(req);
90 if (!resp.plugin) {
91 // This should not actually happen -- the load call here
92 // is just an object construction, not a dynamic load. But
93 // report it if it does...
94 err = "failed to construct plugin with key " + key;
95 }
96 return resp;
92 } else { 97 } else {
93 throw runtime_error("no adapter for plugin key " + key); 98 err = "no adapter for plugin key " + key;
99 return {};
94 } 100 }
95 } 101 }
96 102
97 Vamp::HostExt::ConfigurationResponse 103 Vamp::HostExt::ConfigurationResponse
98 VamPipePluginLibrary::configurePlugin(Vamp::HostExt::ConfigurationRequest req) const 104 VamPipePluginLibrary::configurePlugin(Vamp::HostExt::ConfigurationRequest req,
105 string &err) const
99 { 106 {
100 for (Vamp::HostExt::PluginConfiguration::ParameterMap::const_iterator i = 107 for (Vamp::HostExt::PluginConfiguration::ParameterMap::const_iterator i =
101 req.configuration.parameterValues.begin(); 108 req.configuration.parameterValues.begin();
102 i != req.configuration.parameterValues.end(); ++i) { 109 i != req.configuration.parameterValues.end(); ++i) {
103 req.plugin->setParameter(i->first, i->second); 110 req.plugin->setParameter(i->first, i->second);
113 120
114 if (req.plugin->initialise(req.configuration.channelCount, 121 if (req.plugin->initialise(req.configuration.channelCount,
115 req.configuration.stepSize, 122 req.configuration.stepSize,
116 req.configuration.blockSize)) { 123 req.configuration.blockSize)) {
117 response.outputs = req.plugin->getOutputDescriptors(); 124 response.outputs = req.plugin->getOutputDescriptors();
125 } else {
126 err = "configuration failed (wrong channel count, step size, block size?)";
118 } 127 }
119 128
120 return response; 129 return response;
121 } 130 }
122 131
124 VamPipePluginLibrary::processRawImpl(int pluginHandle, 133 VamPipePluginLibrary::processRawImpl(int pluginHandle,
125 const float *const *inputBuffers, 134 const float *const *inputBuffers,
126 int sec, 135 int sec,
127 int nsec) 136 int nsec)
128 { 137 {
129 try { 138 Vamp::Plugin *plugin = m_mapper.handleToPlugin(pluginHandle);
130 if (!m_mapper.isConfigured(pluginHandle)) { 139 if (!plugin) {
131 throw runtime_error("plugin has not been configured"); 140 return VampJson::fromError("unknown plugin handle", RRType::Process)
132 }
133
134 Vamp::Plugin *plugin = m_mapper.handleToPlugin(pluginHandle);
135 Vamp::RealTime timestamp(sec, nsec);
136
137 Vamp::HostExt::ProcessResponse resp;
138 resp.plugin = plugin;
139 resp.features = plugin->process(inputBuffers, timestamp);
140
141 m_useBase64 = true;
142
143 return VampJson::fromVampResponse_Process
144 (resp, m_mapper,
145 VampJson::BufferSerialisation::Base64)
146 .dump(); 141 .dump();
147 142 }
148 } catch (const std::exception &e) { 143
149 return VampJson::fromException(e, RRType::Process) 144 if (!m_mapper.isConfigured(pluginHandle)) {
145 return VampJson::fromError("plugin has not been configured", RRType::Process)
150 .dump(); 146 .dump();
151 } 147 }
148
149 Vamp::RealTime timestamp(sec, nsec);
150
151 Vamp::HostExt::ProcessResponse resp;
152 resp.plugin = plugin;
153 resp.features = plugin->process(inputBuffers, timestamp);
154
155 m_useBase64 = true;
156
157 return VampJson::fromVampResponse_Process
158 (resp, m_mapper,
159 VampJson::BufferSerialisation::Base64)
160 .dump();
152 } 161 }
153 162
154 string 163 string
155 VamPipePluginLibrary::requestJsonImpl(string req) 164 VamPipePluginLibrary::requestJsonImpl(string req)
156 { 165 {
157 Json j = convertRequestJson(req); 166 string err;
158 167
159 RRType type; 168 Json j = convertRequestJson(req, err);
160 try { 169 if (err != "") {
161 type = VampJson::getRequestResponseType(j); 170 return VampJson::fromError(err, RRType::NotValid).dump();
162 } catch (const std::exception &e) { 171 }
163 return VampJson::fromException(e, RRType::NotValid) 172
164 .dump(); 173 RRType type = VampJson::getRequestResponseType(j, err);
174 if (err != "") {
175 return VampJson::fromError(err, RRType::NotValid).dump();
165 } 176 }
166 177
167 VampJson::BufferSerialisation serialisation = 178 VampJson::BufferSerialisation serialisation =
168 (m_useBase64 ? 179 (m_useBase64 ?
169 VampJson::BufferSerialisation::Base64 : 180 VampJson::BufferSerialisation::Base64 :
170 VampJson::BufferSerialisation::Text); 181 VampJson::BufferSerialisation::Text);
171 182
172 Json rj; 183 Json rj;
173 184
174 try { 185 switch (type) {
175 switch (type) { 186
176 187 case RRType::List:
177 case RRType::List: 188 rj = VampJson::fromVampResponse_List(listPluginData());
178 rj = VampJson::fromVampResponse_List(listPluginData()); 189 break;
179 break; 190
180 191 case RRType::Load:
181 case RRType::Load: 192 {
182 { 193 auto req = VampJson::toVampRequest_Load(j, err);
183 auto req = VampJson::toVampRequest_Load(j); 194 if (err != "") {
184 auto resp = loadPlugin(req); 195 rj = VampJson::fromError(err, type);
185 if (resp.plugin) { 196 } else {
197 auto resp = loadPlugin(req, err);
198 if (err != "") {
199 rj = VampJson::fromError(err, type);
200 } else {
186 m_mapper.addPlugin(resp.plugin); 201 m_mapper.addPlugin(resp.plugin);
202 rj = VampJson::fromVampResponse_Load(resp, m_mapper);
187 } 203 }
188 rj = VampJson::fromVampResponse_Load(resp, m_mapper); 204 }
189 break; 205 break;
190 } 206 }
191 207
192 case RRType::Configure: 208 case RRType::Configure:
193 { 209 {
194 auto req = VampJson::toVampRequest_Configure(j, m_mapper); 210 auto req = VampJson::toVampRequest_Configure(j, m_mapper, err);
211 if (err != "") {
212 rj = VampJson::fromError(err, type);
213 } else {
195 auto h = m_mapper.pluginToHandle(req.plugin); 214 auto h = m_mapper.pluginToHandle(req.plugin);
196 if (m_mapper.isConfigured(h)) { 215 if (h == m_mapper.INVALID_HANDLE) {
197 throw runtime_error("plugin has already been configured"); 216 rj = VampJson::fromError("unknown or invalid plugin handle", type);
217 } else if (m_mapper.isConfigured(h)) {
218 rj = VampJson::fromError("plugin has already been configured", type);
219 } else {
220 auto resp = configurePlugin(req, err);
221 if (err != "") {
222 rj = VampJson::fromError(err, type);
223 } else {
224 m_mapper.markConfigured(h,
225 req.configuration.channelCount,
226 req.configuration.blockSize);
227 rj = VampJson::fromVampResponse_Configure(resp, m_mapper);
228 }
198 } 229 }
199 230 }
200 auto resp = configurePlugin(req); 231 break;
201 if (!resp.outputs.empty()) { 232 }
202 m_mapper.markConfigured(h, 233
203 req.configuration.channelCount, 234 case RRType::Process:
204 req.configuration.blockSize); 235 {
236 VampJson::BufferSerialisation serialisation;
237
238 auto req = VampJson::toVampRequest_Process(j, m_mapper,
239 serialisation, err);
240 if (err != "") {
241 rj = VampJson::fromError(err, type);
242 } else {
243 auto h = m_mapper.pluginToHandle(req.plugin);
244 int channels = int(req.inputBuffers.size());
245 if (h == m_mapper.INVALID_HANDLE) {
246 rj = VampJson::fromError("unknown or invalid plugin handle", type);
247 } else if (!m_mapper.isConfigured(h)) {
248 rj = VampJson::fromError("plugin has not been configured", type);
249 } else if (channels != m_mapper.getChannelCount(h)) {
250 rj = VampJson::fromError("wrong number of channels supplied", type);
251 } else {
252
253 if (serialisation == VampJson::BufferSerialisation::Base64) {
254 m_useBase64 = true;
255 }
256
257 size_t blockSize = m_mapper.getBlockSize(h);
258
259 const float **fbuffers = new const float *[channels];
260 for (int i = 0; i < channels; ++i) {
261 if (req.inputBuffers[i].size() != blockSize) {
262 delete[] fbuffers;
263 fbuffers = 0;
264 rj = VampJson::fromError("wrong block size supplied", type);
265 break;
266 }
267 fbuffers[i] = req.inputBuffers[i].data();
268 }
269
270 if (fbuffers) {
271 Vamp::HostExt::ProcessResponse resp;
272 resp.plugin = req.plugin;
273 resp.features = req.plugin->process(fbuffers, req.timestamp);
274 delete[] fbuffers;
275 rj = VampJson::fromVampResponse_Process
276 (resp, m_mapper, serialisation);
277 }
205 } 278 }
206 279 }
207 rj = VampJson::fromVampResponse_Configure(resp, m_mapper); 280 break;
208 break; 281 }
209 } 282
210 283 case RRType::Finish:
211 case RRType::Process: 284 {
212 { 285 auto req = VampJson::toVampRequest_Finish(j, m_mapper, err);
213 VampJson::BufferSerialisation serialisation; 286 if (err != "") {
214 287 rj = VampJson::fromError(err, type);
215 auto req = VampJson::toVampRequest_Process(j, m_mapper, 288 } else {
216 serialisation);
217
218 auto h = m_mapper.pluginToHandle(req.plugin); 289 auto h = m_mapper.pluginToHandle(req.plugin);
219 if (!m_mapper.isConfigured(h)) { 290 if (h == m_mapper.INVALID_HANDLE) {
220 throw runtime_error("plugin has not been configured"); 291 rj = VampJson::fromError("unknown or invalid plugin handle", type);
292 } else if (!m_mapper.isConfigured(h)) {
293 rj = VampJson::fromError("plugin has not been configured", type);
294 } else {
295
296 Vamp::HostExt::ProcessResponse resp;
297 resp.plugin = req.plugin;
298 resp.features = req.plugin->getRemainingFeatures();
299
300 rj = VampJson::fromVampResponse_Finish
301 (resp, m_mapper, serialisation);
302
303 m_mapper.removePlugin(h);
304 delete req.plugin;
221 } 305 }
222 306 }
223 int channels = int(req.inputBuffers.size()); 307 break;
224 if (channels != m_mapper.getChannelCount(h)) { 308 }
225 throw runtime_error("wrong number of channels supplied to process"); 309
226 } 310 case RRType::NotValid:
227 311 rj = VampJson::fromError("invalid request", type);
228 if (serialisation == VampJson::BufferSerialisation::Base64) { 312 break;
229 m_useBase64 = true;
230 }
231
232 const float **fbuffers = new const float *[channels];
233 for (int i = 0; i < channels; ++i) {
234 if (int(req.inputBuffers[i].size()) != m_mapper.getBlockSize(h)) {
235 delete[] fbuffers;
236 throw runtime_error("wrong block size supplied to process");
237 }
238 fbuffers[i] = req.inputBuffers[i].data();
239 }
240
241 Vamp::HostExt::ProcessResponse resp;
242 resp.plugin = req.plugin;
243 resp.features = req.plugin->process(fbuffers, req.timestamp);
244 delete[] fbuffers;
245
246 rj = VampJson::fromVampResponse_Process(resp, m_mapper, serialisation);
247 break;
248 }
249
250 case RRType::Finish:
251 {
252 auto req = VampJson::toVampRequest_Finish(j, m_mapper);
253 auto h = m_mapper.pluginToHandle(req.plugin);
254 if (!m_mapper.isConfigured(h)) {
255 throw runtime_error("plugin has not been configured");
256 }
257
258 Vamp::HostExt::ProcessResponse resp;
259 resp.plugin = req.plugin;
260 resp.features = req.plugin->getRemainingFeatures();
261
262 rj = VampJson::fromVampResponse_Finish(resp, m_mapper, serialisation);
263
264 m_mapper.removePlugin(h);
265 delete req.plugin;
266 break;
267 }
268
269 case RRType::NotValid:
270 rj = VampJson::fromError("invalid request", type);
271 break;
272 }
273
274 } catch (const std::exception &e) {
275 rj = VampJson::fromException(e, type);
276 } 313 }
277 314
278 return rj.dump(); 315 return rj.dump();
279 } 316 }
280 317