annotate utilities/json-cli.cpp @ 11:aa61cb5c5754

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