Mercurial > hg > piper-cpp
changeset 23:d678cd00e593
Begin vampipe-convert
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Fri, 20 May 2016 18:05:02 +0100 |
parents | b0fc4eb51547 |
children | 533ca5ca3404 |
files | Makefile capnproto/VampnProto.h capnproto/vamp.capnp utilities/json-to-capnp.cpp utilities/vampipe-convert.cpp |
diffstat | 5 files changed, 302 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Fri May 20 17:07:04 2016 +0100 +++ b/Makefile Fri May 20 18:05:02 2016 +0100 @@ -3,7 +3,10 @@ INCFLAGS := -Ivamp-plugin-sdk -Ijson -Icapnproto -I. LDFLAGS := -Lvamp-plugin-sdk -Wl,-Bstatic -lvamp-hostsdk -Wl,-Bdynamic -lcapnp -lkj -ldl -all: bin/vamp-json-cli bin/vamp-json-to-capnp +all: bin/vamp-json-cli bin/vamp-json-to-capnp bin/vampipe-convert + +bin/vampipe-convert: utilities/vampipe-convert.o json/json11/json11.o + c++ $(CXXFLAGS) $^ -o $@ $(LDFLAGS) bin/vamp-json-to-capnp: utilities/json-to-capnp.o json/json11/json11.o c++ $(CXXFLAGS) $^ -o $@ $(LDFLAGS) @@ -14,6 +17,9 @@ capnproto/vamp.capnp.h: capnproto/vamp.capnp capnp compile $< -oc++ +utilities/vampipe-convert.o: utilities/vampipe-convert.cpp capnproto/vamp.capnp.h capnproto/VampnProto.h json/VampJson.h + c++ $(CXXFLAGS) $(INCFLAGS) -c $< -o $@ + utilities/json-to-capnp.o: utilities/json-to-capnp.cpp capnproto/vamp.capnp.h capnproto/VampnProto.h json/VampJson.h c++ $(CXXFLAGS) $(INCFLAGS) -c $< -o $@
--- a/capnproto/VampnProto.h Fri May 20 17:07:04 2016 +0100 +++ b/capnproto/VampnProto.h Fri May 20 18:05:02 2016 +0100 @@ -709,7 +709,7 @@ static void buildVampResponse_Process(VampResponse::Builder &b, - const Vamp::HostExt::ProcessResponse &pr) { + const Vamp::HostExt::ProcessResponse &pr) { b.setSuccess(true); b.setErrorText(""); auto u = b.getResponse().initProcess(); @@ -717,9 +717,12 @@ } static void - buildVampRequest_Finish(VampRequest::Builder &b) { + buildVampRequest_Finish(VampRequest::Builder &b, + Vamp::Plugin *p, + PluginHandleMapper &mapper) { - b.getRequest().setFinish(); + auto u = b.getRequest().initFinish(); + u.setPluginHandle(mapper.pluginToHandle(p)); } static void
--- a/capnproto/vamp.capnp Fri May 20 17:07:04 2016 +0100 +++ b/capnproto/vamp.capnp Fri May 20 18:05:02 2016 +0100 @@ -140,6 +140,10 @@ input @1 :ProcessInput; } +struct FinishRequest { + pluginHandle @0 :Int32; +} + struct ProcessResponse { features @0 :FeatureSet; } @@ -150,7 +154,7 @@ load @1 :LoadRequest; configure @2 :ConfigurationRequest; process @3 :ProcessRequest; - finish @4 :Void; # getRemainingFeatures and unload plugin + finish @4 :FinishRequest; # getRemainingFeatures and unload } }
--- a/utilities/json-to-capnp.cpp Fri May 20 17:07:04 2016 +0100 +++ b/utilities/json-to-capnp.cpp Fri May 20 18:05:02 2016 +0100 @@ -65,10 +65,7 @@ string type = j["type"].string_value(); Json payload = j["payload"]; - if (type == "basic") { - throw VampJson::Failure("can't convert Basic block on its own"); - - } else if (type == "configurationrequest") { + if (type == "configurationrequest") { auto req = message.initRoot<ConfigurationRequest>(); PreservingPluginHandleMapper mapper; VampnProto::buildConfigurationRequest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utilities/vampipe-convert.cpp Fri May 20 18:05:02 2016 +0100 @@ -0,0 +1,283 @@ + +#include "VampJson.h" +#include "VampnProto.h" + +#include <iostream> +#include <sstream> +#include <stdexcept> + +using namespace std; +using namespace json11; +using namespace vampipe; + +// Accepting JSON objects with two fields, "type" and "payload". The +// "type" string corresponds to the JSON schema filename +// (e.g. "outputdescriptor") and the "payload" is the JSON object +// encoded with that schema. + +Json +json_input(string input) +{ + string err; + Json j = Json::parse(input, err); + if (err != "") { + throw VampJson::Failure("invalid json: " + err); + } + if (!j.is_object()) { + throw VampJson::Failure("object expected at top level"); + } + if (!j["type"].is_string()) { + throw VampJson::Failure("string expected for type field"); + } + if (!j["payload"].is_object()) { + throw VampJson::Failure("object expected for payload field"); + } + return j; +} + +class PreservingPluginHandleMapper : public PluginHandleMapper +{ +public: + PreservingPluginHandleMapper() : m_handle(0), m_plugin(0) { } + + virtual int32_t pluginToHandle(Vamp::Plugin *p) { + if (p == m_plugin) return m_handle; + else throw NotFound(); + } + + virtual Vamp::Plugin *handleToPlugin(int32_t h) { + m_handle = h; + m_plugin = reinterpret_cast<Vamp::Plugin *>(h); + return m_plugin; + } + +private: + int32_t m_handle; + Vamp::Plugin *m_plugin; +}; + +void +handle_input(::capnp::MallocMessageBuilder &message, string input) +{ + string err; + + Json j = json_input(input); + string type = j["type"].string_value(); + Json payload = j["payload"]; + + if (type == "configurationrequest") { + auto req = message.initRoot<ConfigurationRequest>(); + PreservingPluginHandleMapper mapper; + VampnProto::buildConfigurationRequest + (req, VampJson::toConfigurationRequest(payload, mapper), mapper); + + } else if (type == "configurationresponse") { + auto resp = message.initRoot<ConfigurationResponse>(); + VampnProto::buildConfigurationResponse + (resp, VampJson::toConfigurationResponse(payload)); + + } else if (type == "feature") { + auto f = message.initRoot<Feature>(); + VampnProto::buildFeature + (f, VampJson::toFeature(payload)); + + } else if (type == "featureset") { + auto fs = message.initRoot<FeatureSet>(); + VampnProto::buildFeatureSet + (fs, VampJson::toFeatureSet(payload)); + + } else if (type == "loadrequest") { + auto req = message.initRoot<LoadRequest>(); + VampnProto::buildLoadRequest + (req, VampJson::toLoadRequest(payload)); + + } else if (type == "loadresponse") { + auto resp = message.initRoot<LoadResponse>(); + PreservingPluginHandleMapper mapper; + VampnProto::buildLoadResponse + (resp, VampJson::toLoadResponse(payload, mapper), mapper); + + } else if (type == "outputdescriptor") { + auto od = message.initRoot<OutputDescriptor>(); + VampnProto::buildOutputDescriptor + (od, VampJson::toOutputDescriptor(payload)); + + } else if (type == "parameterdescriptor") { + auto pd = message.initRoot<ParameterDescriptor>(); + VampnProto::buildParameterDescriptor + (pd, VampJson::toParameterDescriptor(payload)); + + } else if (type == "pluginconfiguration") { + auto pc = message.initRoot<PluginConfiguration>(); + auto config = VampJson::toPluginConfiguration(payload); + VampnProto::buildPluginConfiguration(pc, config); + + } else if (type == "pluginstaticdata") { + auto pc = message.initRoot<PluginStaticData>(); + auto sd = VampJson::toPluginStaticData(payload); + VampnProto::buildPluginStaticData(pc, sd); + + } else if (type == "processrequest") { + auto p = message.initRoot<ProcessRequest>(); + PreservingPluginHandleMapper mapper; + VampnProto::buildProcessRequest + (p, VampJson::toProcessRequest(payload, mapper), mapper); + + } else if (type == "realtime") { + auto b = message.initRoot<RealTime>(); + VampnProto::buildRealTime + (b, VampJson::toRealTime(payload)); + + } else { + throw VampJson::Failure("unknown or unsupported JSON schema type " + + type); + } +} + +void usage() +{ + string myname = "vampipe-convert"; + cerr << "\n" << myname << + ": Convert Vamp request and response messages between formats\n\n" + " Usage: " << myname << " -i <informat> -o <outformat>\n\n" + "Where <informat> and <outformat> may be \"json\" or \"capnp\".\n" + "Messages are read from stdin and written to stdout.\n" << endl; + exit(2); +} + +class RequestOrResponse +{ +public: + enum Type { + List, Load, Configure, Process, Finish, Eof + }; + RequestOrResponse() : // nothing by default + type(Eof), + success(false), + finishPlugin(0) { } + + Type type; + bool success; + string errorText; + + PreservingPluginHandleMapper mapper; + + Vamp::HostExt::LoadRequest loadRequest; + Vamp::HostExt::LoadResponse loadResponse; + Vamp::HostExt::ConfigurationRequest configurationRequest; + Vamp::HostExt::ConfigurationResponse configurationResponse; + Vamp::HostExt::ProcessRequest processRequest; + Vamp::HostExt::ProcessResponse processResponse; + Vamp::Plugin *finishPlugin; + Vamp::HostExt::ProcessResponse finishResponse; + +}; + +RequestOrResponse +readInputJson() +{ + RequestOrResponse rr; + string input; + if (!getline(cin, input)) { + rr.type = RequestOrResponse::Eof; + return rr; + } + + Json j = json_input(input); + string type = j["type"].string_value(); + + if (type == "list") { + rr.type = RequestOrResponse::List; + + } else if (type == "load") { + //!!! ah, we need a way to know whether we're dealing with a request or response here + rr.type = RequestOrResponse::Load; + rr.loadRequest = VampJson::toLoadRequest(j["content"]); + + } else if (type == "configure") { + rr.type = RequestOrResponse::Configure; + rr.configurationRequest = + VampJson::toConfigurationRequest(j["content"], rr.mapper); + + } else if (type == "process") { + rr.type = RequestOrResponse::Process; + rr.processRequest = + VampJson::toProcessRequest(j["content"], rr.mapper); + + } else if (type == "finish") { + rr.type = RequestOrResponse::Finish; + //!!! VampJsonify + rr.finishPlugin = rr.mapper.handleToPlugin(j["content"]["pluginHandle"].int_value()); + + } else { + throw runtime_error("unknown or unexpected request/response type \"" + + type + "\""); + } + + return rr; +} + +RequestOrResponse +readInput(string format) +{ + if (format == "json") { + return readInputJson(); + } else { + throw runtime_error("unknown or unimplemented format \"" + format + "\""); + } +} + +void +writeOutput(string format, const RequestOrResponse &rr) +{ + throw runtime_error("writeOutput not implemented yet"); + +} + +int main(int argc, char **argv) +{ + if (argc != 5) { + usage(); + } + + string informat, outformat; + + for (int i = 1; i + 1 < argc; ++i) { + + string arg = argv[i]; + + if (arg == "-i") { + if (informat != "") usage(); + else informat = argv[++i]; + + } else if (arg == "-o") { + if (outformat != "") usage(); + else outformat = argv[++i]; + + } else { + usage(); + } + } + + if (informat == "" || outformat == "") { + usage(); + } + + while (true) { + + try { + + RequestOrResponse rr = readInput(informat); + if (rr.type == RequestOrResponse::Eof) break; + writeOutput(outformat, rr); + + } catch (std::exception &e) { + cerr << "Error: " << e.what() << endl; + exit(1); + } + } + + exit(0); +} + +