cannam@150: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@150: /* cannam@150: Piper C++ cannam@150: cannam@150: An API for audio analysis and feature extraction plugins. cannam@150: cannam@150: Centre for Digital Music, Queen Mary, University of London. cannam@150: Copyright 2006-2016 Chris Cannam and QMUL. cannam@150: cannam@150: Permission is hereby granted, free of charge, to any person cannam@150: obtaining a copy of this software and associated documentation cannam@150: files (the "Software"), to deal in the Software without cannam@150: restriction, including without limitation the rights to use, copy, cannam@150: modify, merge, publish, distribute, sublicense, and/or sell copies cannam@150: of the Software, and to permit persons to whom the Software is cannam@150: furnished to do so, subject to the following conditions: cannam@150: cannam@150: The above copyright notice and this permission notice shall be cannam@150: included in all copies or substantial portions of the Software. cannam@150: cannam@150: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@150: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@150: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND cannam@150: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR cannam@150: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@150: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@150: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@150: cannam@150: Except as contained in this notice, the names of the Centre for cannam@150: Digital Music; Queen Mary, University of London; and Chris Cannam cannam@150: shall not be used in advertising or otherwise to promote the sale, cannam@150: use or other dealings in this Software without prior written cannam@150: authorization. cannam@150: */ cannam@150: cannam@150: #ifndef PIPER_AUTO_PLUGIN_H cannam@150: #define PIPER_AUTO_PLUGIN_H cannam@150: cannam@150: #include "ProcessQtTransport.h" cannam@152: #include "../CapnpRRClient.h" cannam@170: #include "../Exceptions.h" cannam@150: cannam@150: #include cannam@150: cannam@150: namespace piper_vamp { cannam@150: namespace client { cannam@150: cannam@170: /** cannam@187: * AutoPlugin presents a Piper feature extractor in the form of a Vamp cannam@187: * plugin, managing its own single-use server instance. That is, the cannam@187: * distinguishing quality of AutoPlugin (in comparison with cannam@187: * PluginStub) is that it runs and terminates its own Piper server, cannam@187: * whose lifetime matches that of the plugin. cannam@187: * cannam@187: * Example usage: cannam@187: * cannam@187: * Vamp::Plugin *plugin = cannam@187: * new AutoPlugin("piper-server-name.exe", cannam@187: * "vamp-example-plugins:zerocrossing", cannam@187: * 44100.0f, cannam@187: * Vamp::HostExt::PluginLoader::ADAPT_ALL_SAFE, cannam@187: * nullptr); cannam@187: * plugin->initialise(...); cannam@187: * plugin->process(...); <-- in the normal way for a Vamp plugin cannam@187: * delete plugin; <-- causes the server to exit cannam@187: * cannam@187: * AutoPlugin makes use of the Loader and PluginClient interfaces, cannam@187: * providing them its own transport layer object for its single server. cannam@170: * cannam@170: * Note that any method may throw ServerCrashed, RequestTimedOut or cannam@170: * ProtocolError exceptions. cannam@170: */ cannam@150: class AutoPlugin : public Vamp::Plugin cannam@150: { cannam@150: public: cannam@187: /** cannam@187: * Construct an AutoPlugin that runs an instance of the Piper cannam@187: * server with the given server name (executable path), requesting cannam@187: * the given plugin key from the server. cannam@187: * cannam@187: * \param adapterFlags a bitwise OR of the values in the cannam@187: * Vamp::HostExt::PluginLoader::AdapterFlags enumeration cannam@187: * cannam@187: * \param logger an optional callback for log messages. Pass a cannam@187: * null pointer to use cerr instead. cannam@187: */ cannam@150: AutoPlugin(std::string serverName, cannam@150: std::string pluginKey, cannam@150: float inputSampleRate, cannam@150: int adapterFlags, cannam@187: LogCallback *logger) : cannam@150: Vamp::Plugin(inputSampleRate), cannam@150: m_logger(logger), cannam@150: m_transport(serverName, "capnp", logger), cannam@150: m_client(&m_transport, logger) cannam@150: { cannam@150: LoadRequest req; cannam@150: req.pluginKey = pluginKey; cannam@150: req.inputSampleRate = inputSampleRate; cannam@150: req.adapterFlags = adapterFlags; cannam@150: try { cannam@150: LoadResponse resp = m_client.loadPlugin(req); cannam@150: m_plugin = resp.plugin; cannam@150: } catch (ServerCrashed c) { cannam@150: log(std::string("AutoPlugin: Server crashed: ") + c.what()); cannam@150: m_plugin = 0; cannam@150: } cannam@150: } cannam@150: cannam@150: virtual ~AutoPlugin() { cannam@150: delete m_plugin; cannam@187: // The transport is a plain data member and will be deleted cannam@187: // here, which will have the effect of terminating the server cannam@150: } cannam@150: cannam@150: bool isOK() const { cannam@150: return (m_plugin != nullptr); cannam@150: } cannam@150: cannam@150: virtual std::string getIdentifier() const { cannam@150: return getPlugin()->getIdentifier(); cannam@150: } cannam@150: cannam@150: virtual std::string getName() const { cannam@150: return getPlugin()->getName(); cannam@150: } cannam@150: cannam@150: virtual std::string getDescription() const { cannam@150: return getPlugin()->getDescription(); cannam@150: } cannam@150: cannam@150: virtual std::string getMaker() const { cannam@150: return getPlugin()->getMaker(); cannam@150: } cannam@150: cannam@150: virtual std::string getCopyright() const { cannam@150: return getPlugin()->getCopyright(); cannam@150: } cannam@150: cannam@150: virtual int getPluginVersion() const { cannam@150: return getPlugin()->getPluginVersion(); cannam@150: } cannam@150: cannam@150: virtual ParameterList getParameterDescriptors() const { cannam@150: return getPlugin()->getParameterDescriptors(); cannam@150: } cannam@150: cannam@150: virtual float getParameter(std::string name) const { cannam@150: return getPlugin()->getParameter(name); cannam@150: } cannam@150: cannam@150: virtual void setParameter(std::string name, float value) { cannam@150: getPlugin()->setParameter(name, value); cannam@150: } cannam@150: cannam@150: virtual ProgramList getPrograms() const { cannam@150: return getPlugin()->getPrograms(); cannam@150: } cannam@150: cannam@150: virtual std::string getCurrentProgram() const { cannam@150: return getPlugin()->getCurrentProgram(); cannam@150: } cannam@150: cannam@150: virtual void selectProgram(std::string program) { cannam@150: getPlugin()->selectProgram(program); cannam@150: } cannam@150: cannam@150: virtual bool initialise(size_t inputChannels, cannam@150: size_t stepSize, cannam@150: size_t blockSize) { cannam@186: return getPlugin()->initialise(inputChannels, stepSize, blockSize); cannam@150: } cannam@150: cannam@150: virtual void reset() { cannam@150: getPlugin()->reset(); cannam@150: } cannam@150: cannam@150: virtual InputDomain getInputDomain() const { cannam@150: return getPlugin()->getInputDomain(); cannam@150: } cannam@150: cannam@150: virtual size_t getPreferredBlockSize() const { cannam@150: return getPlugin()->getPreferredBlockSize(); cannam@150: } cannam@150: cannam@150: virtual size_t getPreferredStepSize() const { cannam@150: return getPlugin()->getPreferredStepSize(); cannam@150: } cannam@150: cannam@150: virtual size_t getMinChannelCount() const { cannam@150: return getPlugin()->getMinChannelCount(); cannam@150: } cannam@150: cannam@150: virtual size_t getMaxChannelCount() const { cannam@150: return getPlugin()->getMaxChannelCount(); cannam@150: } cannam@150: cannam@150: virtual OutputList getOutputDescriptors() const { cannam@150: return getPlugin()->getOutputDescriptors(); cannam@150: } cannam@150: cannam@150: virtual FeatureSet process(const float *const *inputBuffers, cannam@150: Vamp::RealTime timestamp) { cannam@150: return getPlugin()->process(inputBuffers, timestamp); cannam@150: } cannam@150: cannam@150: virtual FeatureSet getRemainingFeatures() { cannam@150: return getPlugin()->getRemainingFeatures(); cannam@150: } cannam@150: cannam@150: private: cannam@150: LogCallback *m_logger; cannam@150: ProcessQtTransport m_transport; cannam@150: CapnpRRClient m_client; cannam@150: Vamp::Plugin *m_plugin; cannam@150: Vamp::Plugin *getPlugin() const { cannam@150: if (!m_plugin) { cannam@150: log("AutoPlugin: getPlugin() failed (caller should have called AutoPlugin::isOK)"); cannam@150: throw std::logic_error("Plugin load failed"); cannam@150: } cannam@150: return m_plugin; cannam@150: } cannam@150: cannam@150: void log(std::string message) const { cannam@150: if (m_logger) m_logger->log(message); cannam@150: else std::cerr << message << std::endl; cannam@150: } cannam@150: }; cannam@150: cannam@150: } cannam@150: } cannam@150: cannam@150: #endif cannam@150: cannam@150: