Mercurial > hg > piper-cpp
changeset 92:21f8af53eaf0
Reorganise some classes
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 13 Oct 2016 12:02:44 +0100 |
parents | c897c9a8daf1 |
children | fbce91785d35 |
files | vamp-client/CapnpMessageCompletenessChecker.h vamp-client/Makefile vamp-client/PipedQProcessTransport.h vamp-client/PiperCapnpClient.h vamp-client/PiperClient.h vamp-client/PiperPluginStub.h vamp-client/PiperStubPlugin.h vamp-client/SynchronousTransport.h vamp-client/client.cpp vamp-client/client.pro vamp-server/server.cpp |
diffstat | 11 files changed, 327 insertions(+), 329 deletions(-) [+] |
line wrap: on
line diff
--- a/vamp-client/CapnpMessageCompletenessChecker.h Thu Oct 13 11:33:19 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ - -#ifndef CAPNP_MESSAGE_COMPLETENESS_CHECKER_H -#define CAPNP_MESSAGE_COMPLETENESS_CHECKER_H - -#include "SynchronousTransport.h" //!!! - -#include <capnp/serialize.h> - -#include <iostream> - -namespace piper { //!!! change - -class CapnpMessageCompletenessChecker : public MessageCompletenessChecker -{ -public: - bool isComplete(const std::vector<char> &message) const override { - - // a bit liberal with the copies here - size_t wordSize = sizeof(capnp::word); - size_t words = message.size() / wordSize; - kj::Array<capnp::word> karr(kj::heapArray<capnp::word>(words)); - memcpy(karr.begin(), message.data(), words * wordSize); - - size_t expected = capnp::expectedSizeInWordsFromPrefix(karr); - - if (words > expected) { - std::cerr << "WARNING: obtained more data than expected (" - << words << " " << wordSize << "-byte words, expected " - << expected << ")" << std::endl; - } - - return words >= expected; - } -}; - -} - -#endif
--- a/vamp-client/Makefile Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/Makefile Thu Oct 13 12:02:44 2016 +0100 @@ -205,11 +205,10 @@ /usr/lib/qt/mkspecs/features/testcase_targets.prf \ /usr/lib/qt/mkspecs/features/yacc.prf \ /usr/lib/qt/mkspecs/features/lex.prf \ - client.pro CapnpMessageCompletenessChecker.h \ - PipedQProcessTransport.h \ + client.pro PipedQProcessTransport.h \ PiperCapnpClient.h \ PiperClient.h \ - PiperStubPlugin.h \ + PiperPluginStub.h \ SynchronousTransport.h client.cpp \ ../vamp-capnp/piper.capnp.c++ QMAKE_TARGET = client @@ -548,7 +547,7 @@ distdir: FORCE @test -d $(DISTDIR) || mkdir -p $(DISTDIR) $(COPY_FILE) --parents $(DIST) $(DISTDIR)/ - $(COPY_FILE) --parents CapnpMessageCompletenessChecker.h PipedQProcessTransport.h PiperCapnpClient.h PiperClient.h PiperStubPlugin.h SynchronousTransport.h $(DISTDIR)/ + $(COPY_FILE) --parents PipedQProcessTransport.h PiperCapnpClient.h PiperClient.h PiperPluginStub.h SynchronousTransport.h $(DISTDIR)/ $(COPY_FILE) --parents client.cpp ../vamp-capnp/piper.capnp.c++ $(DISTDIR)/ @@ -589,11 +588,11 @@ ####### Compile -../o/client.o: client.cpp PiperClient.h \ - PiperStubPlugin.h \ - CapnpMessageCompletenessChecker.h \ +../o/client.o: client.cpp PipedQProcessTransport.h \ SynchronousTransport.h \ - PipedQProcessTransport.h + PiperCapnpClient.h \ + PiperClient.h \ + PiperPluginStub.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
--- a/vamp-client/PipedQProcessTransport.h Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/PipedQProcessTransport.h Thu Oct 13 12:02:44 2016 +0100 @@ -14,9 +14,8 @@ class PipedQProcessTransport : public SynchronousTransport { public: - PipedQProcessTransport(QString processName, - MessageCompletenessChecker *checker) : //!!! ownership - m_completenessChecker(checker) { + PipedQProcessTransport(QString processName) : + m_completenessChecker(0) { m_process = new QProcess(); m_process->setReadChannel(QProcess::StandardOutput); m_process->setProcessChannelMode(QProcess::ForwardedErrorChannel); @@ -41,47 +40,47 @@ } } - bool isOK() const override { + void + setCompletenessChecker(MessageCompletenessChecker *checker) { + //!!! ownership? + m_completenessChecker = checker; + } + + bool + isOK() const override { return m_process != nullptr; } std::vector<char> call(const char *ptr, size_t size) override { + if (!m_completenessChecker) { + throw std::logic_error("No completeness checker set on transport"); + } + m_process->write(ptr, size); std::vector<char> 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 (!byteCount) { if (m_process->state() == QProcess::NotRunning) { std::cerr << "ERROR: Subprocess exited: Load failed" << std::endl; throw std::runtime_error("Piper server exited unexpectedly"); } } else { - // only read whole words - byteCount = wordCount * wordSize; size_t formerSize = buffer.size(); buffer.resize(formerSize + byteCount); m_process->read(buffer.data() + formerSize, byteCount); complete = m_completenessChecker->isComplete(buffer); } } -/* - cerr << "buffer = "; - for (int i = 0; i < buffer.size(); ++i) { - if (i % 16 == 0) cerr << "\n"; - cerr << int(buffer[i]) << " "; - } - cerr << "\n"; -*/ + return buffer; }
--- a/vamp-client/PiperCapnpClient.h Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/PiperCapnpClient.h Thu Oct 13 12:02:44 2016 +0100 @@ -3,24 +3,47 @@ #define PIPER_CAPNP_CLIENT_H #include "PiperClient.h" +#include "PiperPluginStub.h" #include "SynchronousTransport.h" #include "vamp-support/AssignedPluginHandleMapper.h" #include "vamp-capnp/VampnProto.h" +#include <capnp/serialize.h> + namespace piper { //!!! change -class PiperCapnpClient : public PiperStubPluginClientInterface +class PiperCapnpClient : public PiperPluginClientInterface, + public PiperLoaderInterface { // unsigned to avoid undefined behaviour on possible wrap typedef uint32_t ReqId; + + class CompletenessChecker : public MessageCompletenessChecker { + public: + bool isComplete(const std::vector<char> &message) const override { + auto karr = toKJArray(message); + size_t words = karr.size(); + size_t expected = capnp::expectedSizeInWordsFromPrefix(karr); + if (words > expected) { + std::cerr << "WARNING: obtained more data than expected (" + << words << " " << sizeof(capnp::word) + << "-byte words, expected " + << expected << ")" << std::endl; + } + return words >= expected; + } + }; public: PiperCapnpClient(SynchronousTransport *transport) : //!!! ownership? shared ptr? - m_transport(transport) { + m_transport(transport), + m_completenessChecker(new CompletenessChecker) { + transport->setCompletenessChecker(m_completenessChecker); } ~PiperCapnpClient() { + delete m_completenessChecker; } //!!! obviously, factor out all repetitive guff @@ -41,7 +64,7 @@ PluginHandleMapper::Handle handle = serverLoad(key, inputSampleRate, adapterFlags, psd, defaultConfig); - Vamp::Plugin *plugin = new PiperStubPlugin(this, + Vamp::Plugin *plugin = new PiperPluginStub(this, key, inputSampleRate, adapterFlags, @@ -95,7 +118,7 @@ protected: virtual Vamp::Plugin::OutputList - configure(PiperStubPlugin *plugin, + configure(PiperPluginStub *plugin, Vamp::HostExt::PluginConfiguration config) override { if (!m_transport->isOK()) { @@ -134,7 +157,7 @@ virtual Vamp::Plugin::FeatureSet - process(PiperStubPlugin *plugin, + process(PiperPluginStub *plugin, std::vector<std::vector<float> > inputBuffers, Vamp::RealTime timestamp) override { @@ -174,7 +197,7 @@ } virtual Vamp::Plugin::FeatureSet - finish(PiperStubPlugin *plugin) override { + finish(PiperPluginStub *plugin) override { if (!m_transport->isOK()) { throw std::runtime_error("Piper server failed to start"); @@ -215,7 +238,7 @@ } virtual void - reset(PiperStubPlugin *plugin, + reset(PiperPluginStub *plugin, Vamp::HostExt::PluginConfiguration config) override { // Reload the plugin on the server side, and configure it as requested @@ -249,6 +272,7 @@ return m_nextId++; } + static kj::Array<capnp::word> toKJArray(const std::vector<char> &buffer) { // We could do this whole thing with fewer copies, but let's @@ -275,6 +299,7 @@ private: SynchronousTransport *m_transport; //!!! I don't own this, but should I? + CompletenessChecker *m_completenessChecker; // I own this }; }
--- a/vamp-client/PiperClient.h Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/PiperClient.h Thu Oct 13 12:02:44 2016 +0100 @@ -6,30 +6,38 @@ namespace piper { //!!! change -class PiperStubPlugin; +class PiperPluginStub; -class PiperStubPluginClientInterface +class PiperLoaderInterface { - friend class PiperStubPlugin; +public: + virtual + Vamp::Plugin * + load(std::string key, float inputSampleRate, int adapterFlags) = 0; +}; + +class PiperPluginClientInterface +{ + friend class PiperPluginStub; protected: virtual Vamp::Plugin::OutputList - configure(PiperStubPlugin *plugin, + configure(PiperPluginStub *plugin, Vamp::HostExt::PluginConfiguration config) = 0; virtual Vamp::Plugin::FeatureSet - process(PiperStubPlugin *plugin, + process(PiperPluginStub *plugin, std::vector<std::vector<float> > inputBuffers, Vamp::RealTime timestamp) = 0; virtual Vamp::Plugin::FeatureSet - finish(PiperStubPlugin *plugin) = 0; + finish(PiperPluginStub *plugin) = 0; virtual void - reset(PiperStubPlugin *plugin, + reset(PiperPluginStub *plugin, Vamp::HostExt::PluginConfiguration config) = 0; };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/PiperPluginStub.h Thu Oct 13 12:02:44 2016 +0100 @@ -0,0 +1,240 @@ + +#ifndef PIPER_STUB_PLUGIN_H +#define PIPER_STUB_PLUGIN_H + +#include <vamp-hostsdk/Plugin.h> +#include <vamp-hostsdk/PluginLoader.h> +#include <vamp-hostsdk/PluginStaticData.h> +#include <vamp-hostsdk/PluginConfiguration.h> + +#include <cstdint> + +#include "PiperClient.h" + +namespace piper { //!!! should be something else + +class PiperPluginStub : public Vamp::Plugin +{ + enum State { + Loaded, Configured, Finished + }; + +public: + PiperPluginStub(PiperPluginClientInterface *client, + std::string pluginKey, + float inputSampleRate, + int adapterFlags, + Vamp::HostExt::PluginStaticData psd, + Vamp::HostExt::PluginConfiguration defaultConfig) : + Plugin(inputSampleRate), + m_client(client), + m_key(pluginKey), + m_adapterFlags(adapterFlags), + m_state(Loaded), + m_psd(psd), + m_defaultConfig(defaultConfig), + m_config(defaultConfig) + { } + + virtual ~PiperPluginStub() { + if (m_state != Finished) { + (void)m_client->finish(this); + } + } + + virtual std::string getIdentifier() const { + return m_psd.basic.identifier; + } + + virtual std::string getName() const { + return m_psd.basic.name; + } + + virtual std::string getDescription() const { + return m_psd.basic.description; + } + + virtual std::string getMaker() const { + return m_psd.maker; + } + + virtual std::string getCopyright() const { + return m_psd.copyright; + } + + virtual int getPluginVersion() const { + return m_psd.pluginVersion; + } + + virtual ParameterList getParameterDescriptors() const { + return m_psd.parameters; + } + + virtual float getParameter(std::string name) const { + if (m_config.parameterValues.find(name) != m_config.parameterValues.end()) { + return m_config.parameterValues.at(name); + } else { + return 0.f; + } + } + + virtual void setParameter(std::string name, float value) { + if (m_state != Loaded) { + throw std::logic_error("Can't set parameter after plugin initialised"); + } + m_config.parameterValues[name] = value; + } + + virtual ProgramList getPrograms() const { + return m_psd.programs; + } + + virtual std::string getCurrentProgram() const { + return m_config.currentProgram; + } + + virtual void selectProgram(std::string program) { + if (m_state != Loaded) { + throw std::logic_error("Can't select program after plugin initialised"); + } + m_config.currentProgram = program; + } + + virtual bool initialise(size_t inputChannels, + size_t stepSize, + size_t blockSize) { + + if (m_state != Loaded) { + throw std::logic_error("Plugin has already been initialised"); + } + + m_config.channelCount = inputChannels; + m_config.stepSize = stepSize; + m_config.blockSize = blockSize; + + m_outputs = m_client->configure(this, m_config); + + if (!m_outputs.empty()) { + m_state = Configured; + return true; + } else { + return false; + } + } + + virtual void reset() { + + if (m_state == Loaded) { + // reset is a no-op if the plugin hasn't been initialised yet + return; + } + + m_client->reset(this, m_config); + + m_state = Configured; + } + + virtual InputDomain getInputDomain() const { + return m_psd.inputDomain; + } + + virtual size_t getPreferredBlockSize() const { + return m_defaultConfig.blockSize; + } + + virtual size_t getPreferredStepSize() const { + return m_defaultConfig.stepSize; + } + + virtual size_t getMinChannelCount() const { + return m_psd.minChannelCount; + } + + virtual size_t getMaxChannelCount() const { + return m_psd.maxChannelCount; + } + + virtual OutputList getOutputDescriptors() const { + if (m_state == Configured) { + return m_outputs; + } + + //!!! todo: figure out for which hosts (and adapters?) it may + //!!! be a problem that the output descriptors are incomplete + //!!! here. Any such hosts/adapters are broken, but I bet they + //!!! exist + + OutputList staticOutputs; + for (const auto &o: m_psd.basicOutputInfo) { + OutputDescriptor od; + od.identifier = o.identifier; + od.name = o.name; + od.description = o.description; + staticOutputs.push_back(od); + } + return staticOutputs; + } + + virtual FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp) { + + if (m_state == Loaded) { + throw std::logic_error("Plugin has not been initialised"); + } + if (m_state == Finished) { + throw std::logic_error("Plugin has already been disposed of"); + } + + //!!! 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() { + + if (m_state == Loaded) { + throw std::logic_error("Plugin has not been configured"); + } + if (m_state == Finished) { + throw std::logic_error("Plugin has already been disposed of"); + } + + m_state = Finished; + + return m_client->finish(this); + } + + // Not Plugin methods, but needed by the PiperClient to support reloads: + + virtual float getInputSampleRate() const { + return m_inputSampleRate; + } + + virtual std::string getPluginKey() const { + return m_key; + } + + virtual int getAdapterFlags() const { + return m_adapterFlags; + } + +private: + PiperPluginClientInterface *m_client; + std::string m_key; + int m_adapterFlags; + State m_state; + Vamp::HostExt::PluginStaticData m_psd; + OutputList m_outputs; + Vamp::HostExt::PluginConfiguration m_defaultConfig; + Vamp::HostExt::PluginConfiguration m_config; +}; + +} + +#endif
--- a/vamp-client/PiperStubPlugin.h Thu Oct 13 11:33:19 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,240 +0,0 @@ - -#ifndef PIPER_STUB_PLUGIN_H -#define PIPER_STUB_PLUGIN_H - -#include <vamp-hostsdk/Plugin.h> -#include <vamp-hostsdk/PluginLoader.h> -#include <vamp-hostsdk/PluginStaticData.h> -#include <vamp-hostsdk/PluginConfiguration.h> - -#include <cstdint> - -#include "PiperClient.h" - -namespace piper { //!!! should be something else - -class PiperStubPlugin : public Vamp::Plugin -{ - enum State { - Loaded, Configured, Finished - }; - -public: - PiperStubPlugin(PiperStubPluginClientInterface *client, - std::string pluginKey, - float inputSampleRate, - int adapterFlags, - Vamp::HostExt::PluginStaticData psd, - Vamp::HostExt::PluginConfiguration defaultConfig) : - Plugin(inputSampleRate), - m_client(client), - m_key(pluginKey), - m_adapterFlags(adapterFlags), - m_state(Loaded), - m_psd(psd), - m_defaultConfig(defaultConfig), - m_config(defaultConfig) - { } - - virtual ~PiperStubPlugin() { - if (m_state != Finished) { - (void)m_client->finish(this); - } - } - - virtual std::string getIdentifier() const { - return m_psd.basic.identifier; - } - - virtual std::string getName() const { - return m_psd.basic.name; - } - - virtual std::string getDescription() const { - return m_psd.basic.description; - } - - virtual std::string getMaker() const { - return m_psd.maker; - } - - virtual std::string getCopyright() const { - return m_psd.copyright; - } - - virtual int getPluginVersion() const { - return m_psd.pluginVersion; - } - - virtual ParameterList getParameterDescriptors() const { - return m_psd.parameters; - } - - virtual float getParameter(std::string name) const { - if (m_config.parameterValues.find(name) != m_config.parameterValues.end()) { - return m_config.parameterValues.at(name); - } else { - return 0.f; - } - } - - virtual void setParameter(std::string name, float value) { - if (m_state != Loaded) { - throw std::logic_error("Can't set parameter after plugin initialised"); - } - m_config.parameterValues[name] = value; - } - - virtual ProgramList getPrograms() const { - return m_psd.programs; - } - - virtual std::string getCurrentProgram() const { - return m_config.currentProgram; - } - - virtual void selectProgram(std::string program) { - if (m_state != Loaded) { - throw std::logic_error("Can't select program after plugin initialised"); - } - m_config.currentProgram = program; - } - - virtual bool initialise(size_t inputChannels, - size_t stepSize, - size_t blockSize) { - - if (m_state != Loaded) { - throw std::logic_error("Plugin has already been initialised"); - } - - m_config.channelCount = inputChannels; - m_config.stepSize = stepSize; - m_config.blockSize = blockSize; - - m_outputs = m_client->configure(this, m_config); - - if (!m_outputs.empty()) { - m_state = Configured; - return true; - } else { - return false; - } - } - - virtual void reset() { - - if (m_state == Loaded) { - // reset is a no-op if the plugin hasn't been initialised yet - return; - } - - m_client->reset(this, m_config); - - m_state = Configured; - } - - virtual InputDomain getInputDomain() const { - return m_psd.inputDomain; - } - - virtual size_t getPreferredBlockSize() const { - return m_defaultConfig.blockSize; - } - - virtual size_t getPreferredStepSize() const { - return m_defaultConfig.stepSize; - } - - virtual size_t getMinChannelCount() const { - return m_psd.minChannelCount; - } - - virtual size_t getMaxChannelCount() const { - return m_psd.maxChannelCount; - } - - virtual OutputList getOutputDescriptors() const { - if (m_state == Configured) { - return m_outputs; - } - - //!!! todo: figure out for which hosts (and adapters?) it may - //!!! be a problem that the output descriptors are incomplete - //!!! here. Any such hosts/adapters are broken, but I bet they - //!!! exist - - OutputList staticOutputs; - for (const auto &o: m_psd.basicOutputInfo) { - OutputDescriptor od; - od.identifier = o.identifier; - od.name = o.name; - od.description = o.description; - staticOutputs.push_back(od); - } - return staticOutputs; - } - - virtual FeatureSet process(const float *const *inputBuffers, - Vamp::RealTime timestamp) { - - if (m_state == Loaded) { - throw std::logic_error("Plugin has not been initialised"); - } - if (m_state == Finished) { - throw std::logic_error("Plugin has already been disposed of"); - } - - //!!! 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() { - - if (m_state == Loaded) { - throw std::logic_error("Plugin has not been configured"); - } - if (m_state == Finished) { - throw std::logic_error("Plugin has already been disposed of"); - } - - m_state = Finished; - - return m_client->finish(this); - } - - // Not Plugin methods, but needed by the PiperClient to support reloads: - - virtual float getInputSampleRate() const { - return m_inputSampleRate; - } - - virtual std::string getPluginKey() const { - return m_key; - } - - virtual int getAdapterFlags() const { - return m_adapterFlags; - } - -private: - PiperStubPluginClientInterface *m_client; - std::string m_key; - int m_adapterFlags; - State m_state; - Vamp::HostExt::PluginStaticData m_psd; - OutputList m_outputs; - Vamp::HostExt::PluginConfiguration m_defaultConfig; - Vamp::HostExt::PluginConfiguration m_config; -}; - -} - -#endif
--- a/vamp-client/SynchronousTransport.h Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/SynchronousTransport.h Thu Oct 13 12:02:44 2016 +0100 @@ -3,12 +3,26 @@ #define PIPER_SYNCHRONOUS_TRANSPORT_H #include <vector> +#include <cstdlib> namespace piper { +class MessageCompletenessChecker // interface +{ +public: + virtual ~MessageCompletenessChecker() = default; + + virtual bool isComplete(const std::vector<char> &message) const = 0; +}; + class SynchronousTransport // interface { public: + virtual ~SynchronousTransport() = default; + + //!!! I do not take ownership + virtual void setCompletenessChecker(MessageCompletenessChecker *) = 0; + //!!! how to handle errors -- exception or return value? often an //!!! error (e.g. server has exited) may mean the transport can no //!!! longer be used at all @@ -17,12 +31,6 @@ virtual bool isOK() const = 0; }; -class MessageCompletenessChecker // interface -{ -public: - virtual bool isComplete(const std::vector<char> &message) const = 0; -}; - } #endif
--- a/vamp-client/client.cpp Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/client.cpp Thu Oct 13 12:02:44 2016 +0100 @@ -1,6 +1,4 @@ -#include "PiperStubPlugin.h" -#include "CapnpMessageCompletenessChecker.h" #include "PipedQProcessTransport.h" #include "PiperCapnpClient.h" @@ -11,8 +9,7 @@ int main(int, char **) { - piper::CapnpMessageCompletenessChecker checker; - piper::PipedQProcessTransport transport("../bin/piper-vamp-server", &checker); + piper::PipedQProcessTransport transport("../bin/piper-vamp-server"); piper::PiperCapnpClient client(&transport); Vamp::Plugin *plugin = client.load("vamp-example-plugins:zerocrossing", 16, 0);
--- a/vamp-client/client.pro Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-client/client.pro Thu Oct 13 12:02:44 2016 +0100 @@ -29,11 +29,10 @@ ../vamp-capnp/piper.capnp.c++ HEADERS += \ - CapnpMessageCompletenessChecker.h \ PipedQProcessTransport.h \ PiperCapnpClient.h \ PiperClient.h \ - PiperStubPlugin.h \ + PiperPluginStub.h \ SynchronousTransport.h
--- a/vamp-server/server.cpp Thu Oct 13 11:33:19 2016 +0100 +++ b/vamp-server/server.cpp Thu Oct 13 12:02:44 2016 +0100 @@ -295,6 +295,7 @@ if (request.type == RRType::Finish) { auto h = mapper.pluginToHandle(request.finishRequest.plugin); + cerr << "deleting the plugin with handle " << h << endl; mapper.removePlugin(h); delete request.finishRequest.plugin; }