annotate utilities/vampipe-convert.cpp @ 23:d678cd00e593

Begin vampipe-convert
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 20 May 2016 18:05:02 +0100
parents
children 533ca5ca3404
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@23 13 // Accepting JSON objects with two fields, "type" and "payload". The
c@23 14 // "type" string corresponds to the JSON schema filename
c@23 15 // (e.g. "outputdescriptor") and the "payload" is the JSON object
c@23 16 // encoded with that schema.
c@23 17
c@23 18 Json
c@23 19 json_input(string input)
c@23 20 {
c@23 21 string err;
c@23 22 Json j = Json::parse(input, err);
c@23 23 if (err != "") {
c@23 24 throw VampJson::Failure("invalid json: " + err);
c@23 25 }
c@23 26 if (!j.is_object()) {
c@23 27 throw VampJson::Failure("object expected at top level");
c@23 28 }
c@23 29 if (!j["type"].is_string()) {
c@23 30 throw VampJson::Failure("string expected for type field");
c@23 31 }
c@23 32 if (!j["payload"].is_object()) {
c@23 33 throw VampJson::Failure("object expected for payload field");
c@23 34 }
c@23 35 return j;
c@23 36 }
c@23 37
c@23 38 class PreservingPluginHandleMapper : public PluginHandleMapper
c@23 39 {
c@23 40 public:
c@23 41 PreservingPluginHandleMapper() : m_handle(0), m_plugin(0) { }
c@23 42
c@23 43 virtual int32_t pluginToHandle(Vamp::Plugin *p) {
c@23 44 if (p == m_plugin) return m_handle;
c@23 45 else throw NotFound();
c@23 46 }
c@23 47
c@23 48 virtual Vamp::Plugin *handleToPlugin(int32_t h) {
c@23 49 m_handle = h;
c@23 50 m_plugin = reinterpret_cast<Vamp::Plugin *>(h);
c@23 51 return m_plugin;
c@23 52 }
c@23 53
c@23 54 private:
c@23 55 int32_t m_handle;
c@23 56 Vamp::Plugin *m_plugin;
c@23 57 };
c@23 58
c@23 59 void
c@23 60 handle_input(::capnp::MallocMessageBuilder &message, string input)
c@23 61 {
c@23 62 string err;
c@23 63
c@23 64 Json j = json_input(input);
c@23 65 string type = j["type"].string_value();
c@23 66 Json payload = j["payload"];
c@23 67
c@23 68 if (type == "configurationrequest") {
c@23 69 auto req = message.initRoot<ConfigurationRequest>();
c@23 70 PreservingPluginHandleMapper mapper;
c@23 71 VampnProto::buildConfigurationRequest
c@23 72 (req, VampJson::toConfigurationRequest(payload, mapper), mapper);
c@23 73
c@23 74 } else if (type == "configurationresponse") {
c@23 75 auto resp = message.initRoot<ConfigurationResponse>();
c@23 76 VampnProto::buildConfigurationResponse
c@23 77 (resp, VampJson::toConfigurationResponse(payload));
c@23 78
c@23 79 } else if (type == "feature") {
c@23 80 auto f = message.initRoot<Feature>();
c@23 81 VampnProto::buildFeature
c@23 82 (f, VampJson::toFeature(payload));
c@23 83
c@23 84 } else if (type == "featureset") {
c@23 85 auto fs = message.initRoot<FeatureSet>();
c@23 86 VampnProto::buildFeatureSet
c@23 87 (fs, VampJson::toFeatureSet(payload));
c@23 88
c@23 89 } else if (type == "loadrequest") {
c@23 90 auto req = message.initRoot<LoadRequest>();
c@23 91 VampnProto::buildLoadRequest
c@23 92 (req, VampJson::toLoadRequest(payload));
c@23 93
c@23 94 } else if (type == "loadresponse") {
c@23 95 auto resp = message.initRoot<LoadResponse>();
c@23 96 PreservingPluginHandleMapper mapper;
c@23 97 VampnProto::buildLoadResponse
c@23 98 (resp, VampJson::toLoadResponse(payload, mapper), mapper);
c@23 99
c@23 100 } else if (type == "outputdescriptor") {
c@23 101 auto od = message.initRoot<OutputDescriptor>();
c@23 102 VampnProto::buildOutputDescriptor
c@23 103 (od, VampJson::toOutputDescriptor(payload));
c@23 104
c@23 105 } else if (type == "parameterdescriptor") {
c@23 106 auto pd = message.initRoot<ParameterDescriptor>();
c@23 107 VampnProto::buildParameterDescriptor
c@23 108 (pd, VampJson::toParameterDescriptor(payload));
c@23 109
c@23 110 } else if (type == "pluginconfiguration") {
c@23 111 auto pc = message.initRoot<PluginConfiguration>();
c@23 112 auto config = VampJson::toPluginConfiguration(payload);
c@23 113 VampnProto::buildPluginConfiguration(pc, config);
c@23 114
c@23 115 } else if (type == "pluginstaticdata") {
c@23 116 auto pc = message.initRoot<PluginStaticData>();
c@23 117 auto sd = VampJson::toPluginStaticData(payload);
c@23 118 VampnProto::buildPluginStaticData(pc, sd);
c@23 119
c@23 120 } else if (type == "processrequest") {
c@23 121 auto p = message.initRoot<ProcessRequest>();
c@23 122 PreservingPluginHandleMapper mapper;
c@23 123 VampnProto::buildProcessRequest
c@23 124 (p, VampJson::toProcessRequest(payload, mapper), mapper);
c@23 125
c@23 126 } else if (type == "realtime") {
c@23 127 auto b = message.initRoot<RealTime>();
c@23 128 VampnProto::buildRealTime
c@23 129 (b, VampJson::toRealTime(payload));
c@23 130
c@23 131 } else {
c@23 132 throw VampJson::Failure("unknown or unsupported JSON schema type " +
c@23 133 type);
c@23 134 }
c@23 135 }
c@23 136
c@23 137 void usage()
c@23 138 {
c@23 139 string myname = "vampipe-convert";
c@23 140 cerr << "\n" << myname <<
c@23 141 ": Convert Vamp request and response messages between formats\n\n"
c@23 142 " Usage: " << myname << " -i <informat> -o <outformat>\n\n"
c@23 143 "Where <informat> and <outformat> may be \"json\" or \"capnp\".\n"
c@23 144 "Messages are read from stdin and written to stdout.\n" << endl;
c@23 145 exit(2);
c@23 146 }
c@23 147
c@23 148 class RequestOrResponse
c@23 149 {
c@23 150 public:
c@23 151 enum Type {
c@23 152 List, Load, Configure, Process, Finish, Eof
c@23 153 };
c@23 154 RequestOrResponse() : // nothing by default
c@23 155 type(Eof),
c@23 156 success(false),
c@23 157 finishPlugin(0) { }
c@23 158
c@23 159 Type type;
c@23 160 bool success;
c@23 161 string errorText;
c@23 162
c@23 163 PreservingPluginHandleMapper mapper;
c@23 164
c@23 165 Vamp::HostExt::LoadRequest loadRequest;
c@23 166 Vamp::HostExt::LoadResponse loadResponse;
c@23 167 Vamp::HostExt::ConfigurationRequest configurationRequest;
c@23 168 Vamp::HostExt::ConfigurationResponse configurationResponse;
c@23 169 Vamp::HostExt::ProcessRequest processRequest;
c@23 170 Vamp::HostExt::ProcessResponse processResponse;
c@23 171 Vamp::Plugin *finishPlugin;
c@23 172 Vamp::HostExt::ProcessResponse finishResponse;
c@23 173
c@23 174 };
c@23 175
c@23 176 RequestOrResponse
c@23 177 readInputJson()
c@23 178 {
c@23 179 RequestOrResponse rr;
c@23 180 string input;
c@23 181 if (!getline(cin, input)) {
c@23 182 rr.type = RequestOrResponse::Eof;
c@23 183 return rr;
c@23 184 }
c@23 185
c@23 186 Json j = json_input(input);
c@23 187 string type = j["type"].string_value();
c@23 188
c@23 189 if (type == "list") {
c@23 190 rr.type = RequestOrResponse::List;
c@23 191
c@23 192 } else if (type == "load") {
c@23 193 //!!! ah, we need a way to know whether we're dealing with a request or response here
c@23 194 rr.type = RequestOrResponse::Load;
c@23 195 rr.loadRequest = VampJson::toLoadRequest(j["content"]);
c@23 196
c@23 197 } else if (type == "configure") {
c@23 198 rr.type = RequestOrResponse::Configure;
c@23 199 rr.configurationRequest =
c@23 200 VampJson::toConfigurationRequest(j["content"], rr.mapper);
c@23 201
c@23 202 } else if (type == "process") {
c@23 203 rr.type = RequestOrResponse::Process;
c@23 204 rr.processRequest =
c@23 205 VampJson::toProcessRequest(j["content"], rr.mapper);
c@23 206
c@23 207 } else if (type == "finish") {
c@23 208 rr.type = RequestOrResponse::Finish;
c@23 209 //!!! VampJsonify
c@23 210 rr.finishPlugin = rr.mapper.handleToPlugin(j["content"]["pluginHandle"].int_value());
c@23 211
c@23 212 } else {
c@23 213 throw runtime_error("unknown or unexpected request/response type \"" +
c@23 214 type + "\"");
c@23 215 }
c@23 216
c@23 217 return rr;
c@23 218 }
c@23 219
c@23 220 RequestOrResponse
c@23 221 readInput(string format)
c@23 222 {
c@23 223 if (format == "json") {
c@23 224 return readInputJson();
c@23 225 } else {
c@23 226 throw runtime_error("unknown or unimplemented format \"" + format + "\"");
c@23 227 }
c@23 228 }
c@23 229
c@23 230 void
c@23 231 writeOutput(string format, const RequestOrResponse &rr)
c@23 232 {
c@23 233 throw runtime_error("writeOutput not implemented yet");
c@23 234
c@23 235 }
c@23 236
c@23 237 int main(int argc, char **argv)
c@23 238 {
c@23 239 if (argc != 5) {
c@23 240 usage();
c@23 241 }
c@23 242
c@23 243 string informat, outformat;
c@23 244
c@23 245 for (int i = 1; i + 1 < argc; ++i) {
c@23 246
c@23 247 string arg = argv[i];
c@23 248
c@23 249 if (arg == "-i") {
c@23 250 if (informat != "") usage();
c@23 251 else informat = argv[++i];
c@23 252
c@23 253 } else if (arg == "-o") {
c@23 254 if (outformat != "") usage();
c@23 255 else outformat = argv[++i];
c@23 256
c@23 257 } else {
c@23 258 usage();
c@23 259 }
c@23 260 }
c@23 261
c@23 262 if (informat == "" || outformat == "") {
c@23 263 usage();
c@23 264 }
c@23 265
c@23 266 while (true) {
c@23 267
c@23 268 try {
c@23 269
c@23 270 RequestOrResponse rr = readInput(informat);
c@23 271 if (rr.type == RequestOrResponse::Eof) break;
c@23 272 writeOutput(outformat, rr);
c@23 273
c@23 274 } catch (std::exception &e) {
c@23 275 cerr << "Error: " << e.what() << endl;
c@23 276 exit(1);
c@23 277 }
c@23 278 }
c@23 279
c@23 280 exit(0);
c@23 281 }
c@23 282
c@23 283