My Project 1.0.5
lv2plugin.hpp
1/****************************************************************************
2
3 lv2plugin.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
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
21
22****************************************************************************/
23
24#ifndef LV2PLUGIN_HPP
25#define LV2PLUGIN_HPP
26
27#include <cstdarg>
28
29#include <cstring>
30#include <string>
31#include <vector>
32
33#include <lv2.h>
34#include <lv2_uri_map.h>
35#include <lv2_saverestore.h>
36#include <lv2_event.h>
37#include <lv2_contexts.h>
38#include <lv2types.hpp>
39
40
73namespace LV2 {
74
75
79 class DescList : public std::vector<LV2_Descriptor> {
80 public:
81 ~DescList();
82 };
83
84
88 DescList& get_lv2_descriptors();
89
90
131 template <class Derived,
132 class Ext1 = End, class Ext2 = End, class Ext3 = End,
133 class Ext4 = End, class Ext5 = End, class Ext6 = End,
134 class Ext7 = End, class Ext8 = End, class Ext9 = End>
135 class Plugin : public MixinTree<Derived,
136 Ext1, Ext2, Ext3, Ext4, Ext5,
137 Ext6, Ext7, Ext8, Ext9> {
138 public:
139
146 Plugin(uint32_t ports)
147 : m_ports(ports, 0),
148 m_ok(true) {
149 m_features = s_features;
150 m_bundle_path = s_bundle_path;
151 s_features = 0;
152 s_bundle_path = 0;
153 if (m_features) {
154 FeatureHandlerMap hmap;
155 Derived::map_feature_handlers(hmap);
156 for (const Feature* const* iter = m_features; *iter != 0; ++iter) {
157 FeatureHandlerMap::iterator miter;
158 miter = hmap.find((*iter)->URI);
159 if (miter != hmap.end())
160 miter->second(static_cast<Derived*>(this), (*iter)->data);
161 }
162 }
163 }
164
174 void connect_port(uint32_t port, void* data_location) {
175 m_ports[port] = data_location;
176 }
177
181 void activate() { }
182
193 void run(uint32_t sample_count) { }
194
199 void deactivate() { }
200
213 static unsigned register_class(const std::string& uri) {
214 LV2_Descriptor desc;
215 std::memset(&desc, 0, sizeof(LV2_Descriptor));
216 char* c_uri = new char[uri.size() + 1];
217 std::memcpy(c_uri, uri.c_str(), uri.size() + 1);
218 desc.URI = c_uri;
219 desc.instantiate = &Derived::_create_plugin_instance;
220 desc.connect_port = &Derived::_connect_port;
221 desc.activate = &Derived::_activate;
222 desc.run = &Derived::_run;
223 desc.deactivate = &Derived::_deactivate;
224 desc.cleanup = &Derived::_delete_plugin_instance;
225 desc.extension_data = &Derived::extension_data;
226 get_lv2_descriptors().push_back(desc);
227 return get_lv2_descriptors().size() - 1;
228 }
229
238 bool check_ok() {
239 return m_ok && MixinTree<Derived,
240 Ext1, Ext2, Ext3, Ext4, Ext5,
241 Ext6, Ext7, Ext8, Ext9>::check_ok();
242 }
243
244 protected:
245
257 template <typename T> T*& p(uint32_t port) {
258 return reinterpret_cast<T*&>(m_ports[port]);
259 }
260
264 float*& p(uint32_t port) {
265 return reinterpret_cast<float*&>(m_ports[port]);
266 }
267
271 const char* bundle_path() const {
272 return m_bundle_path;
273 }
274
283 void set_ok(bool ok) {
284 m_ok = ok;
285 }
286
290 std::vector<void*> m_ports;
291
292 private:
293
297 static void _connect_port(LV2_Handle instance, uint32_t port,
298 void* data_location) {
299 reinterpret_cast<Derived*>(instance)->connect_port(port, data_location);
300 }
301
305 static void _activate(LV2_Handle instance) {
306 reinterpret_cast<Derived*>(instance)->activate();
307 }
308
312 static void _run(LV2_Handle instance, uint32_t sample_count) {
313 reinterpret_cast<Derived*>(instance)->run(sample_count);
314 }
315
319 static void _deactivate(LV2_Handle instance) {
320 reinterpret_cast<Derived*>(instance)->deactivate();
321 }
322
327 static LV2_Handle _create_plugin_instance(const LV2_Descriptor* descriptor,
328 double sample_rate,
329 const char* bundle_path,
330 const Feature* const*
331 features) {
332
333 // copy some data to static variables so the subclasses don't have to
334 // bother with it
335 s_features = features;
336 s_bundle_path = bundle_path;
337
338 Derived* t = new Derived(sample_rate);
339 if (t->check_ok())
340 return reinterpret_cast<LV2_Handle>(t);
341 delete t;
342 return 0;
343 }
344
349 static void _delete_plugin_instance(LV2_Handle instance) {
350 delete reinterpret_cast<Derived*>(instance);
351 }
352
353
354 private:
355
360 LV2::Feature const* const* m_features;
361
366 char const* m_bundle_path;
367
372 static LV2::Feature const* const* s_features;
373
378 static char const* s_bundle_path;
379
385 bool m_ok;
386
387 };
388
389
390 // The static variables need to be initialised.
391 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
392 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
393 LV2::Feature const* const*
394 Plugin<Derived, Ext1, Ext2, Ext3, Ext4,
395 Ext5, Ext6, Ext7, Ext8, Ext9>::s_features = 0;
396
397 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
398 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
399 char const*
400 Plugin<Derived, Ext1, Ext2, Ext3, Ext4,
401 Ext5, Ext6, Ext7, Ext8, Ext9>::s_bundle_path = 0;
402
403
429 template <bool Required = true>
431
436 template <class Derived> struct I : Extension<Required> {
437
439 I() : m_buffer_size(0) { }
440
442 static void map_feature_handlers(FeatureHandlerMap& hmap) {
443 hmap["http://tapas.affenbande.org/lv2/ext/fixed-buffersize"] =
445 }
446
448 static void handle_feature(void* instance, void* data) {
449 Derived* d = reinterpret_cast<Derived*>(instance);
450 I<Derived>* fe = static_cast<I<Derived>*>(d);
451 fe->m_buffer_size = *reinterpret_cast<uint32_t*>(data);
452 fe->m_ok = true;
453 }
454
455 protected:
456
460 uint32_t get_buffer_size() const { return m_buffer_size; }
461
462 uint32_t m_buffer_size;
463
464 };
465
466 };
467
476 template <bool Required = true>
478
483 template <class Derived> struct I : Extension<Required> {
484
486 I() : m_buffer_size(0) { }
487
489 static void map_feature_handlers(FeatureHandlerMap& hmap) {
490 hmap["http://tapas.affenbande.org/lv2/ext/power-of-two-buffersize"] =
492 }
493
495 static void handle_feature(void* instance, void* data) {
496 Derived* d = reinterpret_cast<Derived*>(instance);
497 I<Derived>* fe = static_cast<I<Derived>*>(d);
498 fe->m_buffer_size = *reinterpret_cast<uint32_t*>(data);
499 fe->m_ok = true;
500 }
501
502 protected:
503
507 uint32_t get_buffer_size() const { return m_buffer_size; }
508
509 uint32_t m_buffer_size;
510
511 };
512
513 };
514
515
522 template <bool Required = true>
523 struct SaveRestore {
524
529 template <class Derived> struct I : Extension<Required> {
530
532 I() { }
533
535 static void map_feature_handlers(FeatureHandlerMap& hmap) {
536 hmap[LV2_SAVERESTORE_URI] = &I<Derived>::handle_feature;
537 }
538
540 static void handle_feature(void* instance, void* data) {
541 Derived* d = reinterpret_cast<Derived*>(instance);
542 I<Derived>* fe = static_cast<I<Derived>*>(d);
543 fe->m_ok = true;
544 }
545
547 static const void* extension_data(const char* uri) {
548 if (!std::strcmp(uri, LV2_SAVERESTORE_URI)) {
549 static LV2SR_Descriptor srdesc = { &I<Derived>::_save,
551 return &srdesc;
552 }
553 return 0;
554 }
555
568 char* save(const char* directory, LV2SR_File*** files) { return 0; }
569
576 char* restore(const LV2SR_File** files) { return 0; }
577
578 protected:
579
582 static char* _save(LV2_Handle h,
583 const char* directory, LV2SR_File*** files) {
584 return reinterpret_cast<Derived*>(h)->save(directory, files);
585 }
586
589 static char* _restore(LV2_Handle h, const LV2SR_File** files) {
590 return reinterpret_cast<Derived*>(h)->restore(files);
591 }
592
593 };
594 };
595
596
603 template <bool Required = true>
604 struct EventRef {
605
610 template <class Derived> struct I : Extension<Required> {
611
613 I() : m_callback_data(0), m_ref_func(0), m_unref_func(0) { }
614
616 static void map_feature_handlers(FeatureHandlerMap& hmap) {
617 hmap[LV2_EVENT_URI] = &I<Derived>::handle_feature;
618 }
619
621 static void handle_feature(void* instance, void* data) {
622 Derived* d = reinterpret_cast<Derived*>(instance);
623 I<Derived>* fe = static_cast<I<Derived>*>(d);
624 LV2_Event_Feature* ef = reinterpret_cast<LV2_Event_Feature*>(data);
625 fe->m_callback_data = ef->callback_data;
626 fe->m_ref_func = ef->lv2_event_ref;
627 fe->m_unref_func = ef->lv2_event_unref;
628 fe->m_ok = true;
629 }
630
631 protected:
632
642 uint32_t event_ref(LV2_Event* event) {
643 return m_ref_func(m_callback_data, event);
644 }
645
650 uint32_t event_unref(LV2_Event* event) {
651 return m_unref_func(m_callback_data, event);
652 }
653
654 LV2_Event_Callback_Data m_callback_data;
655 uint32_t (*m_ref_func)(LV2_Event_Callback_Data, LV2_Event*);
656 uint32_t (*m_unref_func)(LV2_Event_Callback_Data, LV2_Event*);
657
658 };
659
660 };
661
662
670 template <bool Required = true>
671 struct MsgContext {
672
677 template <class Derived> struct I : Extension<Required> {
678
680 I() { }
681
683 static void map_feature_handlers(FeatureHandlerMap& hmap) {
684 hmap[LV2_CONTEXT_MESSAGE] = &I<Derived>::handle_feature;
685 }
686
688 static void handle_feature(void* instance, void* data) {
689 Derived* d = reinterpret_cast<Derived*>(instance);
690 I<Derived>* fe = static_cast<I<Derived>*>(d);
691 fe->m_ok = true;
692 }
693
695 static const void* extension_data(const char* uri) {
696 if (!std::strcmp(uri, LV2_CONTEXT_MESSAGE)) {
697 static LV2_Blocking_Context desc = { &I<Derived>::_blocking_run,
699 return &desc;
700 }
701 return 0;
702 }
703
708 bool blocking_run(uint8_t* outputs_written) { return false; }
709
710 protected:
711
714 static bool _blocking_run(LV2_Handle h, uint8_t* outputs_written) {
715 return reinterpret_cast<Derived*>(h)->blocking_run(outputs_written);
716 }
717
720 static void _connect_port(LV2_Handle h, uint32_t port, void* buffer) {
721 reinterpret_cast<Derived*>(h)->connect_port(port, buffer);
722 }
723
724 };
725 };
726
727
728}
729
730
731#endif
Definition lv2plugin.hpp:137
void run(uint32_t sample_count)
Definition lv2plugin.hpp:193
void activate()
Definition lv2plugin.hpp:181
void set_ok(bool ok)
Definition lv2plugin.hpp:283
void connect_port(uint32_t port, void *data_location)
Definition lv2plugin.hpp:174
T *& p(uint32_t port)
Definition lv2plugin.hpp:257
void deactivate()
Definition lv2plugin.hpp:199
static unsigned register_class(const std::string &uri)
Definition lv2plugin.hpp:213
float *& p(uint32_t port)
Definition lv2plugin.hpp:264
Plugin(uint32_t ports)
Definition lv2plugin.hpp:146
const char * bundle_path() const
Definition lv2plugin.hpp:271
Definition lv2plugin.hpp:610
uint32_t event_unref(LV2_Event *event)
Definition lv2plugin.hpp:650
uint32_t event_ref(LV2_Event *event)
Definition lv2plugin.hpp:642
Definition lv2plugin.hpp:604
Definition lv2plugin.hpp:436
uint32_t get_buffer_size() const
Definition lv2plugin.hpp:460
Definition lv2plugin.hpp:430
Definition lv2plugin.hpp:483
uint32_t get_buffer_size() const
Definition lv2plugin.hpp:507
Definition lv2plugin.hpp:477
Definition lv2plugin.hpp:677
Definition lv2plugin.hpp:529
char * save(const char *directory, LV2SR_File ***files)
Definition lv2plugin.hpp:568
char * restore(const LV2SR_File **files)
Definition lv2plugin.hpp:576
Definition lv2plugin.hpp:523