annotate json/VampJson.h @ 66:6f160dee1192

Instead of using separate values and b64values entries in JSON serialisations, allow numeric arrays to be replaced by b64 variants wherever they appear (discriminating by type). Also rename values to featureValues in feature throughout, as values turns out to be a hazardous name in a JS context. Finally use Array instead of Text for array encoding (seems clearer).
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 27 Sep 2016 15:04:59 +0100
parents 2d866edd79d5
children db17657ac875
rev   line source
c@5 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@5 2
c@18 3 /*
c@18 4 VamPipe
c@18 5
c@18 6 Centre for Digital Music, Queen Mary, University of London.
c@18 7 Copyright 2015-2016 QMUL.
c@18 8
c@18 9 Permission is hereby granted, free of charge, to any person
c@18 10 obtaining a copy of this software and associated documentation
c@18 11 files (the "Software"), to deal in the Software without
c@18 12 restriction, including without limitation the rights to use, copy,
c@18 13 modify, merge, publish, distribute, sublicense, and/or sell copies
c@18 14 of the Software, and to permit persons to whom the Software is
c@18 15 furnished to do so, subject to the following conditions:
c@18 16
c@18 17 The above copyright notice and this permission notice shall be
c@18 18 included in all copies or substantial portions of the Software.
c@18 19
c@18 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
c@18 21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
c@18 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
c@18 23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
c@18 24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
c@18 25 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
c@18 26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
c@18 27
c@18 28 Except as contained in this notice, the names of the Centre for
c@18 29 Digital Music; Queen Mary, University of London; and Chris Cannam
c@18 30 shall not be used in advertising or otherwise to promote the sale,
c@18 31 use or other dealings in this Software without prior written
c@18 32 authorization.
c@18 33 */
c@18 34
c@5 35 #ifndef VAMP_JSON_H
c@5 36 #define VAMP_JSON_H
c@5 37
c@5 38 #include <vector>
c@5 39 #include <string>
c@5 40 #include <sstream>
c@5 41
c@5 42 #include <json11/json11.hpp>
c@5 43 #include <base-n/include/basen.hpp>
c@5 44
c@5 45 #include <vamp-hostsdk/Plugin.h>
c@5 46 #include <vamp-hostsdk/PluginLoader.h>
c@5 47
c@10 48 #include "bits/PluginHandleMapper.h"
c@49 49 #include "bits/PluginOutputIdMapper.h"
c@25 50 #include "bits/RequestResponseType.h"
c@10 51
c@10 52 namespace vampipe {
c@10 53
c@6 54 /**
c@6 55 * Convert the structures laid out in the Vamp SDK classes into JSON
c@6 56 * (and back again) following the schema in the vamp-json-schema
c@6 57 * project repo.
c@60 58 *
c@60 59 * Functions with names starting "from" convert from a Vamp SDK object
c@60 60 * to JSON output. Most of them return a json11::Json object, with a
c@60 61 * few exceptions for low-level utilities that return a string. These
c@60 62 * functions succeed all of the time.
c@60 63 *
c@60 64 * Functions with names starting "to" convert to a Vamp SDK object
c@60 65 * from JSON input. These functions all accept a json11::Json object
c@60 66 * as first argument, with a few exceptions for low-level utilities
c@60 67 * that accept a string. These functions all accept a string reference
c@60 68 * as a final argument and return an error string through it if the
c@60 69 * conversion fails. If conversion fails the return value is
c@60 70 * undefined, and any returned object may be incomplete or
c@60 71 * invalid. Callers should check for an empty error string (indicating
c@60 72 * success) before using the returned value.
c@6 73 */
c@60 74
c@60 75 //!!! todo: convert pmapper to err style
c@60 76
c@5 77 class VampJson
c@5 78 {
c@5 79 public:
c@45 80 /** Serialisation format for arrays of floats (process input and
c@66 81 * feature values). Wherever such an array appears, it may
c@66 82 * alternatively be replaced by a single string containing a
c@66 83 * base-64 encoding of the IEEE float buffer. When parsing, if a
c@66 84 * string is found instead of an array in this case, it will be
c@66 85 * interpreted as a base-64 encoded buffer. Only array or base-64
c@66 86 * encoding may be provided, not both.
c@45 87 */
c@44 88 enum class BufferSerialisation {
c@45 89
c@45 90 /** Default JSON serialisation of values in array form. This
c@45 91 * is relatively slow to parse and serialise, and can take a
c@45 92 * lot of space.
c@45 93 */
c@66 94 Array,
c@45 95
c@66 96 /** Base64-encoded string of the raw data as packed
c@66 97 * little-endian IEEE 32-bit floats. Faster and more compact
c@66 98 * than the text encoding but more complicated to
c@66 99 * provide. Note that Base64 serialisations produced by this
c@45 100 * library do not including padding characters and so are not
c@45 101 * necessarily multiples of 4 characters long. You will need
c@45 102 * to pad them yourself if concatenating them or supplying to
c@45 103 * a consumer that expects padding.
c@45 104 */
c@45 105 Base64
c@44 106 };
c@44 107
c@60 108 static bool failed(const std::string &err) {
c@60 109 return err != "";
c@60 110 }
c@5 111
c@5 112 template <typename T>
c@5 113 static json11::Json
c@5 114 fromBasicDescriptor(const T &t) {
c@5 115 return json11::Json::object {
c@5 116 { "identifier", t.identifier },
c@5 117 { "name", t.name },
c@5 118 { "description", t.description }
c@5 119 };
c@5 120 }
c@5 121
c@5 122 template <typename T>
c@5 123 static void
c@60 124 toBasicDescriptor(json11::Json j, T &t, std::string &err) {
c@5 125 if (!j.is_object()) {
c@60 126 err = "object expected for basic descriptor content";
c@60 127 return;
c@5 128 }
c@5 129 if (!j["identifier"].is_string()) {
c@60 130 err = "string expected for identifier";
c@60 131 return;
c@5 132 }
c@5 133 t.identifier = j["identifier"].string_value();
c@5 134 t.name = j["name"].string_value();
c@5 135 t.description = j["description"].string_value();
c@5 136 }
c@5 137
c@5 138 template <typename T>
c@5 139 static json11::Json
c@5 140 fromValueExtents(const T &t) {
c@5 141 return json11::Json::object {
c@5 142 { "min", t.minValue },
c@5 143 { "max", t.maxValue }
c@5 144 };
c@5 145 }
c@5 146
c@5 147 template <typename T>
c@5 148 static bool
c@60 149 toValueExtents(json11::Json j, T &t, std::string &err) {
c@5 150 if (j["extents"].is_null()) {
c@5 151 return false;
c@5 152 } else if (j["extents"].is_object()) {
c@5 153 if (j["extents"]["min"].is_number() &&
c@5 154 j["extents"]["max"].is_number()) {
c@5 155 t.minValue = j["extents"]["min"].number_value();
c@5 156 t.maxValue = j["extents"]["max"].number_value();
c@5 157 return true;
c@5 158 } else {
c@60 159 err = "numbers expected for min and max";
c@60 160 return false;
c@5 161 }
c@5 162 } else {
c@60 163 err = "object expected for extents (if present)";
c@60 164 return false;
c@5 165 }
c@5 166 }
c@5 167
c@5 168 static json11::Json
c@5 169 fromRealTime(const Vamp::RealTime &r) {
c@5 170 return json11::Json::object {
c@5 171 { "s", r.sec },
c@5 172 { "n", r.nsec }
c@5 173 };
c@5 174 }
c@5 175
c@5 176 static Vamp::RealTime
c@60 177 toRealTime(json11::Json j, std::string &err) {
c@5 178 json11::Json sec = j["s"];
c@5 179 json11::Json nsec = j["n"];
c@5 180 if (!sec.is_number() || !nsec.is_number()) {
c@60 181 err = "invalid Vamp::RealTime object " + j.dump();
c@60 182 return {};
c@5 183 }
c@5 184 return Vamp::RealTime(sec.int_value(), nsec.int_value());
c@5 185 }
c@5 186
c@5 187 static std::string
c@5 188 fromSampleType(Vamp::Plugin::OutputDescriptor::SampleType type) {
c@5 189 switch (type) {
c@5 190 case Vamp::Plugin::OutputDescriptor::OneSamplePerStep:
c@5 191 return "OneSamplePerStep";
c@5 192 case Vamp::Plugin::OutputDescriptor::FixedSampleRate:
c@5 193 return "FixedSampleRate";
c@5 194 case Vamp::Plugin::OutputDescriptor::VariableSampleRate:
c@5 195 return "VariableSampleRate";
c@5 196 }
c@5 197 return "";
c@5 198 }
c@5 199
c@5 200 static Vamp::Plugin::OutputDescriptor::SampleType
c@60 201 toSampleType(std::string text, std::string &err) {
c@5 202 if (text == "OneSamplePerStep") {
c@5 203 return Vamp::Plugin::OutputDescriptor::OneSamplePerStep;
c@5 204 } else if (text == "FixedSampleRate") {
c@5 205 return Vamp::Plugin::OutputDescriptor::FixedSampleRate;
c@5 206 } else if (text == "VariableSampleRate") {
c@5 207 return Vamp::Plugin::OutputDescriptor::VariableSampleRate;
c@5 208 } else {
c@60 209 err = "invalid sample type string: " + text;
c@60 210 return Vamp::Plugin::OutputDescriptor::OneSamplePerStep;
c@5 211 }
c@5 212 }
c@5 213
c@5 214 static json11::Json
c@64 215 fromConfiguredOutputDescriptor(const Vamp::Plugin::OutputDescriptor &desc) {
c@5 216 json11::Json::object jo {
c@5 217 { "unit", desc.unit },
c@5 218 { "sampleType", fromSampleType(desc.sampleType) },
c@5 219 { "sampleRate", desc.sampleRate },
c@5 220 { "hasDuration", desc.hasDuration }
c@5 221 };
c@5 222 if (desc.hasFixedBinCount) {
c@5 223 jo["binCount"] = int(desc.binCount);
c@5 224 jo["binNames"] = json11::Json::array
c@5 225 (desc.binNames.begin(), desc.binNames.end());
c@5 226 }
c@5 227 if (desc.hasKnownExtents) {
c@5 228 jo["extents"] = fromValueExtents(desc);
c@5 229 }
c@5 230 if (desc.isQuantized) {
c@5 231 jo["quantizeStep"] = desc.quantizeStep;
c@5 232 }
c@5 233 return json11::Json(jo);
c@5 234 }
c@12 235
c@64 236 static json11::Json
c@64 237 fromOutputDescriptor(const Vamp::Plugin::OutputDescriptor &desc) {
c@64 238 json11::Json::object jo {
c@64 239 { "basic", fromBasicDescriptor(desc) },
c@64 240 { "configured", fromConfiguredOutputDescriptor(desc) }
c@64 241 };
c@64 242 return json11::Json(jo);
c@64 243 }
c@64 244
c@5 245 static Vamp::Plugin::OutputDescriptor
c@65 246 toConfiguredOutputDescriptor(json11::Json j, std::string &err) {
c@5 247
c@5 248 Vamp::Plugin::OutputDescriptor od;
c@5 249 if (!j.is_object()) {
c@60 250 err = "object expected for output descriptor";
c@60 251 return {};
c@5 252 }
c@5 253
c@5 254 od.unit = j["unit"].string_value();
c@5 255
c@60 256 od.sampleType = toSampleType(j["sampleType"].string_value(), err);
c@60 257 if (failed(err)) return {};
c@5 258
c@5 259 if (!j["sampleRate"].is_number()) {
c@60 260 err = "number expected for sample rate";
c@60 261 return {};
c@5 262 }
c@5 263 od.sampleRate = j["sampleRate"].number_value();
c@5 264 od.hasDuration = j["hasDuration"].bool_value();
c@5 265
c@5 266 if (j["binCount"].is_number() && j["binCount"].int_value() > 0) {
c@5 267 od.hasFixedBinCount = true;
c@5 268 od.binCount = j["binCount"].int_value();
c@5 269 for (auto &n: j["binNames"].array_items()) {
c@5 270 if (!n.is_string()) {
c@60 271 err = "string expected for bin name";
c@60 272 return {};
c@5 273 }
c@5 274 od.binNames.push_back(n.string_value());
c@5 275 }
c@5 276 } else {
c@5 277 od.hasFixedBinCount = false;
c@5 278 }
c@5 279
c@60 280 bool extentsPresent = toValueExtents(j, od, err);
c@60 281 if (failed(err)) return {};
c@60 282
c@5 283 od.hasKnownExtents = extentsPresent;
c@5 284
c@5 285 if (j["quantizeStep"].is_number()) {
c@5 286 od.isQuantized = true;
c@5 287 od.quantizeStep = j["quantizeStep"].number_value();
c@5 288 } else {
c@5 289 od.isQuantized = false;
c@5 290 }
c@5 291
c@5 292 return od;
c@5 293 }
c@64 294
c@64 295 static Vamp::Plugin::OutputDescriptor
c@65 296 toOutputDescriptor(json11::Json j, std::string &err) {
c@64 297
c@64 298 Vamp::Plugin::OutputDescriptor od;
c@64 299 if (!j.is_object()) {
c@65 300 err = "object expected for output descriptor";
c@65 301 return {};
c@64 302 }
c@64 303
c@65 304 od = toConfiguredOutputDescriptor(j, err);
c@65 305 if (failed(err)) return {};
c@64 306
c@65 307 toBasicDescriptor(j["basic"], od, err);
c@65 308 if (failed(err)) return {};
c@64 309
c@64 310 return od;
c@64 311 }
c@5 312
c@5 313 static json11::Json
c@5 314 fromParameterDescriptor(const Vamp::PluginBase::ParameterDescriptor &desc) {
c@5 315
c@5 316 json11::Json::object jo {
c@5 317 { "basic", fromBasicDescriptor(desc) },
c@5 318 { "unit", desc.unit },
c@5 319 { "extents", fromValueExtents(desc) },
c@5 320 { "defaultValue", desc.defaultValue },
c@5 321 { "valueNames", json11::Json::array
c@5 322 (desc.valueNames.begin(), desc.valueNames.end()) }
c@5 323 };
c@5 324 if (desc.isQuantized) {
c@5 325 jo["quantizeStep"] = desc.quantizeStep;
c@5 326 }
c@5 327 return json11::Json(jo);
c@5 328 }
c@5 329
c@5 330 static Vamp::PluginBase::ParameterDescriptor
c@60 331 toParameterDescriptor(json11::Json j, std::string &err) {
c@5 332
c@5 333 Vamp::PluginBase::ParameterDescriptor pd;
c@5 334 if (!j.is_object()) {
c@60 335 err = "object expected for parameter descriptor";
c@60 336 return {};
c@5 337 }
c@5 338
c@60 339 toBasicDescriptor(j["basic"], pd, err);
c@60 340 if (failed(err)) return {};
c@5 341
c@5 342 pd.unit = j["unit"].string_value();
c@5 343
c@60 344 bool extentsPresent = toValueExtents(j, pd, err);
c@60 345 if (failed(err)) return {};
c@5 346 if (!extentsPresent) {
c@60 347 err = "extents must be present in parameter descriptor";
c@60 348 return {};
c@5 349 }
c@5 350
c@5 351 if (!j["defaultValue"].is_number()) {
c@60 352 err = "number expected for default value";
c@60 353 return {};
c@5 354 }
c@5 355
c@5 356 pd.defaultValue = j["defaultValue"].number_value();
c@5 357
c@5 358 pd.valueNames.clear();
c@5 359 for (auto &n: j["valueNames"].array_items()) {
c@5 360 if (!n.is_string()) {
c@60 361 err = "string expected for value name";
c@60 362 return {};
c@5 363 }
c@5 364 pd.valueNames.push_back(n.string_value());
c@5 365 }
c@5 366
c@5 367 if (j["quantizeStep"].is_number()) {
c@5 368 pd.isQuantized = true;
c@5 369 pd.quantizeStep = j["quantizeStep"].number_value();
c@5 370 } else {
c@5 371 pd.isQuantized = false;
c@5 372 }
c@5 373
c@5 374 return pd;
c@5 375 }
c@5 376
c@5 377 static std::string
c@5 378 fromFloatBuffer(const float *buffer, size_t nfloats) {
c@5 379 // must use char pointers, otherwise the converter will only
c@5 380 // encode every 4th byte (as it will count up in float* steps)
c@5 381 const char *start = reinterpret_cast<const char *>(buffer);
c@5 382 const char *end = reinterpret_cast<const char *>(buffer + nfloats);
c@5 383 std::string encoded;
c@5 384 bn::encode_b64(start, end, back_inserter(encoded));
c@5 385 return encoded;
c@5 386 }
c@5 387
c@5 388 static std::vector<float>
c@60 389 toFloatBuffer(std::string encoded, std::string & /* err */) {
c@5 390 std::string decoded;
c@5 391 bn::decode_b64(encoded.begin(), encoded.end(), back_inserter(decoded));
c@5 392 const float *buffer = reinterpret_cast<const float *>(decoded.c_str());
c@5 393 size_t n = decoded.size() / sizeof(float);
c@47 394 return std::vector<float>(buffer, buffer + n);
c@5 395 }
c@5 396
c@5 397 static json11::Json
c@44 398 fromFeature(const Vamp::Plugin::Feature &f,
c@44 399 BufferSerialisation serialisation) {
c@5 400
c@5 401 json11::Json::object jo;
c@5 402 if (f.values.size() > 0) {
c@66 403 if (serialisation == BufferSerialisation::Array) {
c@66 404 jo["featureValues"] = json11::Json::array(f.values.begin(),
c@66 405 f.values.end());
c@35 406 } else {
c@66 407 jo["featureValues"] = fromFloatBuffer(f.values.data(),
c@66 408 f.values.size());
c@35 409 }
c@5 410 }
c@5 411 if (f.label != "") {
c@5 412 jo["label"] = f.label;
c@5 413 }
c@5 414 if (f.hasTimestamp) {
c@5 415 jo["timestamp"] = fromRealTime(f.timestamp);
c@5 416 }
c@5 417 if (f.hasDuration) {
c@5 418 jo["duration"] = fromRealTime(f.duration);
c@5 419 }
c@5 420 return json11::Json(jo);
c@5 421 }
c@5 422
c@5 423 static Vamp::Plugin::Feature
c@60 424 toFeature(json11::Json j, BufferSerialisation &serialisation, std::string &err) {
c@5 425
c@5 426 Vamp::Plugin::Feature f;
c@5 427 if (!j.is_object()) {
c@60 428 err = "object expected for feature";
c@60 429 return {};
c@5 430 }
c@5 431 if (j["timestamp"].is_object()) {
c@60 432 f.timestamp = toRealTime(j["timestamp"], err);
c@60 433 if (failed(err)) return {};
c@5 434 f.hasTimestamp = true;
c@5 435 }
c@5 436 if (j["duration"].is_object()) {
c@60 437 f.duration = toRealTime(j["duration"], err);
c@60 438 if (failed(err)) return {};
c@5 439 f.hasDuration = true;
c@5 440 }
c@66 441 if (j["featureValues"].is_string()) {
c@66 442 f.values = toFloatBuffer(j["featureValues"].string_value(), err);
c@60 443 if (failed(err)) return {};
c@44 444 serialisation = BufferSerialisation::Base64;
c@66 445 } else if (j["featureValues"].is_array()) {
c@66 446 for (auto v : j["featureValues"].array_items()) {
c@5 447 f.values.push_back(v.number_value());
c@5 448 }
c@66 449 serialisation = BufferSerialisation::Array;
c@5 450 }
c@5 451 f.label = j["label"].string_value();
c@5 452 return f;
c@5 453 }
c@5 454
c@5 455 static json11::Json
c@44 456 fromFeatureSet(const Vamp::Plugin::FeatureSet &fs,
c@49 457 const PluginOutputIdMapper &omapper,
c@44 458 BufferSerialisation serialisation) {
c@5 459
c@5 460 json11::Json::object jo;
c@5 461 for (const auto &fsi : fs) {
c@5 462 std::vector<json11::Json> fj;
c@5 463 for (const Vamp::Plugin::Feature &f: fsi.second) {
c@44 464 fj.push_back(fromFeature(f, serialisation));
c@5 465 }
c@49 466 jo[omapper.indexToId(fsi.first)] = fj;
c@5 467 }
c@5 468 return json11::Json(jo);
c@5 469 }
c@5 470
c@5 471 static Vamp::Plugin::FeatureList
c@44 472 toFeatureList(json11::Json j,
c@60 473 BufferSerialisation &serialisation, std::string &err) {
c@5 474
c@5 475 Vamp::Plugin::FeatureList fl;
c@5 476 if (!j.is_array()) {
c@60 477 err = "array expected for feature list";
c@60 478 return {};
c@5 479 }
c@5 480 for (const json11::Json &fj : j.array_items()) {
c@60 481 fl.push_back(toFeature(fj, serialisation, err));
c@60 482 if (failed(err)) return {};
c@5 483 }
c@5 484 return fl;
c@5 485 }
c@5 486
c@5 487 static Vamp::Plugin::FeatureSet
c@49 488 toFeatureSet(json11::Json j,
c@49 489 const PluginOutputIdMapper &omapper,
c@60 490 BufferSerialisation &serialisation,
c@60 491 std::string &err) {
c@5 492
c@5 493 Vamp::Plugin::FeatureSet fs;
c@5 494 if (!j.is_object()) {
c@60 495 err = "object expected for feature set";
c@60 496 return {};
c@5 497 }
c@5 498 for (auto &entry : j.object_items()) {
c@49 499 int n = omapper.idToIndex(entry.first);
c@49 500 if (fs.find(n) != fs.end()) {
c@60 501 err = "duplicate numerical index for output";
c@60 502 return {};
c@5 503 }
c@60 504 fs[n] = toFeatureList(entry.second, serialisation, err);
c@60 505 if (failed(err)) return {};
c@5 506 }
c@5 507 return fs;
c@5 508 }
c@5 509
c@5 510 static std::string
c@5 511 fromInputDomain(Vamp::Plugin::InputDomain domain) {
c@5 512
c@5 513 switch (domain) {
c@5 514 case Vamp::Plugin::TimeDomain:
c@5 515 return "TimeDomain";
c@5 516 case Vamp::Plugin::FrequencyDomain:
c@5 517 return "FrequencyDomain";
c@5 518 }
c@5 519 return "";
c@5 520 }
c@5 521
c@5 522 static Vamp::Plugin::InputDomain
c@60 523 toInputDomain(std::string text, std::string &err) {
c@5 524
c@5 525 if (text == "TimeDomain") {
c@5 526 return Vamp::Plugin::TimeDomain;
c@5 527 } else if (text == "FrequencyDomain") {
c@5 528 return Vamp::Plugin::FrequencyDomain;
c@5 529 } else {
c@60 530 err = "invalid input domain string: " + text;
c@60 531 return {};
c@5 532 }
c@5 533 }
c@5 534
c@5 535 static json11::Json
c@5 536 fromPluginStaticData(const Vamp::HostExt::PluginStaticData &d) {
c@5 537
c@5 538 json11::Json::object jo;
c@5 539 jo["pluginKey"] = d.pluginKey;
c@5 540 jo["basic"] = fromBasicDescriptor(d.basic);
c@5 541 jo["maker"] = d.maker;
c@5 542 jo["copyright"] = d.copyright;
c@5 543 jo["pluginVersion"] = d.pluginVersion;
c@5 544
c@5 545 json11::Json::array cat;
c@5 546 for (const std::string &c: d.category) cat.push_back(c);
c@5 547 jo["category"] = cat;
c@5 548
c@5 549 jo["minChannelCount"] = d.minChannelCount;
c@5 550 jo["maxChannelCount"] = d.maxChannelCount;
c@5 551
c@5 552 json11::Json::array params;
c@5 553 Vamp::PluginBase::ParameterList vparams = d.parameters;
c@5 554 for (auto &p: vparams) params.push_back(fromParameterDescriptor(p));
c@5 555 jo["parameters"] = params;
c@5 556
c@5 557 json11::Json::array progs;
c@5 558 Vamp::PluginBase::ProgramList vprogs = d.programs;
c@5 559 for (auto &p: vprogs) progs.push_back(p);
c@5 560 jo["programs"] = progs;
c@5 561
c@5 562 jo["inputDomain"] = fromInputDomain(d.inputDomain);
c@5 563
c@5 564 json11::Json::array outinfo;
c@5 565 auto vouts = d.basicOutputInfo;
c@5 566 for (auto &o: vouts) outinfo.push_back(fromBasicDescriptor(o));
c@5 567 jo["basicOutputInfo"] = outinfo;
c@5 568
c@5 569 return json11::Json(jo);
c@5 570 }
c@5 571
c@5 572 static Vamp::HostExt::PluginStaticData
c@60 573 toPluginStaticData(json11::Json j, std::string &err) {
c@5 574
c@5 575 if (!j.has_shape({
c@5 576 { "pluginKey", json11::Json::STRING },
c@5 577 { "pluginVersion", json11::Json::NUMBER },
c@5 578 { "minChannelCount", json11::Json::NUMBER },
c@5 579 { "maxChannelCount", json11::Json::NUMBER },
c@5 580 { "inputDomain", json11::Json::STRING }}, err)) {
c@60 581
c@60 582 err = "malformed plugin static data: " + err;
c@60 583
c@60 584 } else if (!j["basicOutputInfo"].is_array()) {
c@60 585
c@60 586 err = "array expected for basic output info";
c@60 587
c@60 588 } else if (!j["maker"].is_null() &&
c@60 589 !j["maker"].is_string()) {
c@60 590
c@60 591 err = "string expected for maker";
c@60 592
c@60 593 } else if (!j["copyright"].is_null() &&
c@60 594 !j["copyright"].is_string()) {
c@60 595 err = "string expected for copyright";
c@60 596
c@60 597 } else if (!j["category"].is_null() &&
c@60 598 !j["category"].is_array()) {
c@60 599
c@60 600 err = "array expected for category";
c@60 601
c@60 602 } else if (!j["parameters"].is_null() &&
c@60 603 !j["parameters"].is_array()) {
c@60 604
c@60 605 err = "array expected for parameters";
c@60 606
c@60 607 } else if (!j["programs"].is_null() &&
c@60 608 !j["programs"].is_array()) {
c@60 609
c@60 610 err = "array expected for programs";
c@60 611
c@60 612 } else if (!j["inputDomain"].is_null() &&
c@60 613 !j["inputDomain"].is_string()) {
c@60 614
c@60 615 err = "string expected for inputDomain";
c@60 616
c@60 617 } else if (!j["basicOutputInfo"].is_null() &&
c@60 618 !j["basicOutputInfo"].is_array()) {
c@60 619
c@60 620 err = "array expected for basicOutputInfo";
c@60 621
c@60 622 } else {
c@60 623
c@60 624 Vamp::HostExt::PluginStaticData psd;
c@60 625
c@60 626 psd.pluginKey = j["pluginKey"].string_value();
c@60 627
c@60 628 toBasicDescriptor(j["basic"], psd.basic, err);
c@60 629 if (failed(err)) return {};
c@60 630
c@60 631 psd.maker = j["maker"].string_value();
c@60 632 psd.copyright = j["copyright"].string_value();
c@60 633 psd.pluginVersion = j["pluginVersion"].int_value();
c@60 634
c@60 635 for (const auto &c : j["category"].array_items()) {
c@60 636 if (!c.is_string()) {
c@60 637 err = "strings expected in category array";
c@60 638 return {};
c@60 639 }
c@60 640 psd.category.push_back(c.string_value());
c@60 641 }
c@60 642
c@60 643 psd.minChannelCount = j["minChannelCount"].int_value();
c@60 644 psd.maxChannelCount = j["maxChannelCount"].int_value();
c@60 645
c@60 646 for (const auto &p : j["parameters"].array_items()) {
c@60 647 auto pd = toParameterDescriptor(p, err);
c@60 648 if (failed(err)) return {};
c@60 649 psd.parameters.push_back(pd);
c@60 650 }
c@60 651
c@60 652 for (const auto &p : j["programs"].array_items()) {
c@60 653 if (!p.is_string()) {
c@60 654 err = "strings expected in programs array";
c@60 655 return {};
c@60 656 }
c@60 657 psd.programs.push_back(p.string_value());
c@60 658 }
c@60 659
c@60 660 psd.inputDomain = toInputDomain(j["inputDomain"].string_value(), err);
c@60 661 if (failed(err)) return {};
c@60 662
c@60 663 for (const auto &bo : j["basicOutputInfo"].array_items()) {
c@60 664 Vamp::HostExt::PluginStaticData::Basic b;
c@60 665 toBasicDescriptor(bo, b, err);
c@60 666 if (failed(err)) return {};
c@60 667 psd.basicOutputInfo.push_back(b);
c@60 668 }
c@60 669
c@60 670 return psd;
c@5 671 }
c@5 672
c@60 673 // fallthrough error case
c@60 674 return {};
c@5 675 }
c@5 676
c@5 677 static json11::Json
c@5 678 fromPluginConfiguration(const Vamp::HostExt::PluginConfiguration &c) {
c@5 679
c@5 680 json11::Json::object jo;
c@5 681
c@5 682 json11::Json::object paramValues;
c@5 683 for (auto &vp: c.parameterValues) {
c@5 684 paramValues[vp.first] = vp.second;
c@5 685 }
c@5 686 jo["parameterValues"] = paramValues;
c@5 687
c@5 688 if (c.currentProgram != "") {
c@5 689 jo["currentProgram"] = c.currentProgram;
c@5 690 }
c@5 691
c@5 692 jo["channelCount"] = c.channelCount;
c@5 693 jo["stepSize"] = c.stepSize;
c@5 694 jo["blockSize"] = c.blockSize;
c@5 695
c@5 696 return json11::Json(jo);
c@5 697 }
c@5 698
c@5 699 static Vamp::HostExt::PluginConfiguration
c@60 700 toPluginConfiguration(json11::Json j, std::string &err) {
c@5 701
c@5 702 if (!j.has_shape({
c@5 703 { "channelCount", json11::Json::NUMBER },
c@5 704 { "stepSize", json11::Json::NUMBER },
c@5 705 { "blockSize", json11::Json::NUMBER } }, err)) {
c@60 706 err = "malformed plugin configuration: " + err;
c@60 707 return {};
c@5 708 }
c@5 709
c@5 710 if (!j["parameterValues"].is_null() &&
c@5 711 !j["parameterValues"].is_object()) {
c@60 712 err = "object expected for parameter values";
c@60 713 return {};
c@5 714 }
c@5 715
c@5 716 for (auto &pv : j["parameterValues"].object_items()) {
c@5 717 if (!pv.second.is_number()) {
c@60 718 err = "number expected for parameter value";
c@60 719 return {};
c@5 720 }
c@5 721 }
c@5 722
c@5 723 if (!j["currentProgram"].is_null() &&
c@5 724 !j["currentProgram"].is_string()) {
c@60 725 err = "string expected for program name";
c@60 726 return {};
c@5 727 }
c@5 728
c@5 729 Vamp::HostExt::PluginConfiguration config;
c@5 730
c@5 731 config.channelCount = j["channelCount"].number_value();
c@5 732 config.stepSize = j["stepSize"].number_value();
c@5 733 config.blockSize = j["blockSize"].number_value();
c@5 734
c@5 735 for (auto &pv : j["parameterValues"].object_items()) {
c@5 736 config.parameterValues[pv.first] = pv.second.number_value();
c@5 737 }
c@5 738
c@5 739 if (j["currentProgram"].is_string()) {
c@5 740 config.currentProgram = j["currentProgram"].string_value();
c@5 741 }
c@5 742
c@5 743 return config;
c@5 744 }
c@5 745
c@5 746 static json11::Json
c@5 747 fromAdapterFlags(int flags) {
c@5 748
c@5 749 json11::Json::array arr;
c@5 750
c@5 751 if (flags & Vamp::HostExt::PluginLoader::ADAPT_INPUT_DOMAIN) {
c@5 752 arr.push_back("AdaptInputDomain");
c@5 753 }
c@5 754 if (flags & Vamp::HostExt::PluginLoader::ADAPT_CHANNEL_COUNT) {
c@5 755 arr.push_back("AdaptChannelCount");
c@5 756 }
c@5 757 if (flags & Vamp::HostExt::PluginLoader::ADAPT_BUFFER_SIZE) {
c@5 758 arr.push_back("AdaptBufferSize");
c@5 759 }
c@5 760
c@5 761 return json11::Json(arr);
c@5 762 }
c@5 763
c@5 764 static Vamp::HostExt::PluginLoader::AdapterFlags
c@60 765 toAdapterFlags(json11::Json j, std::string &err) {
c@60 766
c@60 767 int flags = 0x0;
c@5 768
c@5 769 if (!j.is_array()) {
c@5 770
c@60 771 err = "array expected for adapter flags";
c@60 772
c@60 773 } else {
c@60 774
c@60 775 for (auto &jj: j.array_items()) {
c@60 776 if (!jj.is_string()) {
c@60 777 err = "string expected for adapter flag";
c@60 778 break;
c@60 779 }
c@60 780 std::string text = jj.string_value();
c@60 781 if (text == "AdaptInputDomain") {
c@60 782 flags |= Vamp::HostExt::PluginLoader::ADAPT_INPUT_DOMAIN;
c@60 783 } else if (text == "AdaptChannelCount") {
c@60 784 flags |= Vamp::HostExt::PluginLoader::ADAPT_CHANNEL_COUNT;
c@60 785 } else if (text == "AdaptBufferSize") {
c@60 786 flags |= Vamp::HostExt::PluginLoader::ADAPT_BUFFER_SIZE;
c@60 787 } else if (text == "AdaptAllSafe") {
c@60 788 flags |= Vamp::HostExt::PluginLoader::ADAPT_ALL_SAFE;
c@60 789 } else if (text == "AdaptAll") {
c@60 790 flags |= Vamp::HostExt::PluginLoader::ADAPT_ALL;
c@60 791 } else {
c@60 792 err = "invalid adapter flag string: " + text;
c@60 793 break;
c@60 794 }
c@5 795 }
c@5 796 }
c@5 797
c@5 798 return Vamp::HostExt::PluginLoader::AdapterFlags(flags);
c@5 799 }
c@5 800
c@5 801 static json11::Json
c@17 802 fromLoadRequest(const Vamp::HostExt::LoadRequest &req) {
c@5 803
c@5 804 json11::Json::object jo;
c@5 805 jo["pluginKey"] = req.pluginKey;
c@5 806 jo["inputSampleRate"] = req.inputSampleRate;
c@5 807 jo["adapterFlags"] = fromAdapterFlags(req.adapterFlags);
c@5 808 return json11::Json(jo);
c@5 809 }
c@5 810
c@5 811 static Vamp::HostExt::LoadRequest
c@60 812 toLoadRequest(json11::Json j, std::string &err) {
c@5 813
c@5 814 if (!j.has_shape({
c@5 815 { "pluginKey", json11::Json::STRING },
c@32 816 { "inputSampleRate", json11::Json::NUMBER } }, err)) {
c@60 817 err = "malformed load request: " + err;
c@60 818 return {};
c@5 819 }
c@5 820
c@5 821 Vamp::HostExt::LoadRequest req;
c@5 822 req.pluginKey = j["pluginKey"].string_value();
c@5 823 req.inputSampleRate = j["inputSampleRate"].number_value();
c@32 824 if (!j["adapterFlags"].is_null()) {
c@60 825 req.adapterFlags = toAdapterFlags(j["adapterFlags"], err);
c@60 826 if (failed(err)) return {};
c@32 827 }
c@5 828 return req;
c@5 829 }
c@10 830
c@10 831 static json11::Json
c@17 832 fromLoadResponse(const Vamp::HostExt::LoadResponse &resp,
c@49 833 const PluginHandleMapper &pmapper) {
c@10 834
c@10 835 json11::Json::object jo;
c@49 836 jo["pluginHandle"] = double(pmapper.pluginToHandle(resp.plugin));
c@10 837 jo["staticData"] = fromPluginStaticData(resp.staticData);
c@10 838 jo["defaultConfiguration"] =
c@10 839 fromPluginConfiguration(resp.defaultConfiguration);
c@10 840 return json11::Json(jo);
c@10 841 }
c@10 842
c@10 843 static Vamp::HostExt::LoadResponse
c@10 844 toLoadResponse(json11::Json j,
c@60 845 const PluginHandleMapper &pmapper, std::string &err) {
c@10 846
c@10 847 if (!j.has_shape({
c@10 848 { "pluginHandle", json11::Json::NUMBER },
c@10 849 { "staticData", json11::Json::OBJECT },
c@10 850 { "defaultConfiguration", json11::Json::OBJECT } }, err)) {
c@60 851 err = "malformed load response: " + err;
c@60 852 return {};
c@10 853 }
c@10 854
c@10 855 Vamp::HostExt::LoadResponse resp;
c@49 856 resp.plugin = pmapper.handleToPlugin(j["pluginHandle"].int_value());
c@60 857 resp.staticData = toPluginStaticData(j["staticData"], err);
c@60 858 if (failed(err)) return {};
c@60 859 resp.defaultConfiguration = toPluginConfiguration(j["defaultConfiguration"],
c@60 860 err);
c@60 861 if (failed(err)) return {};
c@10 862 return resp;
c@10 863 }
c@12 864
c@12 865 static json11::Json
c@13 866 fromConfigurationRequest(const Vamp::HostExt::ConfigurationRequest &cr,
c@49 867 const PluginHandleMapper &pmapper) {
c@13 868
c@13 869 json11::Json::object jo;
c@13 870
c@49 871 jo["pluginHandle"] = pmapper.pluginToHandle(cr.plugin);
c@13 872 jo["configuration"] = fromPluginConfiguration(cr.configuration);
c@13 873
c@13 874 return json11::Json(jo);
c@13 875 }
c@13 876
c@13 877 static Vamp::HostExt::ConfigurationRequest
c@13 878 toConfigurationRequest(json11::Json j,
c@60 879 const PluginHandleMapper &pmapper, std::string &err) {
c@13 880
c@13 881 if (!j.has_shape({
c@13 882 { "pluginHandle", json11::Json::NUMBER },
c@13 883 { "configuration", json11::Json::OBJECT } }, err)) {
c@60 884 err = "malformed configuration request: " + err;
c@60 885 return {};
c@13 886 }
c@13 887
c@13 888 Vamp::HostExt::ConfigurationRequest cr;
c@49 889 cr.plugin = pmapper.handleToPlugin(j["pluginHandle"].int_value());
c@60 890 cr.configuration = toPluginConfiguration(j["configuration"], err);
c@60 891 if (failed(err)) return {};
c@13 892 return cr;
c@13 893 }
c@13 894
c@13 895 static json11::Json
c@55 896 fromConfigurationResponse(const Vamp::HostExt::ConfigurationResponse &cr,
c@55 897 const PluginHandleMapper &pmapper) {
c@12 898
c@13 899 json11::Json::object jo;
c@55 900
c@55 901 jo["pluginHandle"] = pmapper.pluginToHandle(cr.plugin);
c@12 902
c@12 903 json11::Json::array outs;
c@12 904 for (auto &d: cr.outputs) {
c@12 905 outs.push_back(fromOutputDescriptor(d));
c@12 906 }
c@13 907 jo["outputList"] = outs;
c@12 908
c@13 909 return json11::Json(jo);
c@12 910 }
c@12 911
c@13 912 static Vamp::HostExt::ConfigurationResponse
c@55 913 toConfigurationResponse(json11::Json j,
c@60 914 const PluginHandleMapper &pmapper, std::string &err) {
c@13 915
c@12 916 Vamp::HostExt::ConfigurationResponse cr;
c@12 917
c@55 918 cr.plugin = pmapper.handleToPlugin(j["pluginHandle"].int_value());
c@55 919
c@12 920 if (!j["outputList"].is_array()) {
c@60 921 err = "array expected for output list";
c@60 922 return {};
c@12 923 }
c@12 924
c@12 925 for (const auto &o: j["outputList"].array_items()) {
c@60 926 cr.outputs.push_back(toOutputDescriptor(o, err));
c@60 927 if (failed(err)) return {};
c@12 928 }
c@12 929
c@12 930 return cr;
c@12 931 }
c@16 932
c@16 933 static json11::Json
c@16 934 fromProcessRequest(const Vamp::HostExt::ProcessRequest &r,
c@49 935 const PluginHandleMapper &pmapper,
c@44 936 BufferSerialisation serialisation) {
c@16 937
c@16 938 json11::Json::object jo;
c@49 939 jo["pluginHandle"] = pmapper.pluginToHandle(r.plugin);
c@16 940
c@16 941 json11::Json::object io;
c@16 942 io["timestamp"] = fromRealTime(r.timestamp);
c@16 943
c@16 944 json11::Json::array chans;
c@16 945 for (size_t i = 0; i < r.inputBuffers.size(); ++i) {
c@66 946 if (serialisation == BufferSerialisation::Array) {
c@66 947 chans.push_back(json11::Json::array(r.inputBuffers[i].begin(),
c@66 948 r.inputBuffers[i].end()));
c@44 949 } else {
c@66 950 chans.push_back(fromFloatBuffer(r.inputBuffers[i].data(),
c@66 951 r.inputBuffers[i].size()));
c@44 952 }
c@16 953 }
c@16 954 io["inputBuffers"] = chans;
c@16 955
c@16 956 jo["processInput"] = io;
c@16 957 return json11::Json(jo);
c@16 958 }
c@17 959
c@17 960 static Vamp::HostExt::ProcessRequest
c@44 961 toProcessRequest(json11::Json j,
c@49 962 const PluginHandleMapper &pmapper,
c@60 963 BufferSerialisation &serialisation, std::string &err) {
c@17 964
c@17 965 if (!j.has_shape({
c@17 966 { "pluginHandle", json11::Json::NUMBER },
c@17 967 { "processInput", json11::Json::OBJECT } }, err)) {
c@60 968 err = "malformed process request: " + err;
c@60 969 return {};
c@17 970 }
c@17 971
c@17 972 auto input = j["processInput"];
c@17 973
c@17 974 if (!input.has_shape({
c@17 975 { "timestamp", json11::Json::OBJECT },
c@17 976 { "inputBuffers", json11::Json::ARRAY } }, err)) {
c@60 977 err = "malformed process request: " + err;
c@60 978 return {};
c@17 979 }
c@17 980
c@17 981 Vamp::HostExt::ProcessRequest r;
c@49 982 r.plugin = pmapper.handleToPlugin(j["pluginHandle"].int_value());
c@17 983
c@60 984 r.timestamp = toRealTime(input["timestamp"], err);
c@60 985 if (failed(err)) return {};
c@17 986
c@66 987 for (const auto &a: input["inputBuffers"].array_items()) {
c@44 988
c@66 989 if (a.is_string()) {
c@66 990 std::vector<float> buf = toFloatBuffer(a.string_value(),
c@60 991 err);
c@60 992 if (failed(err)) return {};
c@44 993 r.inputBuffers.push_back(buf);
c@44 994 serialisation = BufferSerialisation::Base64;
c@44 995
c@66 996 } else if (a.is_array()) {
c@17 997 std::vector<float> buf;
c@66 998 for (auto v : a.array_items()) {
c@17 999 buf.push_back(v.number_value());
c@17 1000 }
c@17 1001 r.inputBuffers.push_back(buf);
c@66 1002 serialisation = BufferSerialisation::Array;
c@44 1003
c@17 1004 } else {
c@66 1005 err = "expected arrays or strings in inputBuffers array";
c@60 1006 return {};
c@17 1007 }
c@17 1008 }
c@17 1009
c@17 1010 return r;
c@17 1011 }
c@17 1012
c@17 1013 static json11::Json
c@17 1014 fromVampRequest_List() {
c@17 1015
c@17 1016 json11::Json::object jo;
c@17 1017 jo["type"] = "list";
c@17 1018 return json11::Json(jo);
c@17 1019 }
c@17 1020
c@17 1021 static json11::Json
c@59 1022 fromVampResponse_List(const Vamp::HostExt::ListResponse &resp) {
c@17 1023
c@17 1024 json11::Json::object jo;
c@24 1025 jo["type"] = "list";
c@59 1026 jo["success"] = true;
c@17 1027
c@17 1028 json11::Json::array arr;
c@64 1029 for (const auto &a: resp.plugins) {
c@17 1030 arr.push_back(fromPluginStaticData(a));
c@17 1031 }
c@24 1032 json11::Json::object po;
c@24 1033 po["plugins"] = arr;
c@24 1034
c@24 1035 jo["content"] = po;
c@17 1036 return json11::Json(jo);
c@17 1037 }
c@17 1038
c@17 1039 static json11::Json
c@17 1040 fromVampRequest_Load(const Vamp::HostExt::LoadRequest &req) {
c@17 1041
c@17 1042 json11::Json::object jo;
c@17 1043 jo["type"] = "load";
c@17 1044 jo["content"] = fromLoadRequest(req);
c@17 1045 return json11::Json(jo);
c@17 1046 }
c@17 1047
c@17 1048 static json11::Json
c@17 1049 fromVampResponse_Load(const Vamp::HostExt::LoadResponse &resp,
c@49 1050 const PluginHandleMapper &pmapper) {
c@17 1051
c@17 1052 json11::Json::object jo;
c@24 1053 jo["type"] = "load";
c@17 1054 jo["success"] = (resp.plugin != 0);
c@17 1055 jo["errorText"] = "";
c@49 1056 jo["content"] = fromLoadResponse(resp, pmapper);
c@17 1057 return json11::Json(jo);
c@17 1058 }
c@17 1059
c@17 1060 static json11::Json
c@17 1061 fromVampRequest_Configure(const Vamp::HostExt::ConfigurationRequest &req,
c@49 1062 const PluginHandleMapper &pmapper) {
c@17 1063
c@17 1064 json11::Json::object jo;
c@17 1065 jo["type"] = "configure";
c@49 1066 jo["content"] = fromConfigurationRequest(req, pmapper);
c@17 1067 return json11::Json(jo);
c@17 1068 }
c@17 1069
c@17 1070 static json11::Json
c@55 1071 fromVampResponse_Configure(const Vamp::HostExt::ConfigurationResponse &resp,
c@55 1072 const PluginHandleMapper &pmapper) {
c@17 1073
c@17 1074 json11::Json::object jo;
c@24 1075 jo["type"] = "configure";
c@17 1076 jo["success"] = (!resp.outputs.empty());
c@17 1077 jo["errorText"] = "";
c@55 1078 jo["content"] = fromConfigurationResponse(resp, pmapper);
c@17 1079 return json11::Json(jo);
c@17 1080 }
c@17 1081
c@17 1082 static json11::Json
c@17 1083 fromVampRequest_Process(const Vamp::HostExt::ProcessRequest &req,
c@49 1084 const PluginHandleMapper &pmapper,
c@44 1085 BufferSerialisation serialisation) {
c@17 1086
c@17 1087 json11::Json::object jo;
c@17 1088 jo["type"] = "process";
c@49 1089 jo["content"] = fromProcessRequest(req, pmapper, serialisation);
c@17 1090 return json11::Json(jo);
c@17 1091 }
c@17 1092
c@17 1093 static json11::Json
c@44 1094 fromVampResponse_Process(const Vamp::HostExt::ProcessResponse &resp,
c@51 1095 const PluginHandleMapper &pmapper,
c@44 1096 BufferSerialisation serialisation) {
c@17 1097
c@17 1098 json11::Json::object jo;
c@24 1099 jo["type"] = "process";
c@17 1100 jo["success"] = true;
c@17 1101 jo["errorText"] = "";
c@52 1102 json11::Json::object po;
c@52 1103 po["pluginHandle"] = pmapper.pluginToHandle(resp.plugin);
c@52 1104 po["features"] = fromFeatureSet(resp.features,
c@57 1105 *pmapper.pluginToOutputIdMapper(resp.plugin),
c@52 1106 serialisation);
c@52 1107 jo["content"] = po;
c@17 1108 return json11::Json(jo);
c@17 1109 }
c@17 1110
c@17 1111 static json11::Json
c@55 1112 fromVampRequest_Finish(const Vamp::HostExt::FinishRequest &req,
c@49 1113 const PluginHandleMapper &pmapper) {
c@17 1114
c@17 1115 json11::Json::object jo;
c@17 1116 jo["type"] = "finish";
c@24 1117 json11::Json::object fo;
c@55 1118 fo["pluginHandle"] = pmapper.pluginToHandle(req.plugin);
c@24 1119 jo["content"] = fo;
c@17 1120 return json11::Json(jo);
c@17 1121 }
c@17 1122
c@17 1123 static json11::Json
c@44 1124 fromVampResponse_Finish(const Vamp::HostExt::ProcessResponse &resp,
c@51 1125 const PluginHandleMapper &pmapper,
c@44 1126 BufferSerialisation serialisation) {
c@17 1127
c@17 1128 json11::Json::object jo;
c@24 1129 jo["type"] = "finish";
c@17 1130 jo["success"] = true;
c@17 1131 jo["errorText"] = "";
c@52 1132 json11::Json::object po;
c@52 1133 po["pluginHandle"] = pmapper.pluginToHandle(resp.plugin);
c@52 1134 po["features"] = fromFeatureSet(resp.features,
c@57 1135 *pmapper.pluginToOutputIdMapper(resp.plugin),
c@52 1136 serialisation);
c@52 1137 jo["content"] = po;
c@17 1138 return json11::Json(jo);
c@17 1139 }
c@24 1140
c@41 1141 static json11::Json
c@52 1142 fromError(std::string errorText, RRType responseType) {
c@41 1143
c@41 1144 json11::Json::object jo;
c@43 1145 std::string type;
c@41 1146
c@43 1147 if (responseType == RRType::List) type = "list";
c@43 1148 else if (responseType == RRType::Load) type = "load";
c@43 1149 else if (responseType == RRType::Configure) type = "configure";
c@43 1150 else if (responseType == RRType::Process) type = "process";
c@43 1151 else if (responseType == RRType::Finish) type = "finish";
c@43 1152 else type = "invalid";
c@41 1153
c@43 1154 jo["type"] = type;
c@41 1155 jo["success"] = false;
c@52 1156 jo["errorText"] = std::string("error in ") + type + " request: " + errorText;
c@41 1157 return json11::Json(jo);
c@41 1158 }
c@41 1159
c@24 1160 private: // go private briefly for a couple of helper functions
c@24 1161
c@24 1162 static void
c@60 1163 checkTypeField(json11::Json j, std::string expected, std::string &err) {
c@24 1164 if (!j["type"].is_string()) {
c@60 1165 err = "string expected for type";
c@60 1166 return;
c@24 1167 }
c@24 1168 if (j["type"].string_value() != expected) {
c@60 1169 err = "expected value \"" + expected + "\" for type";
c@60 1170 return;
c@24 1171 }
c@24 1172 }
c@24 1173
c@24 1174 static bool
c@60 1175 successful(json11::Json j, std::string &err) {
c@24 1176 if (!j["success"].is_bool()) {
c@60 1177 err = "bool expected for success";
c@60 1178 return false;
c@24 1179 }
c@24 1180 return j["success"].bool_value();
c@24 1181 }
c@24 1182
c@24 1183 public:
c@25 1184 static RRType
c@60 1185 getRequestResponseType(json11::Json j, std::string &err) {
c@25 1186
c@25 1187 if (!j["type"].is_string()) {
c@60 1188 err = "string expected for type";
c@60 1189 return RRType::NotValid;
c@25 1190 }
c@25 1191
c@25 1192 std::string type = j["type"].string_value();
c@25 1193
c@25 1194 if (type == "list") return RRType::List;
c@25 1195 else if (type == "load") return RRType::Load;
c@25 1196 else if (type == "configure") return RRType::Configure;
c@25 1197 else if (type == "process") return RRType::Process;
c@25 1198 else if (type == "finish") return RRType::Finish;
c@60 1199 else if (type == "invalid") return RRType::NotValid;
c@25 1200 else {
c@60 1201 err = "unknown or unexpected request/response type \"" + type + "\"";
c@60 1202 return RRType::NotValid;
c@25 1203 }
c@25 1204 }
c@44 1205
c@24 1206 static void
c@60 1207 toVampRequest_List(json11::Json j, std::string &err) {
c@60 1208 checkTypeField(j, "list", err);
c@24 1209 }
c@24 1210
c@56 1211 static Vamp::HostExt::ListResponse
c@60 1212 toVampResponse_List(json11::Json j, std::string &err) {
c@24 1213
c@56 1214 Vamp::HostExt::ListResponse resp;
c@60 1215 if (successful(j, err) && !failed(err)) {
c@24 1216 for (const auto &a: j["content"]["plugins"].array_items()) {
c@65 1217 resp.plugins.push_back(toPluginStaticData(a, err));
c@60 1218 if (failed(err)) return {};
c@24 1219 }
c@24 1220 }
c@60 1221
c@56 1222 return resp;
c@24 1223 }
c@24 1224
c@24 1225 static Vamp::HostExt::LoadRequest
c@60 1226 toVampRequest_Load(json11::Json j, std::string &err) {
c@24 1227
c@60 1228 checkTypeField(j, "load", err);
c@60 1229 if (failed(err)) return {};
c@60 1230 return toLoadRequest(j["content"], err);
c@24 1231 }
c@24 1232
c@24 1233 static Vamp::HostExt::LoadResponse
c@60 1234 toVampResponse_Load(json11::Json j,
c@60 1235 const PluginHandleMapper &pmapper,
c@60 1236 std::string &err) {
c@24 1237
c@24 1238 Vamp::HostExt::LoadResponse resp;
c@60 1239 if (successful(j, err) && !failed(err)) {
c@60 1240 resp = toLoadResponse(j["content"], pmapper, err);
c@24 1241 }
c@24 1242 return resp;
c@24 1243 }
c@24 1244
c@24 1245 static Vamp::HostExt::ConfigurationRequest
c@60 1246 toVampRequest_Configure(json11::Json j,
c@60 1247 const PluginHandleMapper &pmapper,
c@60 1248 std::string &err) {
c@24 1249
c@60 1250 checkTypeField(j, "configure", err);
c@60 1251 if (failed(err)) return {};
c@60 1252 return toConfigurationRequest(j["content"], pmapper, err);
c@24 1253 }
c@24 1254
c@24 1255 static Vamp::HostExt::ConfigurationResponse
c@60 1256 toVampResponse_Configure(json11::Json j,
c@60 1257 const PluginHandleMapper &pmapper,
c@60 1258 std::string &err) {
c@24 1259
c@24 1260 Vamp::HostExt::ConfigurationResponse resp;
c@60 1261 if (successful(j, err) && !failed(err)) {
c@60 1262 resp = toConfigurationResponse(j["content"], pmapper, err);
c@24 1263 }
c@24 1264 return resp;
c@24 1265 }
c@24 1266
c@24 1267 static Vamp::HostExt::ProcessRequest
c@49 1268 toVampRequest_Process(json11::Json j, const PluginHandleMapper &pmapper,
c@60 1269 BufferSerialisation &serialisation, std::string &err) {
c@24 1270
c@60 1271 checkTypeField(j, "process", err);
c@60 1272 if (failed(err)) return {};
c@60 1273 return toProcessRequest(j["content"], pmapper, serialisation, err);
c@24 1274 }
c@24 1275
c@24 1276 static Vamp::HostExt::ProcessResponse
c@49 1277 toVampResponse_Process(json11::Json j,
c@51 1278 const PluginHandleMapper &pmapper,
c@60 1279 BufferSerialisation &serialisation, std::string &err) {
c@24 1280
c@24 1281 Vamp::HostExt::ProcessResponse resp;
c@60 1282 if (successful(j, err) && !failed(err)) {
c@51 1283 auto jc = j["content"];
c@52 1284 auto h = jc["pluginHandle"].int_value();
c@52 1285 resp.plugin = pmapper.handleToPlugin(h);
c@52 1286 resp.features = toFeatureSet(jc["features"],
c@57 1287 *pmapper.handleToOutputIdMapper(h),
c@60 1288 serialisation, err);
c@24 1289 }
c@24 1290 return resp;
c@24 1291 }
c@24 1292
c@55 1293 static Vamp::HostExt::FinishRequest
c@60 1294 toVampRequest_Finish(json11::Json j, const PluginHandleMapper &pmapper,
c@60 1295 std::string &err) {
c@24 1296
c@60 1297 checkTypeField(j, "finish", err);
c@60 1298 if (failed(err)) return {};
c@55 1299 Vamp::HostExt::FinishRequest req;
c@55 1300 req.plugin = pmapper.handleToPlugin
c@55 1301 (j["content"]["pluginHandle"].int_value());
c@55 1302 return req;
c@24 1303 }
c@24 1304
c@24 1305 static Vamp::HostExt::ProcessResponse
c@49 1306 toVampResponse_Finish(json11::Json j,
c@51 1307 const PluginHandleMapper &pmapper,
c@60 1308 BufferSerialisation &serialisation, std::string &err) {
c@24 1309
c@24 1310 Vamp::HostExt::ProcessResponse resp;
c@60 1311 if (successful(j, err) && !failed(err)) {
c@51 1312 auto jc = j["content"];
c@52 1313 auto h = jc["pluginHandle"].int_value();
c@52 1314 resp.plugin = pmapper.handleToPlugin(h);
c@52 1315 resp.features = toFeatureSet(jc["features"],
c@57 1316 *pmapper.handleToOutputIdMapper(h),
c@60 1317 serialisation, err);
c@24 1318 }
c@24 1319 return resp;
c@24 1320 }
c@5 1321 };
c@5 1322
c@10 1323 }
c@5 1324
c@5 1325 #endif