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
|