LV2 Toolkit  1.2.0
plugin.hpp
1 /*
2  plugin.hpp - Support file for writing LV2 plugins in C++
3  Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
4  Modified by Dave Robillard, 2008
5  Modified by Michael Fisher, 2012
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
20 */
21 
22 #ifndef LVTK_PLUGIN_HPP
23 #define LVTK_PLUGIN_HPP
24 
25 #include <iostream>
26 #include <cstdarg>
27 #include <cstring>
28 #include <string>
29 #include <vector>
30 
31 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
32 
33 #include <lvtk/feature.hpp>
34 #include <lvtk/ext/common.h>
35 #include <lvtk/ext/bufsize.hpp>
36 #include <lvtk/ext/resize_port.hpp>
37 #include <lvtk/ext/state.hpp>
38 #include <lvtk/ext/worker.hpp>
39 
40 #include "private/debug.hpp"
41 
89 namespace lvtk {
90 
91  using std::vector;
92 
96  class DescList : public vector<LV2_Descriptor> {
97  public:
98  ~DescList();
99  };
100 
101 
105  DescList& get_lv2_descriptors();
106 
107 
155  template <class Derived,
156  class Ext1 = end, class Ext2 = end, class Ext3 = end,
157  class Ext4 = end, class Ext5 = end, class Ext6 = end,
158  class Ext7 = end, class Ext8 = end, class Ext9 = end>
159  class Plugin : public MixinTree<Derived, Ext1, Ext2, Ext3,
160  Ext4, Ext5, Ext6,
161  Ext7, Ext8, Ext9>
162  {
163  public:
164 
171  Plugin(uint32_t ports)
172  : m_ports(ports, 0), m_ok(true)
173  {
174  m_features = s_features;
175  m_bundle_path = s_bundle_path;
176  s_features = 0;
177  s_bundle_path = 0;
178 
179  if (m_features)
180  {
181  FeatureHandlerMap hmap;
182  Derived::map_feature_handlers (hmap);
183 
184  for (const Feature* const* iter = m_features; *iter != 0; ++iter)
185  {
186  FeatureHandlerMap::iterator miter;
187  miter = hmap.find((*iter)->URI);
188 
189  if (miter != hmap.end())
190  {
191  miter->second (static_cast<Derived*>(this), (*iter)->data);
192  }
193  }
194  }
195  }
196 
197 
207  void connect_port(uint32_t port, void* data_location) {
208  m_ports[port] = data_location;
209  }
210 
214  void activate() { }
215 
226  void run(uint32_t sample_count) { }
227 
232  void deactivate() { }
233 
246  static unsigned
247  register_class(const char* uri)
248  {
249  LV2_Descriptor desc;
250  std::memset(&desc, 0, sizeof(LV2_Descriptor));
251  desc.URI = strdup (uri);
252  desc.instantiate = &Derived::_create_plugin_instance;
253  desc.connect_port = &Derived::_connect_port;
254  desc.activate = &Derived::_activate;
255  desc.run = &Derived::_run;
256  desc.deactivate = &Derived::_deactivate;
257  desc.cleanup = &Derived::_delete_plugin_instance;
258  desc.extension_data = &Derived::extension_data;
259  get_lv2_descriptors().push_back (desc);
260 
261  return get_lv2_descriptors().size() - 1;
262  }
263 
272  bool check_ok() {
273  return m_ok && MixinTree<Derived,
274  Ext1, Ext2, Ext3, Ext4, Ext5,
275  Ext6, Ext7, Ext8, Ext9>::check_ok();
276  }
277 
278  protected:
279 
291  template <typename T> T*&
292  p(uint32_t port)
293  {
294  return reinterpret_cast<T*&>(m_ports[port]);
295  }
296 
300  float*&
301  p(uint32_t port) {
302  return reinterpret_cast<float*&>(m_ports[port]);
303  }
304 
308  const char*
309  bundle_path() const
310  {
311  return m_bundle_path;
312  }
313 
322  void
323  set_ok(bool ok)
324  {
325  m_ok = ok;
326  }
327 
331  std::vector<void*> m_ports;
332 
333  private:
334 
338  static void _connect_port(LV2_Handle instance, uint32_t port,
339  void* data_location) {
340  reinterpret_cast<Derived*>(instance)->connect_port(port, data_location);
341  }
342 
346  static void _activate(LV2_Handle instance) {
347  reinterpret_cast<Derived*>(instance)->activate();
348  }
349 
353  static void _run(LV2_Handle instance, uint32_t sample_count) {
354  reinterpret_cast<Derived*>(instance)->run(sample_count);
355  }
356 
360  static void _deactivate(LV2_Handle instance) {
361  reinterpret_cast<Derived*>(instance)->deactivate();
362  }
363 
368  static LV2_Handle _create_plugin_instance(const LV2_Descriptor* descriptor,
369  double sample_rate,
370  const char* bundle_path,
371  const LV2_Feature* const*
372  features)
373  {
374  // copy some data to static variables so the subclasses don't have to
375  // bother with it
376  s_features = features;
377  s_bundle_path = bundle_path;
378 
379  if (LVTK_DEBUG)
380  {
381  std::clog<<"[plugin] Instantiating plugin...\n"
382  <<" Bundle path: "<<bundle_path<<"\n"
383  <<" features: \n";
384 
385  FeatureIter feats (features);
386  while (const Feature* feature = feats.next())
387  std::clog <<" "<< feature->URI << "\n";
388 
389  std::clog<<" Creating plugin object...\n";
390  }
391 
392  Derived* t = new Derived (sample_rate);
393 
394  if (LVTK_DEBUG) { std::clog<<" Validating...\n"; }
395 
396  if (t->check_ok()) {
397  if (LVTK_DEBUG)
398  std::clog<<" Done!"<<std::endl;
399  return reinterpret_cast<LV2_Handle>(t);
400  }
401 
402  if (LVTK_DEBUG) {
403  std::clog<<" Failed!\n"
404  <<" Deleting object."<<std::endl;
405  }
406 
407  delete t;
408  return 0;
409  }
410 
415  static void _delete_plugin_instance(LV2_Handle instance) {
416  delete reinterpret_cast<Derived*> (instance);
417  }
418 
419 
420  private:
421 
426  Feature const* const* m_features;
427 
432  char const* m_bundle_path;
433 
438  static Feature const* const* s_features;
439 
444  static char const* s_bundle_path;
445 
451  bool m_ok;
452 
453  };
454 
455 
456  // The static variables need to be initialised.
457  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
458  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
459  Feature const* const*
460  Plugin<Derived, Ext1, Ext2, Ext3, Ext4,
461  Ext5, Ext6, Ext7, Ext8, Ext9>::s_features = 0;
462 
463  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
464  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
465  char const*
466  Plugin<Derived, Ext1, Ext2, Ext3, Ext4,
467  Ext5, Ext6, Ext7, Ext8, Ext9>::s_bundle_path = 0;
468 
469 
494 } /* namespace lvtk */
495 
496 
497 #endif /* LVTK_PLUGIN_HPP */
void set_ok(bool ok)
Definition: plugin.hpp:323
const char * bundle_path() const
Definition: plugin.hpp:309
void activate()
Definition: plugin.hpp:214
Definition: plugin.hpp:96
void connect_port(uint32_t port, void *data_location)
Definition: plugin.hpp:207
void deactivate()
Definition: plugin.hpp:232
void run(uint32_t sample_count)
Definition: plugin.hpp:226
LV2_Feature Feature
Definition: feature.hpp:41
Plugin(uint32_t ports)
Definition: plugin.hpp:171
Definition: feature.hpp:34
Definition: plugin.hpp:159
T *& p(uint32_t port)
Definition: plugin.hpp:292
float *& p(uint32_t port)
Definition: plugin.hpp:301
static unsigned register_class(const char *uri)
Definition: plugin.hpp:247
Definition: feature.hpp:59
map< string, FeatureHandler > FeatureHandlerMap
Definition: feature.hpp:57