annotate utilities/vampipe-server.cpp @ 32:2d97883d20df

Wire up a couple of server actions
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 24 May 2016 17:17:03 +0100
parents b376ab0ce003
children 0b48b10140bb
rev   line source
c@31 1
c@31 2 #include "VampnProto.h"
c@31 3
c@31 4 #include "bits/RequestOrResponse.h"
c@31 5
c@31 6 #include <iostream>
c@31 7 #include <sstream>
c@31 8 #include <stdexcept>
c@31 9
c@32 10 #include <map>
c@32 11 #include <set>
c@32 12
c@31 13 using namespace std;
c@31 14 using namespace vampipe;
c@32 15 using namespace Vamp;
c@32 16 using namespace Vamp::HostExt;
c@31 17
c@31 18 void usage()
c@31 19 {
c@31 20 string myname = "vampipe-server";
c@31 21 cerr << "\n" << myname <<
c@31 22 ": Load and run Vamp plugins in response to messages from stdin\n\n"
c@31 23 " Usage: " << myname << "\n\n"
c@31 24 "Expects Vamp request messages in Cap'n Proto packed format on stdin,\n"
c@31 25 "and writes Vamp response messages in the same format to stdout.\n\n";
c@31 26
c@31 27 exit(2);
c@31 28 }
c@31 29
c@32 30 class Mapper : public PluginHandleMapper
c@32 31 {
c@32 32 public:
c@32 33 Mapper() : m_nextHandle(1) { }
c@32 34
c@32 35 void addPlugin(Plugin *p) {
c@32 36 if (m_rplugins.find(p) == m_rplugins.end()) {
c@32 37 int32_t h = m_nextHandle++;
c@32 38 m_plugins[h] = p;
c@32 39 m_rplugins[p] = h;
c@32 40 }
c@32 41 }
c@32 42
c@32 43 int32_t pluginToHandle(Plugin *p) {
c@32 44 if (m_rplugins.find(p) == m_rplugins.end()) {
c@32 45 throw NotFound();
c@32 46 }
c@32 47 return m_rplugins[p];
c@32 48 }
c@32 49
c@32 50 Plugin *handleToPlugin(int32_t h) {
c@32 51 if (m_plugins.find(h) == m_plugins.end()) {
c@32 52 throw NotFound();
c@32 53 }
c@32 54 return m_plugins[h];
c@32 55 }
c@32 56
c@32 57 bool isInitialised(int32_t h) {
c@32 58 return m_initialisedPlugins.find(h) != m_initialisedPlugins.end();
c@32 59 }
c@32 60
c@32 61 void markInitialised(int32_t h) {
c@32 62 m_initialisedPlugins.insert(h);
c@32 63 }
c@32 64
c@32 65 private:
c@32 66 int32_t m_nextHandle; // NB plugin handle type must fit in JSON number
c@32 67 map<uint32_t, Plugin *> m_plugins;
c@32 68 map<Plugin *, uint32_t> m_rplugins;
c@32 69 set<uint32_t> m_initialisedPlugins;
c@32 70 };
c@32 71
c@32 72 static Mapper mapper;
c@32 73
c@31 74 RequestOrResponse
c@31 75 readRequestCapnp()
c@31 76 {
c@31 77 RequestOrResponse rr;
c@31 78 rr.direction = RequestOrResponse::Request;
c@31 79
c@31 80 ::capnp::PackedFdMessageReader message(0); // stdin
c@31 81 VampRequest::Reader reader = message.getRoot<VampRequest>();
c@31 82
c@31 83 rr.type = VampnProto::getRequestResponseType(reader);
c@31 84
c@31 85 switch (rr.type) {
c@31 86
c@31 87 case RRType::List:
c@31 88 VampnProto::readVampRequest_List(reader); // type check only
c@31 89 break;
c@31 90 case RRType::Load:
c@31 91 VampnProto::readVampRequest_Load(rr.loadRequest, reader);
c@31 92 break;
c@31 93 case RRType::Configure:
c@32 94 VampnProto::readVampRequest_Configure(rr.configurationRequest,
c@32 95 reader, mapper);
c@31 96 break;
c@31 97 case RRType::Process:
c@32 98 VampnProto::readVampRequest_Process(rr.processRequest, reader, mapper);
c@31 99 break;
c@31 100 case RRType::Finish:
c@32 101 VampnProto::readVampRequest_Finish(rr.finishPlugin, reader, mapper);
c@31 102 break;
c@31 103 case RRType::NotValid:
c@31 104 break;
c@31 105 }
c@31 106
c@31 107 return rr;
c@31 108 }
c@31 109
c@31 110 void
c@31 111 writeResponseCapnp(RequestOrResponse &rr)
c@31 112 {
c@31 113 ::capnp::MallocMessageBuilder message;
c@31 114 VampResponse::Builder builder = message.initRoot<VampResponse>();
c@31 115
c@31 116 switch (rr.type) {
c@31 117
c@31 118 case RRType::List:
c@31 119 VampnProto::buildVampResponse_List(builder, "", rr.listResponse);
c@31 120 break;
c@31 121 case RRType::Load:
c@32 122 VampnProto::buildVampResponse_Load(builder, rr.loadResponse, mapper);
c@31 123 break;
c@31 124 case RRType::Configure:
c@31 125 VampnProto::buildVampResponse_Configure(builder, rr.configurationResponse);
c@31 126 break;
c@31 127 case RRType::Process:
c@31 128 VampnProto::buildVampResponse_Process(builder, rr.processResponse);
c@31 129 break;
c@31 130 case RRType::Finish:
c@31 131 VampnProto::buildVampResponse_Finish(builder, rr.finishResponse);
c@31 132 break;
c@31 133 case RRType::NotValid:
c@31 134 break;
c@31 135 }
c@31 136
c@31 137 writePackedMessageToFd(1, message);
c@31 138 }
c@31 139
c@31 140 RequestOrResponse
c@31 141 processRequest(const RequestOrResponse &request)
c@31 142 {
c@31 143 RequestOrResponse response;
c@31 144 response.direction = RequestOrResponse::Response;
c@32 145 response.type = request.type;
c@32 146
c@32 147 auto loader = PluginLoader::getInstance();
c@32 148
c@32 149 switch (request.type) {
c@32 150
c@32 151 case RRType::List:
c@32 152 response.listResponse = loader->listPluginData();
c@32 153 response.success = true;
c@32 154 break;
c@32 155
c@32 156 case RRType::Load:
c@32 157 response.loadResponse = loader->loadPlugin(request.loadRequest);
c@32 158 if (response.loadResponse.plugin != nullptr) {
c@32 159 mapper.addPlugin(response.loadResponse.plugin);
c@32 160 response.success = true;
c@32 161 }
c@32 162 break;
c@32 163
c@32 164 default:
c@32 165 //!!!
c@32 166 ;
c@32 167 }
c@32 168
c@31 169 return response;
c@31 170 }
c@31 171
c@31 172 int main(int argc, char **argv)
c@31 173 {
c@31 174 if (argc != 1) {
c@31 175 usage();
c@31 176 }
c@31 177
c@31 178 while (true) {
c@31 179
c@31 180 try {
c@31 181
c@31 182 RequestOrResponse request = readRequestCapnp();
c@31 183
c@31 184 // NotValid without an exception indicates EOF:
c@31 185
c@31 186 //!!! not yet it doesn't -- have to figure out how to
c@31 187 //!!! handle this with capnp
c@31 188 if (request.type == RRType::NotValid) break;
c@31 189
c@31 190 RequestOrResponse response = processRequest(request);
c@31 191
c@31 192 writeResponseCapnp(response);
c@31 193
c@31 194 } catch (std::exception &e) {
c@31 195 cerr << "Error: " << e.what() << endl;
c@31 196 exit(1);
c@31 197 }
c@31 198 }
c@31 199
c@31 200 exit(0);
c@31 201 }