annotate utilities/vampipe-convert.cpp @ 26:13393bdfc7ef

Start introducing request/response readers to capnp code as well
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 24 May 2016 11:07:59 +0100
parents 5b9690d18241
children cc85c2851605
rev   line source
c@23 1
c@23 2 #include "VampJson.h"
c@23 3 #include "VampnProto.h"
c@23 4
c@23 5 #include <iostream>
c@23 6 #include <sstream>
c@23 7 #include <stdexcept>
c@23 8
c@23 9 using namespace std;
c@23 10 using namespace json11;
c@23 11 using namespace vampipe;
c@23 12
c@24 13 // Accepting JSON objects with two fields, "type" and "content". The
c@23 14 // "type" string corresponds to the JSON schema filename
c@24 15 // (e.g. "outputdescriptor") and the "content" is the JSON object
c@23 16 // encoded with that schema.
c@23 17
c@23 18 class PreservingPluginHandleMapper : public PluginHandleMapper
c@23 19 {
c@23 20 public:
c@23 21 PreservingPluginHandleMapper() : m_handle(0), m_plugin(0) { }
c@23 22
c@23 23 virtual int32_t pluginToHandle(Vamp::Plugin *p) {
c@23 24 if (p == m_plugin) return m_handle;
c@23 25 else throw NotFound();
c@23 26 }
c@23 27
c@23 28 virtual Vamp::Plugin *handleToPlugin(int32_t h) {
c@23 29 m_handle = h;
c@23 30 m_plugin = reinterpret_cast<Vamp::Plugin *>(h);
c@23 31 return m_plugin;
c@23 32 }
c@23 33
c@23 34 private:
c@23 35 int32_t m_handle;
c@23 36 Vamp::Plugin *m_plugin;
c@23 37 };
c@23 38
c@23 39 void usage()
c@23 40 {
c@23 41 string myname = "vampipe-convert";
c@23 42 cerr << "\n" << myname <<
c@24 43 ": Validate and convert Vamp request and response messages\n\n"
c@24 44 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n"
c@24 45 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n"
c@24 46 " where\n"
c@24 47 " <informat>: the format to read from stdin\n"
c@24 48 " (\"json\" or \"capnp\", default is \"json\")\n"
c@24 49 " <outformat>: the format to convert to and write to stdout\n"
c@24 50 " (\"json\" or \"capnp\", default is \"json\")\n"
c@24 51 " request|response: whether to expect Vamp request or response messages\n\n"
c@24 52 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n"
c@24 53 "If <informat> and <outformat> are the same, just check validity of incoming\n"
c@24 54 "messages and pass them to output.\n\n";
c@24 55
c@23 56 exit(2);
c@23 57 }
c@23 58
c@23 59 class RequestOrResponse
c@23 60 {
c@23 61 public:
c@24 62 enum Direction {
c@24 63 Request, Response
c@24 64 };
c@24 65
c@23 66 RequestOrResponse() : // nothing by default
c@24 67 direction(Request),
c@25 68 type(RRType::NotValid),
c@23 69 success(false),
c@23 70 finishPlugin(0) { }
c@23 71
c@24 72 Direction direction;
c@25 73 RRType type;
c@23 74 bool success;
c@23 75 string errorText;
c@23 76
c@23 77 PreservingPluginHandleMapper mapper;
c@24 78
c@24 79 vector<Vamp::HostExt::PluginStaticData> listResponse;
c@23 80 Vamp::HostExt::LoadRequest loadRequest;
c@23 81 Vamp::HostExt::LoadResponse loadResponse;
c@23 82 Vamp::HostExt::ConfigurationRequest configurationRequest;
c@23 83 Vamp::HostExt::ConfigurationResponse configurationResponse;
c@23 84 Vamp::HostExt::ProcessRequest processRequest;
c@23 85 Vamp::HostExt::ProcessResponse processResponse;
c@23 86 Vamp::Plugin *finishPlugin;
c@23 87 Vamp::HostExt::ProcessResponse finishResponse;
c@23 88 };
c@23 89
c@24 90 Json
c@24 91 convertRequestJson(string input)
c@24 92 {
c@24 93 string err;
c@24 94 Json j = Json::parse(input, err);
c@24 95 if (err != "") {
c@24 96 throw VampJson::Failure("invalid json: " + err);
c@24 97 }
c@24 98 if (!j.is_object()) {
c@24 99 throw VampJson::Failure("object expected at top level");
c@24 100 }
c@24 101 if (!j["type"].is_string()) {
c@24 102 throw VampJson::Failure("string expected for type field");
c@24 103 }
c@24 104 if (!j["content"].is_object()) {
c@24 105 throw VampJson::Failure("object expected for content field");
c@24 106 }
c@24 107 return j;
c@24 108 }
c@24 109
c@24 110 Json
c@24 111 convertResponseJson(string input)
c@24 112 {
c@24 113 string err;
c@24 114 Json j = Json::parse(input, err);
c@24 115 if (err != "") {
c@24 116 throw VampJson::Failure("invalid json: " + err);
c@24 117 }
c@24 118 if (!j.is_object()) {
c@24 119 throw VampJson::Failure("object expected at top level");
c@24 120 }
c@24 121 if (!j["success"].is_bool()) {
c@24 122 throw VampJson::Failure("bool expected for success field");
c@24 123 }
c@24 124 if (!j["content"].is_object()) {
c@24 125 throw VampJson::Failure("object expected for content field");
c@24 126 }
c@24 127 return j;
c@24 128 }
c@24 129
c@23 130 RequestOrResponse
c@24 131 readRequestJson()
c@23 132 {
c@23 133 RequestOrResponse rr;
c@24 134 rr.direction = RequestOrResponse::Request;
c@24 135
c@24 136 string input;
c@24 137 if (!getline(cin, input)) {
c@25 138 rr.type = RRType::NotValid;
c@24 139 return rr;
c@24 140 }
c@24 141
c@24 142 Json j = convertRequestJson(input);
c@25 143 rr.type = VampJson::getRequestResponseType(j);
c@24 144
c@25 145 if (rr.type == RRType::Load) {
c@24 146 rr.loadRequest = VampJson::toVampRequest_Load(j);
c@24 147
c@25 148 } else if (rr.type == RRType::Configure) {
c@24 149 rr.configurationRequest = VampJson::toVampRequest_Configure(j, rr.mapper);
c@24 150
c@25 151 } else if (rr.type == RRType::Process) {
c@24 152 rr.processRequest = VampJson::toVampRequest_Process(j, rr.mapper);
c@24 153
c@25 154 } else if (rr.type == RRType::Finish) {
c@24 155 rr.finishPlugin = VampJson::toVampRequest_Finish(j, rr.mapper);
c@24 156 }
c@24 157
c@24 158 return rr;
c@24 159 }
c@24 160
c@24 161 void
c@24 162 writeRequestJson(RequestOrResponse &rr)
c@24 163 {
c@24 164 Json j;
c@24 165
c@25 166 if (rr.type == RRType::List) {
c@24 167 j = VampJson::fromVampRequest_List();
c@24 168
c@25 169 } else if (rr.type == RRType::Load) {
c@24 170 j = VampJson::fromVampRequest_Load(rr.loadRequest);
c@24 171
c@25 172 } else if (rr.type == RRType::Configure) {
c@24 173 j = VampJson::fromVampRequest_Configure(rr.configurationRequest, rr.mapper);
c@24 174
c@25 175 } else if (rr.type == RRType::Process) {
c@24 176 j = VampJson::fromVampRequest_Process(rr.processRequest, rr.mapper);
c@24 177
c@25 178 } else if (rr.type == RRType::Finish) {
c@24 179 j = VampJson::fromVampRequest_Finish(rr.finishPlugin, rr.mapper);
c@24 180 }
c@24 181
c@24 182 cout << j.dump() << endl;
c@24 183 }
c@24 184
c@24 185 RequestOrResponse
c@24 186 readResponseJson()
c@24 187 {
c@24 188 RequestOrResponse rr;
c@24 189 rr.direction = RequestOrResponse::Response;
c@24 190
c@23 191 string input;
c@23 192 if (!getline(cin, input)) {
c@25 193 rr.type = RRType::NotValid;
c@23 194 return rr;
c@23 195 }
c@23 196
c@24 197 Json j = convertResponseJson(input);
c@25 198 rr.type = VampJson::getRequestResponseType(j);
c@23 199
c@25 200 if (rr.type == RRType::List) {
c@24 201 rr.listResponse = VampJson::toVampResponse_List(j);
c@24 202
c@25 203 } else if (rr.type == RRType::Load) {
c@24 204 rr.loadResponse = VampJson::toVampResponse_Load(j, rr.mapper);
c@23 205
c@25 206 } else if (rr.type == RRType::Configure) {
c@24 207 rr.configurationResponse = VampJson::toVampResponse_Configure(j);
c@23 208
c@25 209 } else if (rr.type == RRType::Process) {
c@24 210 rr.processResponse = VampJson::toVampResponse_Process(j);
c@23 211
c@25 212 } else if (rr.type == RRType::Finish) {
c@24 213 rr.finishResponse = VampJson::toVampResponse_Finish(j);
c@23 214 }
c@23 215
c@23 216 return rr;
c@23 217 }
c@23 218
c@24 219 void
c@24 220 writeResponseJson(RequestOrResponse &rr)
c@24 221 {
c@24 222 Json j;
c@24 223
c@25 224 if (rr.type == RRType::List) {
c@24 225 j = VampJson::fromVampResponse_List("", rr.listResponse);
c@24 226
c@25 227 } else if (rr.type == RRType::Load) {
c@24 228 j = VampJson::fromVampResponse_Load(rr.loadResponse, rr.mapper);
c@24 229 }
c@24 230
c@25 231 //!!!
c@25 232
c@24 233 cout << j.dump() << endl;
c@24 234 }
c@24 235
c@23 236 RequestOrResponse
c@24 237 readInput(string format, RequestOrResponse::Direction direction)
c@23 238 {
c@23 239 if (format == "json") {
c@24 240 if (direction == RequestOrResponse::Request) {
c@24 241 return readRequestJson();
c@24 242 } else {
c@24 243 return readResponseJson();
c@24 244 }
c@23 245 } else {
c@23 246 throw runtime_error("unknown or unimplemented format \"" + format + "\"");
c@23 247 }
c@23 248 }
c@23 249
c@23 250 void
c@24 251 writeOutput(string format, RequestOrResponse &rr)
c@23 252 {
c@24 253 if (format == "json") {
c@24 254 if (rr.direction == RequestOrResponse::Request) {
c@24 255 writeRequestJson(rr);
c@24 256 } else {
c@24 257 writeResponseJson(rr);
c@24 258 }
c@24 259 } else {
c@24 260 throw runtime_error("unknown or unimplemented format \"" + format + "\"");
c@24 261 }
c@23 262 }
c@23 263
c@23 264 int main(int argc, char **argv)
c@23 265 {
c@24 266 if (argc < 2) {
c@23 267 usage();
c@23 268 }
c@23 269
c@24 270 string informat = "json", outformat = "json";
c@24 271 RequestOrResponse::Direction direction;
c@24 272 bool haveDirection = false;
c@23 273
c@24 274 for (int i = 1; i < argc; ++i) {
c@23 275
c@23 276 string arg = argv[i];
c@24 277 bool final = (i + 1 == argc);
c@23 278
c@23 279 if (arg == "-i") {
c@24 280 if (informat != "" || final) usage();
c@23 281 else informat = argv[++i];
c@23 282
c@23 283 } else if (arg == "-o") {
c@24 284 if (outformat != "" || final) usage();
c@23 285 else outformat = argv[++i];
c@23 286
c@24 287 } else if (arg == "request") {
c@24 288 direction = RequestOrResponse::Request;
c@24 289 haveDirection = true;
c@24 290
c@24 291 } else if (arg == "response") {
c@24 292 direction = RequestOrResponse::Response;
c@24 293 haveDirection = true;
c@24 294
c@23 295 } else {
c@23 296 usage();
c@23 297 }
c@23 298 }
c@23 299
c@24 300 if (informat == "" || outformat == "" || !haveDirection) {
c@23 301 usage();
c@23 302 }
c@23 303
c@23 304 while (true) {
c@23 305
c@23 306 try {
c@23 307
c@24 308 RequestOrResponse rr = readInput(informat, direction);
c@25 309 if (rr.type == RRType::NotValid) break;
c@23 310 writeOutput(outformat, rr);
c@23 311
c@23 312 } catch (std::exception &e) {
c@23 313 cerr << "Error: " << e.what() << endl;
c@23 314 exit(1);
c@23 315 }
c@23 316 }
c@23 317
c@23 318 exit(0);
c@23 319 }
c@23 320
c@23 321