LV2 Toolkit  1.1.1
 All Classes Namespaces Functions Typedefs Enumerations Enumerator Groups Pages
plugin.hpp
1 /****************************************************************************
2 
3  plugin.hpp - Support file for writing LV2 plugins in C++
4 
5  Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
6  Modified by Dave Robillard, 2008
7  Modified by Michael Fisher, 2012
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
22 
23  ****************************************************************************/
24 
25 #ifndef LVTK_LV2_PLUGIN_HPP
26 #define LVTK_LV2_PLUGIN_HPP
27 
28 #include <iostream>
29 #include <cstdarg>
30 #include <cstring>
31 #include <string>
32 #include <vector>
33 
34 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
35 
36 #include <lvtk/feature.hpp>
37 #include <lvtk/ext/common.h>
38 #include <lvtk/ext/bufsize.hpp>
39 #include <lvtk/ext/resize_port.hpp>
40 #include <lvtk/ext/state.hpp>
41 #include <lvtk/ext/worker.hpp>
42 
43 #include "private/debug.hpp"
44 
92 namespace lvtk {
93 
94  using std::vector;
95 
99  class DescList : public vector<LV2_Descriptor> {
100  public:
101  ~DescList();
102  };
103 
104 
108  DescList& get_lv2_descriptors();
109 
110 
158  template <class Derived,
159  class Ext1 = end, class Ext2 = end, class Ext3 = end,
160  class Ext4 = end, class Ext5 = end, class Ext6 = end,
161  class Ext7 = end, class Ext8 = end, class Ext9 = end>
162  class Plugin : public MixinTree<Derived, Ext1, Ext2, Ext3,
163  Ext4, Ext5, Ext6,
164  Ext7, Ext8, Ext9>
165  {
166  public:
167 
174  Plugin(uint32_t ports)
175  : m_ports(ports, 0), m_ok(true)
176  {
177  m_features = s_features;
178  m_bundle_path = s_bundle_path;
179  s_features = 0;
180  s_bundle_path = 0;
181 
182  if (m_features)
183  {
184  FeatureHandlerMap hmap;
185  Derived::map_feature_handlers (hmap);
186 
187  for (const Feature* const* iter = m_features; *iter != 0; ++iter)
188  {
189  FeatureHandlerMap::iterator miter;
190  miter = hmap.find((*iter)->URI);
191 
192  if (miter != hmap.end())
193  {
194  miter->second (static_cast<Derived*>(this), (*iter)->data);
195  }
196  }
197  }
198  }
199 
200 
210  void connect_port(uint32_t port, void* data_location) {
211  m_ports[port] = data_location;
212  }
213 
217  void activate() { }
218 
229  void run(uint32_t sample_count) { }
230 
235  void deactivate() { }
236 
249  static unsigned
250  register_class(const char* uri)
251  {
252  LV2_Descriptor desc;
253  std::memset(&desc, 0, sizeof(LV2_Descriptor));
254  desc.URI = strdup (uri);
255  desc.instantiate = &Derived::_create_plugin_instance;
256  desc.connect_port = &Derived::_connect_port;
257  desc.activate = &Derived::_activate;
258  desc.run = &Derived::_run;
259  desc.deactivate = &Derived::_deactivate;
260  desc.cleanup = &Derived::_delete_plugin_instance;
261  desc.extension_data = &Derived::extension_data;
262  get_lv2_descriptors().push_back (desc);
263 
264  return get_lv2_descriptors().size() - 1;
265  }
266 
275  bool check_ok() {
276  return m_ok && MixinTree<Derived,
277  Ext1, Ext2, Ext3, Ext4, Ext5,
278  Ext6, Ext7, Ext8, Ext9>::check_ok();
279  }
280 
281  protected:
282 
294  template <typename T> T*&
295  p(uint32_t port)
296  {
297  return reinterpret_cast<T*&>(m_ports[port]);
298  }
299 
303  float*&
304  p(uint32_t port) {
305  return reinterpret_cast<float*&>(m_ports[port]);
306  }
307 
311  const char*
312  bundle_path() const
313  {
314  return m_bundle_path;
315  }
316 
325  void
326  set_ok(bool ok)
327  {
328  m_ok = ok;
329  }
330 
334  std::vector<void*> m_ports;
335 
336  private:
337 
341  static void _connect_port(LV2_Handle instance, uint32_t port,
342  void* data_location) {
343  reinterpret_cast<Derived*>(instance)->connect_port(port, data_location);
344  }
345 
349  static void _activate(LV2_Handle instance) {
350  reinterpret_cast<Derived*>(instance)->activate();
351  }
352 
356  static void _run(LV2_Handle instance, uint32_t sample_count) {
357  reinterpret_cast<Derived*>(instance)->run(sample_count);
358  }
359 
363  static void _deactivate(LV2_Handle instance) {
364  reinterpret_cast<Derived*>(instance)->deactivate();
365  }
366 
371  static LV2_Handle _create_plugin_instance(const LV2_Descriptor* descriptor,
372  double sample_rate,
373  const char* bundle_path,
374  const LV2_Feature* const*
375  features)
376  {
377  // copy some data to static variables so the subclasses don't have to
378  // bother with it
379  s_features = features;
380  s_bundle_path = bundle_path;
381 
382  if (LVTK_DEBUG)
383  {
384  std::clog<<"[plugin] Instantiating plugin...\n"
385  <<" Bundle path: "<<bundle_path<<"\n"
386  <<" features: \n";
387 
388  FeatureIter feats (features);
389  while (const Feature* feature = feats.next())
390  std::clog <<" "<< feature->URI << "\n";
391 
392  std::clog<<" Creating plugin object...\n";
393  }
394 
395  Derived* t = new Derived (sample_rate);
396 
397  if (LVTK_DEBUG) { std::clog<<" Validating...\n"; }
398 
399  if (t->check_ok()) {
400  if (LVTK_DEBUG)
401  std::clog<<" Done!"<<std::endl;
402  return reinterpret_cast<LV2_Handle>(t);
403  }
404 
405  if (LVTK_DEBUG) {
406  std::clog<<" Failed!\n"
407  <<" Deleting object."<<std::endl;
408  }
409 
410  delete t;
411  return 0;
412  }
413 
418  static void _delete_plugin_instance(LV2_Handle instance) {
419  delete reinterpret_cast<Derived*> (instance);
420  }
421 
422 
423  private:
424 
429  Feature const* const* m_features;
430 
435  char const* m_bundle_path;
436 
441  static Feature const* const* s_features;
442 
447  static char const* s_bundle_path;
448 
454  bool m_ok;
455 
456  };
457 
458 
459  // The static variables need to be initialised.
460  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
461  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
462  Feature const* const*
463  Plugin<Derived, Ext1, Ext2, Ext3, Ext4,
464  Ext5, Ext6, Ext7, Ext8, Ext9>::s_features = 0;
465 
466  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
467  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
468  char const*
469  Plugin<Derived, Ext1, Ext2, Ext3, Ext4,
470  Ext5, Ext6, Ext7, Ext8, Ext9>::s_bundle_path = 0;
471 
472 
497 } /* namespace lvtk */
498 
499 
500 #endif /* LVTK_LV2_PLUGIN_HPP */