Mercurial > hg > piper-cpp
changeset 84:db9a6ab618bc
Client builds; does not run
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Wed, 12 Oct 2016 11:59:57 +0100 |
parents | 154e94ea84d4 |
children | 1b7c11bc5a88 |
files | vamp-client/Makefile vamp-client/client.cpp vamp-client/client.pro vamp-client/stub.h vamp-support/AssignedPluginHandleMapper.h vamp-support/CountingPluginHandleMapper.h |
diffstat | 6 files changed, 228 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/vamp-client/Makefile Tue Oct 11 17:08:31 2016 +0100 +++ b/vamp-client/Makefile Wed Oct 12 11:59:57 2016 +0100 @@ -36,7 +36,7 @@ DISTDIR = /home/cannam/code/piper-cpp/o/client1.0.0 LINK = g++ LFLAGS = -Wl,-O1 -Wl,-O1,--sort-common,--as-needed,-z,relro -LIBS = $(SUBLIBS) -lQt5Core -lpthread +LIBS = $(SUBLIBS) -lcapnp -lkj -lvamp-hostsdk -lQt5Core -lpthread AR = ar cqs RANLIB = SED = sed @@ -48,8 +48,10 @@ ####### Files -SOURCES = client.cpp -OBJECTS = ../o/client.o +SOURCES = client.cpp \ + ../vamp-capnp/piper.capnp.c++ +OBJECTS = ../o/client.o \ + ../o/piper.capnp.o DIST = /usr/lib/qt/mkspecs/features/spec_pre.prf \ /usr/lib/qt/mkspecs/common/unix.conf \ /usr/lib/qt/mkspecs/common/linux.conf \ @@ -203,7 +205,8 @@ /usr/lib/qt/mkspecs/features/testcase_targets.prf \ /usr/lib/qt/mkspecs/features/yacc.prf \ /usr/lib/qt/mkspecs/features/lex.prf \ - client.pro client.cpp + client.pro client.cpp \ + ../vamp-capnp/piper.capnp.c++ QMAKE_TARGET = client DESTDIR = TARGET = client @@ -540,7 +543,7 @@ distdir: FORCE @test -d $(DISTDIR) || mkdir -p $(DISTDIR) $(COPY_FILE) --parents $(DIST) $(DISTDIR)/ - $(COPY_FILE) --parents client.cpp $(DISTDIR)/ + $(COPY_FILE) --parents client.cpp ../vamp-capnp/piper.capnp.c++ $(DISTDIR)/ clean: compiler_clean @@ -583,6 +586,9 @@ ../o/client.o: client.cpp stub.h $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ../o/client.o client.cpp +../o/piper.capnp.o: ../vamp-capnp/piper.capnp.c++ ../vamp-capnp/piper.capnp.h + $(CC) -c $(CFLAGS) $(INCPATH) -o ../o/piper.capnp.o ../vamp-capnp/piper.capnp.c++ + ####### Install install: FORCE
--- a/vamp-client/client.cpp Tue Oct 11 17:08:31 2016 +0100 +++ b/vamp-client/client.cpp Wed Oct 12 11:59:57 2016 +0100 @@ -59,7 +59,7 @@ } //!!! obviously, factor out all repetitive guff - + Vamp::Plugin * load(std::string key, float inputSampleRate, int adapterFlags) { @@ -72,7 +72,7 @@ request.inputSampleRate = inputSampleRate; request.adapterFlags = adapterFlags; - ::capnp::MallocMessageBuilder message; + capnp::MallocMessageBuilder message; RpcRequest::Builder builder = message.initRoot<RpcRequest>(); VampnProto::buildRpcRequest_Load(builder, request); @@ -82,7 +82,32 @@ auto arr = messageToFlatArray(message); m_process->write(arr.asChars().begin(), arr.asChars().size()); - ///.... read... + //!!! ... --> will also need some way to kill this process + //!!! (from another thread) + + QByteArray buffer = readResponseBuffer(); + capnp::FlatArrayMessageReader responseMessage(toArrayPtr(buffer)); + RpcResponse::Reader reader = responseMessage.getRoot<RpcResponse>(); + + //!!! handle (explicit) error case + + checkResponseType(reader, RpcResponse::Response::Which::LOAD, id); + + const LoadResponse::Reader &lr = reader.getResponse().getLoad(); + + Vamp::HostExt::PluginStaticData psd; + Vamp::HostExt::PluginConfiguration defaultConfig; + VampnProto::readExtractorStaticData(psd, lr.getStaticData()); + VampnProto::readConfiguration(defaultConfig, lr.getDefaultConfiguration()); + + Vamp::Plugin *plugin = new PiperStubPlugin(this, + inputSampleRate, + psd, + defaultConfig); + + m_mapper.addPlugin(lr.getHandle(), plugin); + + return plugin; }; virtual @@ -98,35 +123,202 @@ request.plugin = plugin; request.configuration = config; - ::capnp::MallocMessageBuilder message; + capnp::MallocMessageBuilder message; RpcRequest::Builder builder = message.initRoot<RpcRequest>(); VampnProto::buildRpcRequest_Configure(builder, request, m_mapper); ReqId id = getId(); builder.getId().setNumber(id); + + auto arr = messageToFlatArray(message); + m_process->write(arr.asChars().begin(), arr.asChars().size()); + + QByteArray buffer = readResponseBuffer(); + capnp::FlatArrayMessageReader responseMessage(toArrayPtr(buffer)); + RpcResponse::Reader reader = responseMessage.getRoot<RpcResponse>(); - //!!! now what? + //!!! handle (explicit) error case + + checkResponseType(reader, RpcResponse::Response::Which::CONFIGURE, id); + + Vamp::HostExt::ConfigurationResponse cr; + VampnProto::readConfigurationResponse(cr, + reader.getResponse().getConfigure(), + m_mapper); + + return cr.outputs; }; - virtual Vamp::Plugin::FeatureSet process(PiperStubPlugin *plugin, - const float *const *inputBuffers, - Vamp::RealTime timestamp) = 0; + std::vector<std::vector<float> > inputBuffers, + Vamp::RealTime timestamp) { + + if (!m_process) { + throw std::runtime_error("Piper server failed to start"); + } + + Vamp::HostExt::ProcessRequest request; + request.plugin = plugin; + request.inputBuffers = inputBuffers; + request.timestamp = timestamp; + + capnp::MallocMessageBuilder message; + RpcRequest::Builder builder = message.initRoot<RpcRequest>(); + + VampnProto::buildRpcRequest_Process(builder, request, m_mapper); + ReqId id = getId(); + builder.getId().setNumber(id); + + auto arr = messageToFlatArray(message); + m_process->write(arr.asChars().begin(), arr.asChars().size()); + + QByteArray buffer = readResponseBuffer(); + capnp::FlatArrayMessageReader responseMessage(toArrayPtr(buffer)); + RpcResponse::Reader reader = responseMessage.getRoot<RpcResponse>(); + + //!!! handle (explicit) error case + + checkResponseType(reader, RpcResponse::Response::Which::PROCESS, id); + + Vamp::HostExt::ProcessResponse pr; + VampnProto::readProcessResponse(pr, + reader.getResponse().getProcess(), + m_mapper); + + return pr.features; + } virtual Vamp::Plugin::FeatureSet - finish(PiperStubPlugin *plugin) = 0; + finish(PiperStubPlugin *plugin) { + + if (!m_process) { + throw std::runtime_error("Piper server failed to start"); + } + + Vamp::HostExt::FinishRequest request; + request.plugin = plugin; + + capnp::MallocMessageBuilder message; + RpcRequest::Builder builder = message.initRoot<RpcRequest>(); + + VampnProto::buildRpcRequest_Finish(builder, request, m_mapper); + ReqId id = getId(); + builder.getId().setNumber(id); + + auto arr = messageToFlatArray(message); + m_process->write(arr.asChars().begin(), arr.asChars().size()); + + QByteArray buffer = readResponseBuffer(); + capnp::FlatArrayMessageReader responseMessage(toArrayPtr(buffer)); + RpcResponse::Reader reader = responseMessage.getRoot<RpcResponse>(); + + //!!! handle (explicit) error case + + checkResponseType(reader, RpcResponse::Response::Which::FINISH, id); + + Vamp::HostExt::ProcessResponse pr; + VampnProto::readFinishResponse(pr, + reader.getResponse().getFinish(), + m_mapper); + + m_mapper.removePlugin(m_mapper.pluginToHandle(plugin)); + delete plugin; + + return pr.features; + } private: QProcess *m_process; AssignedPluginHandleMapper m_mapper; - int getId() { + ReqId getId() { //!!! todo: mutex static ReqId m_nextId = 0; return m_nextId++; } + + kj::ArrayPtr<const capnp::word> + toArrayPtr(QByteArray arr) { + size_t wordSize = sizeof(capnp::word); + capnp::word *dptr = reinterpret_cast<capnp::word *>(arr.data()); + kj::ArrayPtr<const capnp::word> kptr(dptr, arr.size() / wordSize); + return kptr; + } + + QByteArray + readResponseBuffer() { + + QByteArray buffer; + size_t wordSize = sizeof(capnp::word); + bool complete = false; + + while (!complete) { + + m_process->waitForReadyRead(1000); + qint64 byteCount = m_process->bytesAvailable(); + qint64 wordCount = byteCount / wordSize; + + if (!wordCount) { + if (m_process->state() == QProcess::NotRunning) { + cerr << "ERROR: Subprocess exited: Load failed" << endl; + throw std::runtime_error("Piper server exited unexpectedly"); + } + } else { + buffer.append(m_process->read(wordCount * wordSize)); + size_t haveWords = buffer.size() / wordSize; + size_t expectedWords = + capnp::expectedSizeInWordsFromPrefix(toArrayPtr(buffer)); + + cerr << "haveWords = " << haveWords << ", expectedWords = " << expectedWords << endl; + + if (haveWords >= expectedWords) { + if (haveWords > expectedWords) { + cerr << "WARNING: obtained more data than expected (" + << haveWords << " words, expected " << expectedWords + << ")" << endl; + } + complete = true; + } + } + } + + return buffer; + } + + void + checkResponseType(const RpcResponse::Reader &r, + RpcResponse::Response::Which type, + ReqId id) { + + if (r.getResponse().which() != type) { + throw std::runtime_error("Wrong response type"); + } + if (ReqId(r.getId().getNumber()) != id) { + throw std::runtime_error("Wrong response id"); + } + } }; } +int main(int, char **) +{ + piper::PiperClient client; + Vamp::Plugin *plugin = client.load("vamp-example-plugins:zerocrossing", 16, 0); + if (!plugin->initialise(1, 4, 4)) { + cerr << "initialisation failed" << endl; + } else { + std::vector<float> buf = { 1.0, -1.0, 1.0, -1.0 }; + float *bd = buf.data(); + Vamp::Plugin::FeatureSet features = plugin->process + (&bd, Vamp::RealTime::zeroTime); + cerr << "results for output 0:" << endl; + auto fl(features[0]); + for (const auto &f: fl) { + cerr << f.values[0] << endl; + } + } + delete plugin; +} +
--- a/vamp-client/client.pro Tue Oct 11 17:08:31 2016 +0100 +++ b/vamp-client/client.pro Wed Oct 12 11:59:57 2016 +0100 @@ -16,6 +16,8 @@ QMAKE_CXXFLAGS = -I$$VAMPSDK_DIR -I.. +LIBS += -lcapnp -lkj -lvamp-hostsdk + # Using the "console" CONFIG flag above should ensure this happens for # normal Windows builds, but this may be necessary when cross-compiling win32-x-g++:QMAKE_LFLAGS += -Wl,-subsystem,console @@ -23,5 +25,5 @@ TARGET = client SOURCES += \ - client.cpp + client.cpp ../vamp-capnp/piper.capnp.c++
--- a/vamp-client/stub.h Tue Oct 11 17:08:31 2016 +0100 +++ b/vamp-client/stub.h Wed Oct 12 11:59:57 2016 +0100 @@ -21,7 +21,7 @@ virtual Vamp::Plugin::FeatureSet process(PiperStubPlugin *plugin, - const float *const *inputBuffers, + std::vector<std::vector<float> > inputBuffers, Vamp::RealTime timestamp) = 0; virtual Vamp::Plugin::FeatureSet @@ -189,7 +189,15 @@ throw std::logic_error("Plugin has already been disposed of"); } - return m_client->process(this, inputBuffers, timestamp); + //!!! ew + std::vector<std::vector<float> > vecbuf; + for (int c = 0; c < m_config.channelCount; ++c) { + vecbuf.push_back(std::vector<float> + (inputBuffers[c], + inputBuffers[c] + m_config.blockSize)); + } + + return m_client->process(this, vecbuf, timestamp); } virtual FeatureSet getRemainingFeatures() {
--- a/vamp-support/AssignedPluginHandleMapper.h Tue Oct 11 17:08:31 2016 +0100 +++ b/vamp-support/AssignedPluginHandleMapper.h Wed Oct 12 11:59:57 2016 +0100 @@ -50,7 +50,7 @@ public: AssignedPluginHandleMapper() { } - void addPlugin(Vamp::Plugin *p, Handle h) { + void addPlugin(Handle h, Vamp::Plugin *p) { if (!p) return; if (m_rplugins.find(p) == m_rplugins.end()) { if (m_plugins.find(h) != m_plugins.end()) {
--- a/vamp-support/CountingPluginHandleMapper.h Tue Oct 11 17:08:31 2016 +0100 +++ b/vamp-support/CountingPluginHandleMapper.h Wed Oct 12 11:59:57 2016 +0100 @@ -51,7 +51,7 @@ void addPlugin(Vamp::Plugin *p) { Handle h = m_nextHandle++; - m_sub.addPlugin(p, h); + m_sub.addPlugin(h, p); } void removePlugin(Handle h) {