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@170: * This "plugin" make the Piper client abstraction behave like a local cannam@170: * Vamp plugin, with its own server that lasts only for the lifetime cannam@170: * of this plugin and serves only it. 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@150: AutoPlugin(std::string serverName, cannam@150: std::string pluginKey, cannam@150: float inputSampleRate, cannam@150: int adapterFlags, cannam@150: LogCallback *logger) : // logger may be nullptr for cerr 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@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@170: try { cannam@170: return getPlugin()->initialise(inputChannels, stepSize, blockSize); cannam@170: } catch (const ServiceError &e) { cannam@170: // Sadly, the Vamp API has taught hosts to try to divine cannam@170: // initialisation problems from a bool return value alone cannam@170: log(std::string("AutoPlugin: initialise failed: ") + e.what()); cannam@170: return false; cannam@170: } 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: