Mercurial > hg > piper-cpp
changeset 90:6429a99abcad
Split out classes
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 13 Oct 2016 10:17:59 +0100 |
parents | 03ed2e0a6c8f |
children | c897c9a8daf1 |
files | vamp-capnp/VampnProto.h vamp-client/CapnpMessageCompletenessChecker.h vamp-client/Makefile vamp-client/PipedQProcessTransport.h vamp-client/PiperCapnpClient.h vamp-client/PiperClient.h vamp-client/PiperStubPlugin.h vamp-client/SynchronousTransport.h vamp-client/client.cpp vamp-client/client.pro vamp-client/stub.h |
diffstat | 11 files changed, 706 insertions(+), 588 deletions(-) [+] |
line wrap: on
line diff
--- a/vamp-capnp/VampnProto.h Wed Oct 12 21:34:21 2016 +0100 +++ b/vamp-capnp/VampnProto.h Thu Oct 13 10:17:59 2016 +0100 @@ -35,7 +35,7 @@ #include "piper.capnp.h" #include <capnp/message.h> -#include <capnp/serialize-packed.h> +//#include <capnp/serialize-packed.h> #include <vamp-hostsdk/Plugin.h> #include <vamp-hostsdk/PluginLoader.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/CapnpMessageCompletenessChecker.h Thu Oct 13 10:17:59 2016 +0100 @@ -0,0 +1,38 @@ + +#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 Wed Oct 12 21:34:21 2016 +0100 +++ b/vamp-client/Makefile Thu Oct 13 10:17:59 2016 +0100 @@ -3,7 +3,7 @@ # Generated by qmake (3.0) (Qt 5.7.0) # Project: client.pro # Template: app -# Command: /usr/lib/qt/bin/qmake -o Makefile client.pro +# Command: /usr/bin/qmake -o Makefile client.pro ############################################################################# MAKEFILE = Makefile @@ -16,7 +16,7 @@ CFLAGS = -pipe -O2 -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -Wall -W -D_REENTRANT -fPIC $(DEFINES) CXXFLAGS = -I../../vamp-plugin-sdk -I.. -O2 -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -std=gnu++11 -Wall -W -D_REENTRANT -fPIC $(DEFINES) INCPATH = -I. -isystem /usr/include/qt -isystem /usr/include/qt/QtCore -I../o -I/usr/lib/qt/mkspecs/linux-g++ -QMAKE = /usr/lib/qt/bin/qmake +QMAKE = /usr/bin/qmake DEL_FILE = rm -f CHK_DIR_EXISTS= test -d MKDIR = mkdir -p @@ -76,9 +76,6 @@ /usr/lib/qt/mkspecs/modules/qt_KCrash.pri \ /usr/lib/qt/mkspecs/modules/qt_KDBusAddons.pri \ /usr/lib/qt/mkspecs/modules/qt_KDeclarative.pri \ - /usr/lib/qt/mkspecs/modules/qt_KDEWebKit.pri \ - /usr/lib/qt/mkspecs/modules/qt_KDNSSD.pri \ - /usr/lib/qt/mkspecs/modules/qt_KEmoticons.pri \ /usr/lib/qt/mkspecs/modules/qt_KGlobalAccel.pri \ /usr/lib/qt/mkspecs/modules/qt_KGuiAddons.pri \ /usr/lib/qt/mkspecs/modules/qt_KI18n.pri \ @@ -87,22 +84,18 @@ /usr/lib/qt/mkspecs/modules/qt_KIOFileWidgets.pri \ /usr/lib/qt/mkspecs/modules/qt_KIOGui.pri \ /usr/lib/qt/mkspecs/modules/qt_KIOWidgets.pri \ - /usr/lib/qt/mkspecs/modules/qt_KItemModels.pri \ /usr/lib/qt/mkspecs/modules/qt_KItemViews.pri \ /usr/lib/qt/mkspecs/modules/qt_KJobWidgets.pri \ - /usr/lib/qt/mkspecs/modules/qt_KNewStuff.pri \ /usr/lib/qt/mkspecs/modules/qt_KNotifications.pri \ - /usr/lib/qt/mkspecs/modules/qt_KNotifyConfig.pri \ /usr/lib/qt/mkspecs/modules/qt_KNTLM.pri \ - /usr/lib/qt/mkspecs/modules/qt_KParts.pri \ - /usr/lib/qt/mkspecs/modules/qt_KPlotting.pri \ /usr/lib/qt/mkspecs/modules/qt_KService.pri \ /usr/lib/qt/mkspecs/modules/qt_KTextWidgets.pri \ - /usr/lib/qt/mkspecs/modules/qt_KUnitConversion.pri \ /usr/lib/qt/mkspecs/modules/qt_KWallet.pri \ /usr/lib/qt/mkspecs/modules/qt_KWidgetsAddons.pri \ /usr/lib/qt/mkspecs/modules/qt_KWindowSystem.pri \ /usr/lib/qt/mkspecs/modules/qt_KXmlGui.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_bluetooth.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_bluetooth_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_bootstrap_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_clucene_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_concurrent.pri \ @@ -130,6 +123,8 @@ /usr/lib/qt/mkspecs/modules/qt_lib_multimediawidgets_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_network.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_network_private.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_nfc.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_nfc_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_opengl.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_opengl_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_openglextensions.pri \ @@ -149,10 +144,7 @@ /usr/lib/qt/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quick.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quick_private.pri \ - /usr/lib/qt/mkspecs/modules/qt_lib_quickcontrols2.pri \ - /usr/lib/qt/mkspecs/modules/qt_lib_quickcontrols2_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quickparticles_private.pri \ - /usr/lib/qt/mkspecs/modules/qt_lib_quicktemplates2_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quickwidgets.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quickwidgets_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_script.pri \ @@ -161,6 +153,8 @@ /usr/lib/qt/mkspecs/modules/qt_lib_scripttools_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sensors.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sensors_private.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_serialport.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_serialport_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sql.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sql_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_svg.pri \ @@ -196,6 +190,7 @@ /usr/lib/qt/mkspecs/features/qt_config.prf \ /usr/lib/qt/mkspecs/linux-g++/qmake.conf \ /usr/lib/qt/mkspecs/features/spec_post.prf \ + .qmake.stash \ /usr/lib/qt/mkspecs/features/exclusive_builds.prf \ /usr/lib/qt/mkspecs/features/default_pre.prf \ /usr/lib/qt/mkspecs/features/resolve_config.prf \ @@ -210,7 +205,12 @@ /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 CapnpMessageCompletenessChecker.h \ + PipedQProcessTransport.h \ + PiperCapnpClient.h \ + PiperClient.h \ + PiperStubPlugin.h \ + SynchronousTransport.h client.cpp \ ../vamp-capnp/piper.capnp.c++ QMAKE_TARGET = client DESTDIR = @@ -247,9 +247,6 @@ /usr/lib/qt/mkspecs/modules/qt_KCrash.pri \ /usr/lib/qt/mkspecs/modules/qt_KDBusAddons.pri \ /usr/lib/qt/mkspecs/modules/qt_KDeclarative.pri \ - /usr/lib/qt/mkspecs/modules/qt_KDEWebKit.pri \ - /usr/lib/qt/mkspecs/modules/qt_KDNSSD.pri \ - /usr/lib/qt/mkspecs/modules/qt_KEmoticons.pri \ /usr/lib/qt/mkspecs/modules/qt_KGlobalAccel.pri \ /usr/lib/qt/mkspecs/modules/qt_KGuiAddons.pri \ /usr/lib/qt/mkspecs/modules/qt_KI18n.pri \ @@ -258,22 +255,18 @@ /usr/lib/qt/mkspecs/modules/qt_KIOFileWidgets.pri \ /usr/lib/qt/mkspecs/modules/qt_KIOGui.pri \ /usr/lib/qt/mkspecs/modules/qt_KIOWidgets.pri \ - /usr/lib/qt/mkspecs/modules/qt_KItemModels.pri \ /usr/lib/qt/mkspecs/modules/qt_KItemViews.pri \ /usr/lib/qt/mkspecs/modules/qt_KJobWidgets.pri \ - /usr/lib/qt/mkspecs/modules/qt_KNewStuff.pri \ /usr/lib/qt/mkspecs/modules/qt_KNotifications.pri \ - /usr/lib/qt/mkspecs/modules/qt_KNotifyConfig.pri \ /usr/lib/qt/mkspecs/modules/qt_KNTLM.pri \ - /usr/lib/qt/mkspecs/modules/qt_KParts.pri \ - /usr/lib/qt/mkspecs/modules/qt_KPlotting.pri \ /usr/lib/qt/mkspecs/modules/qt_KService.pri \ /usr/lib/qt/mkspecs/modules/qt_KTextWidgets.pri \ - /usr/lib/qt/mkspecs/modules/qt_KUnitConversion.pri \ /usr/lib/qt/mkspecs/modules/qt_KWallet.pri \ /usr/lib/qt/mkspecs/modules/qt_KWidgetsAddons.pri \ /usr/lib/qt/mkspecs/modules/qt_KWindowSystem.pri \ /usr/lib/qt/mkspecs/modules/qt_KXmlGui.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_bluetooth.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_bluetooth_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_bootstrap_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_clucene_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_concurrent.pri \ @@ -301,6 +294,8 @@ /usr/lib/qt/mkspecs/modules/qt_lib_multimediawidgets_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_network.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_network_private.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_nfc.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_nfc_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_opengl.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_opengl_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_openglextensions.pri \ @@ -320,10 +315,7 @@ /usr/lib/qt/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quick.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quick_private.pri \ - /usr/lib/qt/mkspecs/modules/qt_lib_quickcontrols2.pri \ - /usr/lib/qt/mkspecs/modules/qt_lib_quickcontrols2_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quickparticles_private.pri \ - /usr/lib/qt/mkspecs/modules/qt_lib_quicktemplates2_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quickwidgets.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_quickwidgets_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_script.pri \ @@ -332,6 +324,8 @@ /usr/lib/qt/mkspecs/modules/qt_lib_scripttools_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sensors.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sensors_private.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_serialport.pri \ + /usr/lib/qt/mkspecs/modules/qt_lib_serialport_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sql.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_sql_private.pri \ /usr/lib/qt/mkspecs/modules/qt_lib_svg.pri \ @@ -367,6 +361,7 @@ /usr/lib/qt/mkspecs/features/qt_config.prf \ /usr/lib/qt/mkspecs/linux-g++/qmake.conf \ /usr/lib/qt/mkspecs/features/spec_post.prf \ + .qmake.stash \ /usr/lib/qt/mkspecs/features/exclusive_builds.prf \ /usr/lib/qt/mkspecs/features/default_pre.prf \ /usr/lib/qt/mkspecs/features/resolve_config.prf \ @@ -408,9 +403,6 @@ /usr/lib/qt/mkspecs/modules/qt_KCrash.pri: /usr/lib/qt/mkspecs/modules/qt_KDBusAddons.pri: /usr/lib/qt/mkspecs/modules/qt_KDeclarative.pri: -/usr/lib/qt/mkspecs/modules/qt_KDEWebKit.pri: -/usr/lib/qt/mkspecs/modules/qt_KDNSSD.pri: -/usr/lib/qt/mkspecs/modules/qt_KEmoticons.pri: /usr/lib/qt/mkspecs/modules/qt_KGlobalAccel.pri: /usr/lib/qt/mkspecs/modules/qt_KGuiAddons.pri: /usr/lib/qt/mkspecs/modules/qt_KI18n.pri: @@ -419,22 +411,18 @@ /usr/lib/qt/mkspecs/modules/qt_KIOFileWidgets.pri: /usr/lib/qt/mkspecs/modules/qt_KIOGui.pri: /usr/lib/qt/mkspecs/modules/qt_KIOWidgets.pri: -/usr/lib/qt/mkspecs/modules/qt_KItemModels.pri: /usr/lib/qt/mkspecs/modules/qt_KItemViews.pri: /usr/lib/qt/mkspecs/modules/qt_KJobWidgets.pri: -/usr/lib/qt/mkspecs/modules/qt_KNewStuff.pri: /usr/lib/qt/mkspecs/modules/qt_KNotifications.pri: -/usr/lib/qt/mkspecs/modules/qt_KNotifyConfig.pri: /usr/lib/qt/mkspecs/modules/qt_KNTLM.pri: -/usr/lib/qt/mkspecs/modules/qt_KParts.pri: -/usr/lib/qt/mkspecs/modules/qt_KPlotting.pri: /usr/lib/qt/mkspecs/modules/qt_KService.pri: /usr/lib/qt/mkspecs/modules/qt_KTextWidgets.pri: -/usr/lib/qt/mkspecs/modules/qt_KUnitConversion.pri: /usr/lib/qt/mkspecs/modules/qt_KWallet.pri: /usr/lib/qt/mkspecs/modules/qt_KWidgetsAddons.pri: /usr/lib/qt/mkspecs/modules/qt_KWindowSystem.pri: /usr/lib/qt/mkspecs/modules/qt_KXmlGui.pri: +/usr/lib/qt/mkspecs/modules/qt_lib_bluetooth.pri: +/usr/lib/qt/mkspecs/modules/qt_lib_bluetooth_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_bootstrap_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_clucene_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_concurrent.pri: @@ -462,6 +450,8 @@ /usr/lib/qt/mkspecs/modules/qt_lib_multimediawidgets_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_network.pri: /usr/lib/qt/mkspecs/modules/qt_lib_network_private.pri: +/usr/lib/qt/mkspecs/modules/qt_lib_nfc.pri: +/usr/lib/qt/mkspecs/modules/qt_lib_nfc_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_opengl.pri: /usr/lib/qt/mkspecs/modules/qt_lib_opengl_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_openglextensions.pri: @@ -481,10 +471,7 @@ /usr/lib/qt/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_quick.pri: /usr/lib/qt/mkspecs/modules/qt_lib_quick_private.pri: -/usr/lib/qt/mkspecs/modules/qt_lib_quickcontrols2.pri: -/usr/lib/qt/mkspecs/modules/qt_lib_quickcontrols2_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_quickparticles_private.pri: -/usr/lib/qt/mkspecs/modules/qt_lib_quicktemplates2_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_quickwidgets.pri: /usr/lib/qt/mkspecs/modules/qt_lib_quickwidgets_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_script.pri: @@ -493,6 +480,8 @@ /usr/lib/qt/mkspecs/modules/qt_lib_scripttools_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_sensors.pri: /usr/lib/qt/mkspecs/modules/qt_lib_sensors_private.pri: +/usr/lib/qt/mkspecs/modules/qt_lib_serialport.pri: +/usr/lib/qt/mkspecs/modules/qt_lib_serialport_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_sql.pri: /usr/lib/qt/mkspecs/modules/qt_lib_sql_private.pri: /usr/lib/qt/mkspecs/modules/qt_lib_svg.pri: @@ -528,6 +517,7 @@ /usr/lib/qt/mkspecs/features/qt_config.prf: /usr/lib/qt/mkspecs/linux-g++/qmake.conf: /usr/lib/qt/mkspecs/features/spec_post.prf: +.qmake.stash: /usr/lib/qt/mkspecs/features/exclusive_builds.prf: /usr/lib/qt/mkspecs/features/default_pre.prf: /usr/lib/qt/mkspecs/features/resolve_config.prf: @@ -558,6 +548,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 client.cpp ../vamp-capnp/piper.capnp.c++ $(DISTDIR)/ @@ -598,7 +589,11 @@ ####### Compile -../o/client.o: client.cpp stub.h +../o/client.o: client.cpp PiperClient.h \ + PiperStubPlugin.h \ + CapnpMessageCompletenessChecker.h \ + SynchronousTransport.h \ + PipedQProcessTransport.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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/PipedQProcessTransport.h Thu Oct 13 10:17:59 2016 +0100 @@ -0,0 +1,95 @@ + +#ifndef PIPER_PIPED_QPROCESS_TRANSPORT_H +#define PIPER_PIPED_QPROCESS_TRANSPORT_H + +#include "SynchronousTransport.h" + +#include <QProcess> +#include <QString> + +#include <iostream> + +namespace piper { //!!! change + +class PipedQProcessTransport : public SynchronousTransport +{ +public: + PipedQProcessTransport(QString processName, + MessageCompletenessChecker *checker) : //!!! ownership + m_completenessChecker(checker) { + m_process = new QProcess(); + m_process->setReadChannel(QProcess::StandardOutput); + m_process->setProcessChannelMode(QProcess::ForwardedErrorChannel); + m_process->start(processName); + if (!m_process->waitForStarted()) { + std::cerr << "server failed to start" << std::endl; + delete m_process; + m_process = nullptr; + } + } + + ~PipedQProcessTransport() { + if (m_process) { + if (m_process->state() != QProcess::NotRunning) { + m_process->closeWriteChannel(); + m_process->waitForFinished(200); + m_process->close(); + m_process->waitForFinished(); + std::cerr << "server exited" << std::endl; + } + delete m_process; + } + } + + bool isOK() const override { + return m_process != nullptr; + } + + std::vector<char> + call(const char *ptr, size_t size) override { + + 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 (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; + } + +private: + MessageCompletenessChecker *m_completenessChecker; //!!! I don't own this (currently) + QProcess *m_process; // I own this +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/PiperCapnpClient.h Thu Oct 13 10:17:59 2016 +0100 @@ -0,0 +1,244 @@ + +#ifndef PIPER_CAPNP_CLIENT_H +#define PIPER_CAPNP_CLIENT_H + +#include "PiperClient.h" +#include "SynchronousTransport.h" + +#include "vamp-support/AssignedPluginHandleMapper.h" +#include "vamp-capnp/VampnProto.h" + +namespace piper { //!!! change + +class PiperCapnpClient : public PiperStubPluginClientInterface +{ + // unsigned to avoid undefined behaviour on possible wrap + typedef uint32_t ReqId; + +public: + PiperCapnpClient(SynchronousTransport *transport) : //!!! ownership? shared ptr? + m_transport(transport) { + } + + ~PiperCapnpClient() { + } + + //!!! obviously, factor out all repetitive guff + + //!!! list and load are supposed to be called by application code, + //!!! but the rest are only supposed to be called by the plugin -- + //!!! sort out the api here + + Vamp::Plugin * + load(std::string key, float inputSampleRate, int adapterFlags) { + + if (!m_transport->isOK()) { + throw std::runtime_error("Piper server failed to start"); + } + + Vamp::HostExt::LoadRequest request; + request.pluginKey = key; + request.inputSampleRate = inputSampleRate; + request.adapterFlags = adapterFlags; + + capnp::MallocMessageBuilder message; + RpcRequest::Builder builder = message.initRoot<RpcRequest>(); + + VampnProto::buildRpcRequest_Load(builder, request); + ReqId id = getId(); + builder.getId().setNumber(id); + + auto arr = messageToFlatArray(message); + + auto responseBuffer = m_transport->call(arr.asChars().begin(), + arr.asChars().size()); + + //!!! ... --> will also need some way to kill this process + //!!! (from another thread) + + auto karr = toKJArray(responseBuffer); + capnp::FlatArrayMessageReader responseMessage(karr); + 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; + }; + +protected: + virtual + Vamp::Plugin::OutputList + configure(PiperStubPlugin *plugin, + Vamp::HostExt::PluginConfiguration config) override { + + if (!m_transport->isOK()) { + throw std::runtime_error("Piper server failed to start"); + } + + Vamp::HostExt::ConfigurationRequest request; + request.plugin = plugin; + request.configuration = config; + + 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); + auto responseBuffer = m_transport->call(arr.asChars().begin(), + arr.asChars().size()); + auto karr = toKJArray(responseBuffer); + capnp::FlatArrayMessageReader responseMessage(karr); + RpcResponse::Reader reader = responseMessage.getRoot<RpcResponse>(); + + //!!! 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, + std::vector<std::vector<float> > inputBuffers, + Vamp::RealTime timestamp) override { + + if (!m_transport->isOK()) { + 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); + auto responseBuffer = m_transport->call(arr.asChars().begin(), + arr.asChars().size()); + auto karr = toKJArray(responseBuffer); + capnp::FlatArrayMessageReader responseMessage(karr); + 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) override { + + if (!m_transport->isOK()) { + 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); + auto responseBuffer = m_transport->call(arr.asChars().begin(), + arr.asChars().size()); + auto karr = toKJArray(responseBuffer); + capnp::FlatArrayMessageReader responseMessage(karr); + 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)); + + // Don't delete the plugin. It's the plugin that is supposed + // to be calling us here + + return pr.features; + } + +private: + AssignedPluginHandleMapper m_mapper; + ReqId getId() { + //!!! todo: mutex + static ReqId m_nextId = 0; + return m_nextId++; + } + + kj::Array<capnp::word> + toKJArray(const std::vector<char> &buffer) { + // We could do this whole thing with fewer copies, but let's + // see whether it matters first + size_t wordSize = sizeof(capnp::word); + size_t words = buffer.size() / wordSize; + kj::Array<capnp::word> karr(kj::heapArray<capnp::word>(words)); + memcpy(karr.begin(), buffer.data(), words * wordSize); + return karr; + } + + 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"); + } + } + +private: + SynchronousTransport *m_transport; //!!! I don't own this, but should I? +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/PiperClient.h Thu Oct 13 10:17:59 2016 +0100 @@ -0,0 +1,33 @@ + +#ifndef PIPER_CLIENT_H +#define PIPER_CLIENT_H + +#include <vamp-hostsdk/PluginConfiguration.h> + +namespace piper { //!!! change + +class PiperStubPlugin; + +class PiperStubPluginClientInterface +{ + friend class PiperStubPlugin; + +protected: + virtual + Vamp::Plugin::OutputList + configure(PiperStubPlugin *plugin, + Vamp::HostExt::PluginConfiguration config) = 0; + + virtual + Vamp::Plugin::FeatureSet + process(PiperStubPlugin *plugin, + std::vector<std::vector<float> > inputBuffers, + Vamp::RealTime timestamp) = 0; + + virtual Vamp::Plugin::FeatureSet + finish(PiperStubPlugin *plugin) = 0; +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/PiperStubPlugin.h Thu Oct 13 10:17:59 2016 +0100 @@ -0,0 +1,213 @@ + +#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, + float inputSampleRate, + Vamp::HostExt::PluginStaticData psd, + Vamp::HostExt::PluginConfiguration defaultConfig) : + Plugin(inputSampleRate), + m_client(client), + 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() { + //!!! hm, how to deal with this? there is no reset() in Piper! + throw "Please do not call this function again."; + } + + 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); + } + +private: + PiperStubPluginClientInterface *m_client; + State m_state; + Vamp::HostExt::PluginStaticData m_psd; + OutputList m_outputs; + Vamp::HostExt::PluginConfiguration m_defaultConfig; + Vamp::HostExt::PluginConfiguration m_config; +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-client/SynchronousTransport.h Thu Oct 13 10:17:59 2016 +0100 @@ -0,0 +1,28 @@ + +#ifndef PIPER_SYNCHRONOUS_TRANSPORT_H +#define PIPER_SYNCHRONOUS_TRANSPORT_H + +#include <vector> + +namespace piper { + +class SynchronousTransport // interface +{ +public: + //!!! 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 + virtual std::vector<char> call(const char *data, size_t bytes) = 0; + + 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 Wed Oct 12 21:34:21 2016 +0100 +++ b/vamp-client/client.cpp Thu Oct 13 10:17:59 2016 +0100 @@ -1,330 +1,20 @@ -#include "stub.h" - -#include "vamp-capnp/VampnProto.h" - -#include "vamp-support/AssignedPluginHandleMapper.h" - -#include <QProcess> +#include "PiperStubPlugin.h" +#include "CapnpMessageCompletenessChecker.h" +#include "PipedQProcessTransport.h" +#include "PiperCapnpClient.h" #include <stdexcept> using std::cerr; using std::endl; -// First cut plan: this is to be client-qt.cpp, using a QProcess, so -// we're using pipes and the server is completely synchronous, -// handling only one call at once. Our PiperClient will fire off a -// QProcess and refer to its io device. Each request message is -// serialised into memory using capnp::MallocMessageBuilder and -// shunted into the process pipe; we then wait for some bytes to come -// back and use capnp::expectedSizeInWordsFromPrefix to work out when -// a whole message is available, reading only that amount from the -// device and using FlatArrayMessageReader to convert to a response -// message. If the response message's id does not match the request -// message's, then the server has gone wrong (it should never be -// servicing more than one request at a time). - -// Next level: Capnp RPC, but I want to get the first level to work -// first, not least because the server already exists. - -namespace piper { //!!! probably something different - -class PiperClient : public PiperClientStubRequirements -{ - // unsigned to avoid undefined behaviour on possible wrap - typedef uint32_t ReqId; - -public: - PiperClient() { - m_process = new QProcess(); - m_process->setReadChannel(QProcess::StandardOutput); - m_process->setProcessChannelMode(QProcess::ForwardedErrorChannel); - m_process->start("../bin/piper-vamp-server"); //!!! - if (!m_process->waitForStarted()) { - cerr << "server failed to start" << endl; - delete m_process; - m_process = 0; - } - } - - ~PiperClient() { - if (m_process) { - if (m_process->state() != QProcess::NotRunning) { - m_process->closeWriteChannel(); - m_process->waitForFinished(200); - m_process->close(); - m_process->waitForFinished(); - cerr << "server exited" << endl; - } - delete m_process; - } - } - - //!!! obviously, factor out all repetitive guff - - //!!! list and load are supposed to be called by application code, - //!!! but the rest are only supposed to be called by the plugin -- - //!!! sort out the api here - - Vamp::Plugin * - load(std::string key, float inputSampleRate, int adapterFlags) { - - if (!m_process) { - throw std::runtime_error("Piper server failed to start"); - } - - Vamp::HostExt::LoadRequest request; - request.pluginKey = key; - request.inputSampleRate = inputSampleRate; - request.adapterFlags = adapterFlags; - - capnp::MallocMessageBuilder message; - RpcRequest::Builder builder = message.initRoot<RpcRequest>(); - - VampnProto::buildRpcRequest_Load(builder, request); - ReqId id = getId(); - builder.getId().setNumber(id); - - auto arr = messageToFlatArray(message); - m_process->write(arr.asChars().begin(), arr.asChars().size()); - - //!!! ... --> will also need some way to kill this process - //!!! (from another thread) - - QByteArray buffer = readResponseBuffer(); - auto karr = toKJArray(buffer); - capnp::FlatArrayMessageReader responseMessage(karr); - 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 - Vamp::Plugin::OutputList - configure(PiperStubPlugin *plugin, - Vamp::HostExt::PluginConfiguration config) { - - if (!m_process) { - throw std::runtime_error("Piper server failed to start"); - } - - Vamp::HostExt::ConfigurationRequest request; - request.plugin = plugin; - request.configuration = config; - - 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(); - auto karr = toKJArray(buffer); - capnp::FlatArrayMessageReader responseMessage(karr); - RpcResponse::Reader reader = responseMessage.getRoot<RpcResponse>(); - - //!!! 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, - 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(); - auto karr = toKJArray(buffer); - capnp::FlatArrayMessageReader responseMessage(karr); - 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) { - - 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(); - auto karr = toKJArray(buffer); - capnp::FlatArrayMessageReader responseMessage(karr); - 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)); - - // Don't delete the plugin. It's the plugin that is supposed - // to be calling us here - - return pr.features; - } - -private: - QProcess *m_process; - AssignedPluginHandleMapper m_mapper; - ReqId getId() { - //!!! todo: mutex - static ReqId m_nextId = 0; - return m_nextId++; - } - - kj::Array<capnp::word> - toKJArray(QByteArray qarr) { - // We could do this whole thing with fewer copies, but let's - // see whether it matters first - size_t wordSize = sizeof(capnp::word); - size_t words = qarr.size() / wordSize; - kj::Array<capnp::word> karr(kj::heapArray<capnp::word>(words)); - memcpy(karr.begin(), qarr.data(), words * wordSize); - return karr; - } - - 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(toKJArray(buffer)); - if (haveWords >= expectedWords) { - if (haveWords > expectedWords) { - cerr << "WARNING: obtained more data than expected (" - << haveWords << " words, expected " << expectedWords - << ")" << endl; - } - complete = true; - } - } - } -/* - cerr << "buffer = "; - for (int i = 0; i < buffer.size(); ++i) { - if (i % 16 == 0) cerr << "\n"; - cerr << int(buffer[i]) << " "; - } - cerr << "\n"; -*/ - 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; + piper::CapnpMessageCompletenessChecker checker; + piper::PipedQProcessTransport transport("../bin/piper-vamp-server", &checker); + piper::PiperCapnpClient client(&transport); + Vamp::Plugin *plugin = client.load("vamp-example-plugins:zerocrossing", 16, 0); if (!plugin->initialise(1, 4, 4)) { cerr << "initialisation failed" << endl;
--- a/vamp-client/client.pro Wed Oct 12 21:34:21 2016 +0100 +++ b/vamp-client/client.pro Thu Oct 13 10:17:59 2016 +0100 @@ -25,5 +25,15 @@ TARGET = client SOURCES += \ - client.cpp ../vamp-capnp/piper.capnp.c++ + client.cpp \ + ../vamp-capnp/piper.capnp.c++ + +HEADERS += \ + CapnpMessageCompletenessChecker.h \ + PipedQProcessTransport.h \ + PiperCapnpClient.h \ + PiperClient.h \ + PiperStubPlugin.h \ + SynchronousTransport.h +
--- a/vamp-client/stub.h Wed Oct 12 21:34:21 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ - -#include <vamp-hostsdk/Plugin.h> -#include <vamp-hostsdk/PluginLoader.h> -#include <vamp-hostsdk/PluginStaticData.h> -#include <vamp-hostsdk/PluginConfiguration.h> - -#include <cstdint> - -namespace piper { //!!! should be something else - -class PiperStubPlugin; - -class PiperClientStubRequirements -{ -public: - virtual - Vamp::Plugin::OutputList - configure(PiperStubPlugin *plugin, - Vamp::HostExt::PluginConfiguration config) = 0; - - virtual - Vamp::Plugin::FeatureSet - process(PiperStubPlugin *plugin, - std::vector<std::vector<float> > inputBuffers, - Vamp::RealTime timestamp) = 0; - - virtual Vamp::Plugin::FeatureSet - finish(PiperStubPlugin *plugin) = 0; -}; - -class PiperStubPlugin : public Vamp::Plugin -{ - enum State { - Loaded, Configured, Finished - }; - -public: - PiperStubPlugin(PiperClientStubRequirements *client, - float inputSampleRate, - Vamp::HostExt::PluginStaticData psd, - Vamp::HostExt::PluginConfiguration defaultConfig) : - Plugin(inputSampleRate), - m_client(client), - 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() { - //!!! hm, how to deal with this? there is no reset() in Piper! - throw "Please do not call this function again."; - } - - 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); - } - -private: - PiperClientStubRequirements *m_client; - State m_state; - Vamp::HostExt::PluginStaticData m_psd; - OutputList m_outputs; - Vamp::HostExt::PluginConfiguration m_defaultConfig; - Vamp::HostExt::PluginConfiguration m_config; -}; - - -} -