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@23
|
65 enum Type {
|
c@23
|
66 List, Load, Configure, Process, Finish, Eof
|
c@23
|
67 };
|
c@24
|
68
|
c@24
|
69 static Type typeForName(string name) {
|
c@24
|
70 if (name == "list") return List;
|
c@24
|
71 else if (name == "load") return Load;
|
c@24
|
72 else if (name == "configure") return Configure;
|
c@24
|
73 else if (name == "process") return Process;
|
c@24
|
74 else if (name == "finish") return Finish;
|
c@24
|
75 else if (name == "eof") return Eof;
|
c@24
|
76 else {
|
c@24
|
77 throw runtime_error("unknown or unexpected request/response type \"" +
|
c@24
|
78 name + "\"");
|
c@24
|
79 }
|
c@24
|
80 }
|
c@24
|
81
|
c@23
|
82 RequestOrResponse() : // nothing by default
|
c@24
|
83 direction(Request),
|
c@23
|
84 type(Eof),
|
c@23
|
85 success(false),
|
c@23
|
86 finishPlugin(0) { }
|
c@23
|
87
|
c@24
|
88 Direction direction;
|
c@23
|
89 Type type;
|
c@23
|
90 bool success;
|
c@23
|
91 string errorText;
|
c@23
|
92
|
c@23
|
93 PreservingPluginHandleMapper mapper;
|
c@24
|
94
|
c@24
|
95 vector<Vamp::HostExt::PluginStaticData> listResponse;
|
c@23
|
96 Vamp::HostExt::LoadRequest loadRequest;
|
c@23
|
97 Vamp::HostExt::LoadResponse loadResponse;
|
c@23
|
98 Vamp::HostExt::ConfigurationRequest configurationRequest;
|
c@23
|
99 Vamp::HostExt::ConfigurationResponse configurationResponse;
|
c@23
|
100 Vamp::HostExt::ProcessRequest processRequest;
|
c@23
|
101 Vamp::HostExt::ProcessResponse processResponse;
|
c@23
|
102 Vamp::Plugin *finishPlugin;
|
c@23
|
103 Vamp::HostExt::ProcessResponse finishResponse;
|
c@23
|
104 };
|
c@23
|
105
|
c@24
|
106 Json
|
c@24
|
107 convertRequestJson(string input)
|
c@24
|
108 {
|
c@24
|
109 string err;
|
c@24
|
110 Json j = Json::parse(input, err);
|
c@24
|
111 if (err != "") {
|
c@24
|
112 throw VampJson::Failure("invalid json: " + err);
|
c@24
|
113 }
|
c@24
|
114 if (!j.is_object()) {
|
c@24
|
115 throw VampJson::Failure("object expected at top level");
|
c@24
|
116 }
|
c@24
|
117 if (!j["type"].is_string()) {
|
c@24
|
118 throw VampJson::Failure("string expected for type field");
|
c@24
|
119 }
|
c@24
|
120 if (!j["content"].is_object()) {
|
c@24
|
121 throw VampJson::Failure("object expected for content field");
|
c@24
|
122 }
|
c@24
|
123 return j;
|
c@24
|
124 }
|
c@24
|
125
|
c@24
|
126 Json
|
c@24
|
127 convertResponseJson(string input)
|
c@24
|
128 {
|
c@24
|
129 string err;
|
c@24
|
130 Json j = Json::parse(input, err);
|
c@24
|
131 if (err != "") {
|
c@24
|
132 throw VampJson::Failure("invalid json: " + err);
|
c@24
|
133 }
|
c@24
|
134 if (!j.is_object()) {
|
c@24
|
135 throw VampJson::Failure("object expected at top level");
|
c@24
|
136 }
|
c@24
|
137 if (!j["success"].is_bool()) {
|
c@24
|
138 throw VampJson::Failure("bool expected for success field");
|
c@24
|
139 }
|
c@24
|
140 if (!j["content"].is_object()) {
|
c@24
|
141 throw VampJson::Failure("object expected for content field");
|
c@24
|
142 }
|
c@24
|
143 return j;
|
c@24
|
144 }
|
c@24
|
145
|
c@23
|
146 RequestOrResponse
|
c@24
|
147 readRequestJson()
|
c@23
|
148 {
|
c@23
|
149 RequestOrResponse rr;
|
c@24
|
150 rr.direction = RequestOrResponse::Request;
|
c@24
|
151
|
c@24
|
152 string input;
|
c@24
|
153 if (!getline(cin, input)) {
|
c@24
|
154 rr.type = RequestOrResponse::Eof;
|
c@24
|
155 return rr;
|
c@24
|
156 }
|
c@24
|
157
|
c@24
|
158 Json j = convertRequestJson(input);
|
c@24
|
159 string type = j["type"].string_value();
|
c@24
|
160 rr.type = RequestOrResponse::typeForName(type);
|
c@24
|
161
|
c@24
|
162 if (rr.type == RequestOrResponse::Load) {
|
c@24
|
163 rr.loadRequest = VampJson::toVampRequest_Load(j);
|
c@24
|
164
|
c@24
|
165 } else if (rr.type == RequestOrResponse::Configure) {
|
c@24
|
166 rr.configurationRequest = VampJson::toVampRequest_Configure(j, rr.mapper);
|
c@24
|
167
|
c@24
|
168 } else if (rr.type == RequestOrResponse::Process) {
|
c@24
|
169 rr.processRequest = VampJson::toVampRequest_Process(j, rr.mapper);
|
c@24
|
170
|
c@24
|
171 } else if (rr.type == RequestOrResponse::Finish) {
|
c@24
|
172 rr.finishPlugin = VampJson::toVampRequest_Finish(j, rr.mapper);
|
c@24
|
173 }
|
c@24
|
174
|
c@24
|
175 return rr;
|
c@24
|
176 }
|
c@24
|
177
|
c@24
|
178 void
|
c@24
|
179 writeRequestJson(RequestOrResponse &rr)
|
c@24
|
180 {
|
c@24
|
181 Json j;
|
c@24
|
182
|
c@24
|
183 if (rr.type == RequestOrResponse::List) {
|
c@24
|
184 j = VampJson::fromVampRequest_List();
|
c@24
|
185
|
c@24
|
186 } else if (rr.type == RequestOrResponse::Load) {
|
c@24
|
187 j = VampJson::fromVampRequest_Load(rr.loadRequest);
|
c@24
|
188
|
c@24
|
189 } else if (rr.type == RequestOrResponse::Configure) {
|
c@24
|
190 j = VampJson::fromVampRequest_Configure(rr.configurationRequest, rr.mapper);
|
c@24
|
191
|
c@24
|
192 } else if (rr.type == RequestOrResponse::Process) {
|
c@24
|
193 j = VampJson::fromVampRequest_Process(rr.processRequest, rr.mapper);
|
c@24
|
194
|
c@24
|
195 } else if (rr.type == RequestOrResponse::Finish) {
|
c@24
|
196 j = VampJson::fromVampRequest_Finish(rr.finishPlugin, rr.mapper);
|
c@24
|
197 }
|
c@24
|
198
|
c@24
|
199 cout << j.dump() << endl;
|
c@24
|
200 }
|
c@24
|
201
|
c@24
|
202 RequestOrResponse
|
c@24
|
203 readResponseJson()
|
c@24
|
204 {
|
c@24
|
205 RequestOrResponse rr;
|
c@24
|
206 rr.direction = RequestOrResponse::Response;
|
c@24
|
207
|
c@23
|
208 string input;
|
c@23
|
209 if (!getline(cin, input)) {
|
c@23
|
210 rr.type = RequestOrResponse::Eof;
|
c@23
|
211 return rr;
|
c@23
|
212 }
|
c@23
|
213
|
c@24
|
214 Json j = convertResponseJson(input);
|
c@23
|
215 string type = j["type"].string_value();
|
c@24
|
216 rr.type = RequestOrResponse::typeForName(type);
|
c@23
|
217
|
c@24
|
218 if (rr.type == RequestOrResponse::List) {
|
c@24
|
219 rr.listResponse = VampJson::toVampResponse_List(j);
|
c@24
|
220
|
c@24
|
221 } else if (rr.type == RequestOrResponse::Load) {
|
c@24
|
222 rr.loadResponse = VampJson::toVampResponse_Load(j, rr.mapper);
|
c@23
|
223
|
c@24
|
224 } else if (rr.type == RequestOrResponse::Configure) {
|
c@24
|
225 rr.configurationResponse = VampJson::toVampResponse_Configure(j);
|
c@23
|
226
|
c@24
|
227 } else if (rr.type == RequestOrResponse::Process) {
|
c@24
|
228 rr.processResponse = VampJson::toVampResponse_Process(j);
|
c@23
|
229
|
c@24
|
230 } else if (rr.type == RequestOrResponse::Finish) {
|
c@24
|
231 rr.finishResponse = VampJson::toVampResponse_Finish(j);
|
c@23
|
232 }
|
c@23
|
233
|
c@23
|
234 return rr;
|
c@23
|
235 }
|
c@23
|
236
|
c@24
|
237 void
|
c@24
|
238 writeResponseJson(RequestOrResponse &rr)
|
c@24
|
239 {
|
c@24
|
240 Json j;
|
c@24
|
241
|
c@24
|
242 if (rr.type == RequestOrResponse::List) {
|
c@24
|
243 j = VampJson::fromVampResponse_List("", rr.listResponse);
|
c@24
|
244
|
c@24
|
245 } else if (rr.type == RequestOrResponse::Load) {
|
c@24
|
246 j = VampJson::fromVampResponse_Load(rr.loadResponse, rr.mapper);
|
c@24
|
247 }
|
c@24
|
248
|
c@24
|
249 cout << j.dump() << endl;
|
c@24
|
250 }
|
c@24
|
251
|
c@23
|
252 RequestOrResponse
|
c@24
|
253 readInput(string format, RequestOrResponse::Direction direction)
|
c@23
|
254 {
|
c@23
|
255 if (format == "json") {
|
c@24
|
256 if (direction == RequestOrResponse::Request) {
|
c@24
|
257 return readRequestJson();
|
c@24
|
258 } else {
|
c@24
|
259 return readResponseJson();
|
c@24
|
260 }
|
c@23
|
261 } else {
|
c@23
|
262 throw runtime_error("unknown or unimplemented format \"" + format + "\"");
|
c@23
|
263 }
|
c@23
|
264 }
|
c@23
|
265
|
c@23
|
266 void
|
c@24
|
267 writeOutput(string format, RequestOrResponse &rr)
|
c@23
|
268 {
|
c@24
|
269 if (format == "json") {
|
c@24
|
270 if (rr.direction == RequestOrResponse::Request) {
|
c@24
|
271 writeRequestJson(rr);
|
c@24
|
272 } else {
|
c@24
|
273 writeResponseJson(rr);
|
c@24
|
274 }
|
c@24
|
275 } else {
|
c@24
|
276 throw runtime_error("unknown or unimplemented format \"" + format + "\"");
|
c@24
|
277 }
|
c@23
|
278 }
|
c@23
|
279
|
c@23
|
280 int main(int argc, char **argv)
|
c@23
|
281 {
|
c@24
|
282 if (argc < 2) {
|
c@23
|
283 usage();
|
c@23
|
284 }
|
c@23
|
285
|
c@24
|
286 string informat = "json", outformat = "json";
|
c@24
|
287 RequestOrResponse::Direction direction;
|
c@24
|
288 bool haveDirection = false;
|
c@23
|
289
|
c@24
|
290 for (int i = 1; i < argc; ++i) {
|
c@23
|
291
|
c@23
|
292 string arg = argv[i];
|
c@24
|
293 bool final = (i + 1 == argc);
|
c@23
|
294
|
c@23
|
295 if (arg == "-i") {
|
c@24
|
296 if (informat != "" || final) usage();
|
c@23
|
297 else informat = argv[++i];
|
c@23
|
298
|
c@23
|
299 } else if (arg == "-o") {
|
c@24
|
300 if (outformat != "" || final) usage();
|
c@23
|
301 else outformat = argv[++i];
|
c@23
|
302
|
c@24
|
303 } else if (arg == "request") {
|
c@24
|
304 direction = RequestOrResponse::Request;
|
c@24
|
305 haveDirection = true;
|
c@24
|
306
|
c@24
|
307 } else if (arg == "response") {
|
c@24
|
308 direction = RequestOrResponse::Response;
|
c@24
|
309 haveDirection = true;
|
c@24
|
310
|
c@23
|
311 } else {
|
c@23
|
312 usage();
|
c@23
|
313 }
|
c@23
|
314 }
|
c@23
|
315
|
c@24
|
316 if (informat == "" || outformat == "" || !haveDirection) {
|
c@23
|
317 usage();
|
c@23
|
318 }
|
c@23
|
319
|
c@23
|
320 while (true) {
|
c@23
|
321
|
c@23
|
322 try {
|
c@23
|
323
|
c@24
|
324 RequestOrResponse rr = readInput(informat, direction);
|
c@23
|
325 if (rr.type == RequestOrResponse::Eof) break;
|
c@23
|
326 writeOutput(outformat, rr);
|
c@23
|
327
|
c@23
|
328 } catch (std::exception &e) {
|
c@23
|
329 cerr << "Error: " << e.what() << endl;
|
c@23
|
330 exit(1);
|
c@23
|
331 }
|
c@23
|
332 }
|
c@23
|
333
|
c@23
|
334 exit(0);
|
c@23
|
335 }
|
c@23
|
336
|
c@23
|
337
|