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