cannam@208
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
cannam@208
|
2 /*
|
cannam@208
|
3 Piper C++
|
cannam@208
|
4
|
cannam@208
|
5 An API for audio analysis and feature extraction plugins.
|
cannam@208
|
6
|
cannam@208
|
7 Centre for Digital Music, Queen Mary, University of London.
|
cannam@208
|
8 Copyright 2006-2017 Chris Cannam and QMUL.
|
cannam@208
|
9
|
cannam@208
|
10 Permission is hereby granted, free of charge, to any person
|
cannam@208
|
11 obtaining a copy of this software and associated documentation
|
cannam@208
|
12 files (the "Software"), to deal in the Software without
|
cannam@208
|
13 restriction, including without limitation the rights to use, copy,
|
cannam@208
|
14 modify, merge, publish, distribute, sublicense, and/or sell copies
|
cannam@208
|
15 of the Software, and to permit persons to whom the Software is
|
cannam@208
|
16 furnished to do so, subject to the following conditions:
|
cannam@208
|
17
|
cannam@208
|
18 The above copyright notice and this permission notice shall be
|
cannam@208
|
19 included in all copies or substantial portions of the Software.
|
cannam@208
|
20
|
cannam@208
|
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
cannam@208
|
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
cannam@208
|
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
cannam@208
|
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
cannam@208
|
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
cannam@208
|
26 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
cannam@208
|
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
cannam@208
|
28
|
cannam@208
|
29 Except as contained in this notice, the names of the Centre for
|
cannam@208
|
30 Digital Music; Queen Mary, University of London; and Chris Cannam
|
cannam@208
|
31 shall not be used in advertising or otherwise to promote the sale,
|
cannam@208
|
32 use or other dealings in this Software without prior written
|
cannam@208
|
33 authorization.
|
cannam@208
|
34 */
|
cannam@208
|
35
|
cannam@208
|
36 #ifndef PIPER_AUTO_PLUGIN_H
|
cannam@208
|
37 #define PIPER_AUTO_PLUGIN_H
|
cannam@208
|
38
|
cannam@208
|
39 #include "ProcessQtTransport.h"
|
cannam@208
|
40 #include "../CapnpRRClient.h"
|
cannam@208
|
41 #include "../Exceptions.h"
|
cannam@208
|
42
|
cannam@208
|
43 #include <cstdint>
|
cannam@208
|
44
|
cannam@208
|
45 namespace piper_vamp {
|
cannam@208
|
46 namespace client {
|
cannam@208
|
47
|
cannam@208
|
48 /**
|
cannam@210
|
49 * AutoPlugin presents a Piper feature extractor in the form of a Vamp
|
cannam@210
|
50 * plugin, managing its own single-use server instance. That is, the
|
cannam@210
|
51 * distinguishing quality of AutoPlugin (in comparison with
|
cannam@210
|
52 * PluginStub) is that it runs and terminates its own Piper server,
|
cannam@210
|
53 * whose lifetime matches that of the plugin.
|
cannam@210
|
54 *
|
cannam@210
|
55 * Example usage:
|
cannam@210
|
56 *
|
cannam@210
|
57 * Vamp::Plugin *plugin =
|
cannam@210
|
58 * new AutoPlugin("piper-server-name.exe",
|
cannam@210
|
59 * "vamp-example-plugins:zerocrossing",
|
cannam@210
|
60 * 44100.0f,
|
cannam@210
|
61 * Vamp::HostExt::PluginLoader::ADAPT_ALL_SAFE,
|
cannam@210
|
62 * nullptr);
|
cannam@210
|
63 * plugin->initialise(...);
|
cannam@210
|
64 * plugin->process(...); <-- in the normal way for a Vamp plugin
|
cannam@210
|
65 * delete plugin; <-- causes the server to exit
|
cannam@210
|
66 *
|
cannam@210
|
67 * AutoPlugin makes use of the Loader and PluginClient interfaces,
|
cannam@210
|
68 * providing them its own transport layer object for its single server.
|
cannam@208
|
69 *
|
cannam@208
|
70 * Note that any method may throw ServerCrashed, RequestTimedOut or
|
cannam@208
|
71 * ProtocolError exceptions.
|
cannam@208
|
72 */
|
cannam@208
|
73 class PiperAutoPlugin : public Vamp::Plugin
|
cannam@208
|
74 {
|
cannam@208
|
75 public:
|
cannam@210
|
76 /**
|
cannam@210
|
77 * Construct a PiperAutoPlugin that runs an instance of the Piper
|
cannam@210
|
78 * server with the given server name (executable path), requesting
|
cannam@210
|
79 * the given plugin key from the server.
|
cannam@210
|
80 *
|
cannam@210
|
81 * \param adapterFlags a bitwise OR of the values in the
|
cannam@210
|
82 * Vamp::HostExt::PluginLoader::AdapterFlags enumeration
|
cannam@210
|
83 *
|
cannam@210
|
84 * \param logger an optional callback for log messages. Pass a
|
cannam@210
|
85 * null pointer to use cerr instead.
|
cannam@210
|
86 */
|
cannam@208
|
87 PiperAutoPlugin(std::string serverName,
|
cannam@208
|
88 std::string pluginKey,
|
cannam@208
|
89 float inputSampleRate,
|
cannam@208
|
90 int adapterFlags,
|
cannam@208
|
91 LogCallback *logger) : // logger may be nullptr for cerr
|
cannam@208
|
92 Vamp::Plugin(inputSampleRate),
|
cannam@208
|
93 m_logger(logger),
|
cannam@208
|
94 m_transport(serverName, "capnp", logger),
|
cannam@208
|
95 m_client(&m_transport, logger)
|
cannam@208
|
96 {
|
cannam@208
|
97 LoadRequest req;
|
cannam@208
|
98 req.pluginKey = pluginKey;
|
cannam@208
|
99 req.inputSampleRate = inputSampleRate;
|
cannam@208
|
100 req.adapterFlags = adapterFlags;
|
cannam@208
|
101 try {
|
cannam@208
|
102 LoadResponse resp = m_client.load(req);
|
cannam@208
|
103 m_plugin = resp.plugin;
|
cannam@260
|
104 } catch (const ServerCrashed &c) {
|
cannam@208
|
105 log(std::string("PiperAutoPlugin: Server crashed: ") + c.what());
|
cannam@208
|
106 m_plugin = 0;
|
cannam@208
|
107 }
|
cannam@208
|
108 }
|
cannam@208
|
109
|
cannam@208
|
110 virtual ~PiperAutoPlugin() {
|
cannam@208
|
111 delete m_plugin;
|
cannam@210
|
112 // The transport is a plain data member and will be deleted
|
cannam@210
|
113 // here, which will have the effect of terminating the server
|
cannam@208
|
114 }
|
cannam@208
|
115
|
cannam@208
|
116 bool isOK() const {
|
cannam@208
|
117 return (m_plugin != nullptr);
|
cannam@208
|
118 }
|
cannam@208
|
119
|
cannam@208
|
120 virtual std::string getIdentifier() const {
|
cannam@208
|
121 return getPlugin()->getIdentifier();
|
cannam@208
|
122 }
|
cannam@208
|
123
|
cannam@208
|
124 virtual std::string getName() const {
|
cannam@208
|
125 return getPlugin()->getName();
|
cannam@208
|
126 }
|
cannam@208
|
127
|
cannam@208
|
128 virtual std::string getDescription() const {
|
cannam@208
|
129 return getPlugin()->getDescription();
|
cannam@208
|
130 }
|
cannam@208
|
131
|
cannam@208
|
132 virtual std::string getMaker() const {
|
cannam@208
|
133 return getPlugin()->getMaker();
|
cannam@208
|
134 }
|
cannam@208
|
135
|
cannam@208
|
136 virtual std::string getCopyright() const {
|
cannam@208
|
137 return getPlugin()->getCopyright();
|
cannam@208
|
138 }
|
cannam@208
|
139
|
cannam@208
|
140 virtual int getPluginVersion() const {
|
cannam@208
|
141 return getPlugin()->getPluginVersion();
|
cannam@208
|
142 }
|
cannam@208
|
143
|
cannam@208
|
144 virtual ParameterList getParameterDescriptors() const {
|
cannam@208
|
145 return getPlugin()->getParameterDescriptors();
|
cannam@208
|
146 }
|
cannam@208
|
147
|
cannam@208
|
148 virtual float getParameter(std::string name) const {
|
cannam@208
|
149 return getPlugin()->getParameter(name);
|
cannam@208
|
150 }
|
cannam@208
|
151
|
cannam@208
|
152 virtual void setParameter(std::string name, float value) {
|
cannam@208
|
153 getPlugin()->setParameter(name, value);
|
cannam@208
|
154 }
|
cannam@208
|
155
|
cannam@208
|
156 virtual ProgramList getPrograms() const {
|
cannam@208
|
157 return getPlugin()->getPrograms();
|
cannam@208
|
158 }
|
cannam@208
|
159
|
cannam@208
|
160 virtual std::string getCurrentProgram() const {
|
cannam@208
|
161 return getPlugin()->getCurrentProgram();
|
cannam@208
|
162 }
|
cannam@208
|
163
|
cannam@208
|
164 virtual void selectProgram(std::string program) {
|
cannam@208
|
165 getPlugin()->selectProgram(program);
|
cannam@208
|
166 }
|
cannam@208
|
167
|
cannam@208
|
168 virtual bool initialise(size_t inputChannels,
|
cannam@208
|
169 size_t stepSize,
|
cannam@208
|
170 size_t blockSize) {
|
cannam@208
|
171 return getPlugin()->initialise(inputChannels, stepSize, blockSize);
|
cannam@208
|
172 }
|
cannam@208
|
173
|
cannam@208
|
174 virtual void reset() {
|
cannam@208
|
175 getPlugin()->reset();
|
cannam@208
|
176 }
|
cannam@208
|
177
|
cannam@208
|
178 virtual InputDomain getInputDomain() const {
|
cannam@208
|
179 return getPlugin()->getInputDomain();
|
cannam@208
|
180 }
|
cannam@208
|
181
|
cannam@208
|
182 virtual size_t getPreferredBlockSize() const {
|
cannam@208
|
183 return getPlugin()->getPreferredBlockSize();
|
cannam@208
|
184 }
|
cannam@208
|
185
|
cannam@208
|
186 virtual size_t getPreferredStepSize() const {
|
cannam@208
|
187 return getPlugin()->getPreferredStepSize();
|
cannam@208
|
188 }
|
cannam@208
|
189
|
cannam@208
|
190 virtual size_t getMinChannelCount() const {
|
cannam@208
|
191 return getPlugin()->getMinChannelCount();
|
cannam@208
|
192 }
|
cannam@208
|
193
|
cannam@208
|
194 virtual size_t getMaxChannelCount() const {
|
cannam@208
|
195 return getPlugin()->getMaxChannelCount();
|
cannam@208
|
196 }
|
cannam@208
|
197
|
cannam@208
|
198 virtual OutputList getOutputDescriptors() const {
|
cannam@208
|
199 return getPlugin()->getOutputDescriptors();
|
cannam@208
|
200 }
|
cannam@208
|
201
|
cannam@208
|
202 virtual FeatureSet process(const float *const *inputBuffers,
|
cannam@208
|
203 Vamp::RealTime timestamp) {
|
cannam@208
|
204 return getPlugin()->process(inputBuffers, timestamp);
|
cannam@208
|
205 }
|
cannam@208
|
206
|
cannam@208
|
207 virtual FeatureSet getRemainingFeatures() {
|
cannam@208
|
208 return getPlugin()->getRemainingFeatures();
|
cannam@208
|
209 }
|
cannam@208
|
210
|
cannam@208
|
211 private:
|
cannam@208
|
212 LogCallback *m_logger;
|
cannam@208
|
213 ProcessQtTransport m_transport;
|
cannam@208
|
214 CapnpRRClient m_client;
|
cannam@208
|
215 Vamp::Plugin *m_plugin;
|
cannam@208
|
216 Vamp::Plugin *getPlugin() const {
|
cannam@208
|
217 if (!m_plugin) {
|
cannam@208
|
218 log("PiperAutoPlugin: getPlugin() failed (caller should have called PiperAutoPlugin::isOK)");
|
cannam@208
|
219 throw std::logic_error("Plugin load failed");
|
cannam@208
|
220 }
|
cannam@208
|
221 return m_plugin;
|
cannam@208
|
222 }
|
cannam@208
|
223
|
cannam@208
|
224 void log(std::string message) const {
|
cannam@208
|
225 if (m_logger) m_logger->log(message);
|
cannam@208
|
226 else std::cerr << message << std::endl;
|
cannam@208
|
227 }
|
cannam@208
|
228 };
|
cannam@208
|
229
|
cannam@208
|
230 }
|
cannam@208
|
231 }
|
cannam@208
|
232
|
cannam@208
|
233 #endif
|
cannam@208
|
234
|
cannam@208
|
235
|