c@5: c@5: #include "VampJson.h" c@5: c@5: #include c@5: #include c@5: #include c@5: c@5: #include c@5: #include c@5: c@5: using namespace std; c@5: using namespace Vamp; c@5: using namespace Vamp::HostExt; c@5: using namespace json11; c@5: c@5: static map loadedPlugins; c@5: static set initialisedPlugins; c@5: c@5: static uint32_t nextHandle = 1; // plugin handle type must fit in JSON number c@5: c@5: Vamp::HostExt::LoadResponse c@5: loadPlugin(json11::Json j) { c@5: c@5: auto req = VampJson::toLoadRequest(j); c@5: auto loader = Vamp::HostExt::PluginLoader::getInstance(); c@5: auto response = loader->loadPlugin(req); c@5: c@5: if (!response.plugin) { c@5: throw VampJson::Failure("plugin load failed"); c@5: } c@5: c@5: return response; c@5: } c@5: c@5: Vamp::Plugin::OutputList c@5: configurePlugin(Vamp::Plugin *plugin, json11::Json j) { c@5: c@5: auto config = VampJson::toPluginConfiguration(j); c@5: auto loader = Vamp::HostExt::PluginLoader::getInstance(); c@5: auto outputs = loader->configurePlugin(plugin, config); c@5: c@5: if (outputs.empty()) { c@5: throw VampJson::Failure("plugin initialisation failed (invalid channelCount, stepSize, blockSize?)"); c@5: } c@5: c@5: return outputs; c@5: } c@5: c@5: Json c@5: handle_list(Json content) c@5: { c@5: if (content != Json()) { c@5: throw VampJson::Failure("no content expected for list request"); c@5: } c@5: c@5: auto loader = PluginLoader::getInstance(); c@5: auto pluginData = loader->listPluginData(); c@5: c@5: Json::array j; c@5: for (const auto &pd: pluginData) { c@5: j.push_back(VampJson::fromPluginStaticData(pd)); c@5: } c@5: return Json(j); c@5: } c@5: c@5: Json c@5: handle_load(Json j) c@5: { c@5: auto loadResponse = loadPlugin(j); c@5: c@5: if (!loadResponse.plugin) { c@5: throw VampJson::Failure("plugin load failed"); c@5: } c@5: c@5: uint32_t h = nextHandle++; c@5: loadedPlugins[h] = loadResponse.plugin; c@5: c@5: Json::object response; c@5: response["pluginHandle"] = double(h); c@5: response["staticData"] = c@5: VampJson::fromPluginStaticData(loadResponse.staticData); c@5: response["defaultConfiguration"] = c@5: VampJson::fromPluginConfiguration(loadResponse.defaultConfiguration); c@5: c@5: cerr << "Loaded plugin: handle is " << h << endl; c@5: c@5: return Json(response); c@5: } c@5: c@5: Json c@5: handle_configure(Json j) c@5: { c@5: string err; c@5: c@5: if (!j.has_shape({ c@5: { "pluginHandle", Json::NUMBER }, c@5: { "configuration", Json::OBJECT }}, err)) { c@5: throw VampJson::Failure("malformed configuration request: " + err); c@5: } c@5: c@5: uint32_t handle = j["pluginHandle"].int_value(); c@5: c@5: if (loadedPlugins.find(handle) == loadedPlugins.end()) { c@5: throw VampJson::Failure("unknown plugin handle"); c@5: } c@5: c@5: if (initialisedPlugins.find(handle) != initialisedPlugins.end()) { c@5: throw VampJson::Failure("plugin has already been initialised"); c@5: } c@5: c@5: Plugin *plugin = loadedPlugins[handle]; c@5: c@5: Json config = j["configuration"]; c@5: c@5: configurePlugin(plugin, config); c@5: c@5: initialisedPlugins.insert(handle); c@5: c@5: cerr << "Configured and initialised plugin " << handle << endl; c@5: c@5: Json::object jout; c@5: Json::array outs; c@5: Vamp::Plugin::OutputList vouts = plugin->getOutputDescriptors(); c@5: for (auto &o: vouts) { c@5: outs.push_back(VampJson::fromOutputDescriptor(o)); c@5: } c@5: jout["outputList"] = outs; c@5: return Json(jout); c@5: } c@5: c@5: Json c@5: handle(string input) c@5: { c@5: string err; c@5: Json j = Json::parse(input, err); c@5: c@5: if (err != "") { c@5: throw VampJson::Failure("invalid request: " + err); c@5: } c@5: c@5: if (!j["verb"].is_string()) { c@5: throw VampJson::Failure("verb expected in request"); c@5: } c@5: c@5: if (!j["content"].is_null() && c@5: !j["content"].is_object()) { c@5: throw VampJson::Failure("object expected for content"); c@5: } c@5: c@5: string verb = j["verb"].string_value(); c@5: Json content = j["content"]; c@5: Json result; c@5: c@5: if (verb == "list") { c@5: result = handle_list(content); c@5: } else if (verb == "load") { c@5: result = handle_load(content); c@5: } else if (verb == "configure") { c@5: result = handle_configure(content); c@5: } else { c@5: throw VampJson::Failure("unknown verb: " + verb + c@5: " (known verbs are: list load configure)"); c@5: } c@5: c@5: return result; c@5: } c@5: c@5: Json c@5: success_response(Json payload) c@5: { c@5: Json::object obj; c@5: obj["success"] = true; c@5: obj["response"] = payload; c@5: return Json(obj); c@5: } c@5: c@5: Json c@5: error_response(string text) c@5: { c@5: Json::object obj; c@5: obj["success"] = false; c@5: obj["errorText"] = text; c@5: return Json(obj); c@5: } c@5: c@5: template c@5: T &getline(T &in, string prompt, string &out) c@5: { c@5: cerr << prompt; c@5: return getline(in, out); c@5: } c@5: c@5: int main(int, char **) c@5: { c@5: string line; c@5: c@5: while (getline(cin, "> ", line)) { c@5: try { c@5: Json result = handle(line); c@5: cout << success_response(result).dump() << endl; c@5: } catch (const VampJson::Failure &e) { c@5: cout << error_response(e.what()).dump() << endl; c@5: } c@5: } c@5: c@5: return 0; c@5: } c@5: c@5: