annotate json/json-cli.cpp @ 5:6e8607ebad03

Promote the more successful experiments (todo: get them to build again)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 13 May 2016 13:48:59 +0100
parents
children
rev   line source
c@5 1
c@5 2 #include "VampJson.h"
c@5 3
c@5 4 #include <iostream>
c@5 5 #include <sstream>
c@5 6 #include <stdexcept>
c@5 7
c@5 8 #include <map>
c@5 9 #include <set>
c@5 10
c@5 11 using namespace std;
c@5 12 using namespace Vamp;
c@5 13 using namespace Vamp::HostExt;
c@5 14 using namespace json11;
c@5 15
c@5 16 static map<uint32_t, Plugin *> loadedPlugins;
c@5 17 static set<uint32_t> initialisedPlugins;
c@5 18
c@5 19 static uint32_t nextHandle = 1; // plugin handle type must fit in JSON number
c@5 20
c@5 21 Vamp::HostExt::LoadResponse
c@5 22 loadPlugin(json11::Json j) {
c@5 23
c@5 24 auto req = VampJson::toLoadRequest(j);
c@5 25 auto loader = Vamp::HostExt::PluginLoader::getInstance();
c@5 26 auto response = loader->loadPlugin(req);
c@5 27
c@5 28 if (!response.plugin) {
c@5 29 throw VampJson::Failure("plugin load failed");
c@5 30 }
c@5 31
c@5 32 return response;
c@5 33 }
c@5 34
c@5 35 Vamp::Plugin::OutputList
c@5 36 configurePlugin(Vamp::Plugin *plugin, json11::Json j) {
c@5 37
c@5 38 auto config = VampJson::toPluginConfiguration(j);
c@5 39 auto loader = Vamp::HostExt::PluginLoader::getInstance();
c@5 40 auto outputs = loader->configurePlugin(plugin, config);
c@5 41
c@5 42 if (outputs.empty()) {
c@5 43 throw VampJson::Failure("plugin initialisation failed (invalid channelCount, stepSize, blockSize?)");
c@5 44 }
c@5 45
c@5 46 return outputs;
c@5 47 }
c@5 48
c@5 49 Json
c@5 50 handle_list(Json content)
c@5 51 {
c@5 52 if (content != Json()) {
c@5 53 throw VampJson::Failure("no content expected for list request");
c@5 54 }
c@5 55
c@5 56 auto loader = PluginLoader::getInstance();
c@5 57 auto pluginData = loader->listPluginData();
c@5 58
c@5 59 Json::array j;
c@5 60 for (const auto &pd: pluginData) {
c@5 61 j.push_back(VampJson::fromPluginStaticData(pd));
c@5 62 }
c@5 63 return Json(j);
c@5 64 }
c@5 65
c@5 66 Json
c@5 67 handle_load(Json j)
c@5 68 {
c@5 69 auto loadResponse = loadPlugin(j);
c@5 70
c@5 71 if (!loadResponse.plugin) {
c@5 72 throw VampJson::Failure("plugin load failed");
c@5 73 }
c@5 74
c@5 75 uint32_t h = nextHandle++;
c@5 76 loadedPlugins[h] = loadResponse.plugin;
c@5 77
c@5 78 Json::object response;
c@5 79 response["pluginHandle"] = double(h);
c@5 80 response["staticData"] =
c@5 81 VampJson::fromPluginStaticData(loadResponse.staticData);
c@5 82 response["defaultConfiguration"] =
c@5 83 VampJson::fromPluginConfiguration(loadResponse.defaultConfiguration);
c@5 84
c@5 85 cerr << "Loaded plugin: handle is " << h << endl;
c@5 86
c@5 87 return Json(response);
c@5 88 }
c@5 89
c@5 90 Json
c@5 91 handle_configure(Json j)
c@5 92 {
c@5 93 string err;
c@5 94
c@5 95 if (!j.has_shape({
c@5 96 { "pluginHandle", Json::NUMBER },
c@5 97 { "configuration", Json::OBJECT }}, err)) {
c@5 98 throw VampJson::Failure("malformed configuration request: " + err);
c@5 99 }
c@5 100
c@5 101 uint32_t handle = j["pluginHandle"].int_value();
c@5 102
c@5 103 if (loadedPlugins.find(handle) == loadedPlugins.end()) {
c@5 104 throw VampJson::Failure("unknown plugin handle");
c@5 105 }
c@5 106
c@5 107 if (initialisedPlugins.find(handle) != initialisedPlugins.end()) {
c@5 108 throw VampJson::Failure("plugin has already been initialised");
c@5 109 }
c@5 110
c@5 111 Plugin *plugin = loadedPlugins[handle];
c@5 112
c@5 113 Json config = j["configuration"];
c@5 114
c@5 115 configurePlugin(plugin, config);
c@5 116
c@5 117 initialisedPlugins.insert(handle);
c@5 118
c@5 119 cerr << "Configured and initialised plugin " << handle << endl;
c@5 120
c@5 121 Json::object jout;
c@5 122 Json::array outs;
c@5 123 Vamp::Plugin::OutputList vouts = plugin->getOutputDescriptors();
c@5 124 for (auto &o: vouts) {
c@5 125 outs.push_back(VampJson::fromOutputDescriptor(o));
c@5 126 }
c@5 127 jout["outputList"] = outs;
c@5 128 return Json(jout);
c@5 129 }
c@5 130
c@5 131 Json
c@5 132 handle(string input)
c@5 133 {
c@5 134 string err;
c@5 135 Json j = Json::parse(input, err);
c@5 136
c@5 137 if (err != "") {
c@5 138 throw VampJson::Failure("invalid request: " + err);
c@5 139 }
c@5 140
c@5 141 if (!j["verb"].is_string()) {
c@5 142 throw VampJson::Failure("verb expected in request");
c@5 143 }
c@5 144
c@5 145 if (!j["content"].is_null() &&
c@5 146 !j["content"].is_object()) {
c@5 147 throw VampJson::Failure("object expected for content");
c@5 148 }
c@5 149
c@5 150 string verb = j["verb"].string_value();
c@5 151 Json content = j["content"];
c@5 152 Json result;
c@5 153
c@5 154 if (verb == "list") {
c@5 155 result = handle_list(content);
c@5 156 } else if (verb == "load") {
c@5 157 result = handle_load(content);
c@5 158 } else if (verb == "configure") {
c@5 159 result = handle_configure(content);
c@5 160 } else {
c@5 161 throw VampJson::Failure("unknown verb: " + verb +
c@5 162 " (known verbs are: list load configure)");
c@5 163 }
c@5 164
c@5 165 return result;
c@5 166 }
c@5 167
c@5 168 Json
c@5 169 success_response(Json payload)
c@5 170 {
c@5 171 Json::object obj;
c@5 172 obj["success"] = true;
c@5 173 obj["response"] = payload;
c@5 174 return Json(obj);
c@5 175 }
c@5 176
c@5 177 Json
c@5 178 error_response(string text)
c@5 179 {
c@5 180 Json::object obj;
c@5 181 obj["success"] = false;
c@5 182 obj["errorText"] = text;
c@5 183 return Json(obj);
c@5 184 }
c@5 185
c@5 186 template<typename T>
c@5 187 T &getline(T &in, string prompt, string &out)
c@5 188 {
c@5 189 cerr << prompt;
c@5 190 return getline(in, out);
c@5 191 }
c@5 192
c@5 193 int main(int, char **)
c@5 194 {
c@5 195 string line;
c@5 196
c@5 197 while (getline(cin, "> ", line)) {
c@5 198 try {
c@5 199 Json result = handle(line);
c@5 200 cout << success_response(result).dump() << endl;
c@5 201 } catch (const VampJson::Failure &e) {
c@5 202 cout << error_response(e.what()).dump() << endl;
c@5 203 }
c@5 204 }
c@5 205
c@5 206 return 0;
c@5 207 }
c@5 208
c@5 209