diff options
-rw-r--r-- | lv2/lv2plug.in/ns/lv2core/Lib.hpp | 17 | ||||
-rw-r--r-- | lv2/lv2plug.in/ns/lv2core/Plugin.hpp | 132 | ||||
-rw-r--r-- | plugins/eg-midiamp.lv2/midiamp.cpp | 29 |
3 files changed, 87 insertions, 91 deletions
diff --git a/lv2/lv2plug.in/ns/lv2core/Lib.hpp b/lv2/lv2plug.in/ns/lv2core/Lib.hpp index 5d7670b..c7a1d95 100644 --- a/lv2/lv2plug.in/ns/lv2core/Lib.hpp +++ b/lv2/lv2plug.in/ns/lv2core/Lib.hpp @@ -1,5 +1,5 @@ /* - Copyright 2015 David Robillard <http://drobilla.net> + Copyright 2015-2016 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -40,15 +40,10 @@ namespace lv2 { } @endcode */ -template<class Derived> class Lib : public LV2_Lib_Descriptor { public: - /** - Library constructor. - */ - Lib(const char* bundle_path, - const LV2_Feature*const* features) + Lib(const char* bundle_path, const LV2_Feature*const* features) { LV2_Lib_Descriptor::handle = this; LV2_Lib_Descriptor::size = sizeof(LV2_Lib_Descriptor); @@ -56,6 +51,8 @@ public: LV2_Lib_Descriptor::get_plugin = s_get_plugin; } + virtual ~Lib() {} + /** Plugin accessor, override to return your plugin descriptors. @@ -63,16 +60,16 @@ public: indices MUST result in this function returning NULL, so the host can enumerate plugins by increasing `index` until NULL is returned. */ - const LV2_Descriptor* get_plugin(uint32_t index) { return NULL; } + virtual const LV2_Descriptor* get_plugin(uint32_t index) { return NULL; } private: static void s_cleanup(LV2_Lib_Handle handle) { - delete reinterpret_cast<Derived*>(handle); + delete reinterpret_cast<Lib*>(handle); } static const LV2_Descriptor* s_get_plugin(LV2_Lib_Handle handle, uint32_t index) { - return reinterpret_cast<Derived*>(handle)->get_plugin(index); + return reinterpret_cast<Lib*>(handle)->get_plugin(index); } }; diff --git a/lv2/lv2plug.in/ns/lv2core/Plugin.hpp b/lv2/lv2plug.in/ns/lv2core/Plugin.hpp index 597dd38..ca054a4 100644 --- a/lv2/lv2plug.in/ns/lv2core/Plugin.hpp +++ b/lv2/lv2plug.in/ns/lv2core/Plugin.hpp @@ -22,32 +22,19 @@ namespace lv2 { /** - C++ interface for writing an LV2 plugin. + Base interface for plugins. This interface is a convenience for plugin authors only, and is not an ABI - used by hosts. To implement a plugin, inherit from this interface with the - derived class passed as the template parameter. The C LV2_Descriptor for the - plugin can be fetched with descriptor(). - + used by hosts. This is the top of a plugin's class hierarchy, which is + inherited by extension mixins. To implement a plugin, inherit from the + lv2::Plugin template, passing any desired extension mixins as template + parameters: @code class MyPlug : public lv2::Plugin<MyPlug> { // ... }; - - static const LV2_Descriptor p = MyPlug::descriptor("http://example.org/plug"); - @endcode - - This class is a stateless interface and imposes no restrictions or overhead - compared to a plugin implemented using the underlying C interface. Note - that this is not a virtual class, so calling methods from a Plugin* base - pointer will not work. Instead, anything that must dispatch on Plugin - methods takes a template parameter for static dispatch. - - The destructor will be called when the host cleans up the plugin. */ -template<class Derived> -class PluginBase -{ +class PluginBase { public: /** Instantiate the plugin. @@ -79,13 +66,21 @@ public: @return A handle for the new plugin instance, or NULL if instantiation has failed. */ - PluginBase(double sampcle_rate, + PluginBase(double sample_rate, const char* bundle_path, const LV2_Feature*const* features, bool* valid) {} /** + Clean up plugin instance. + + If activate() was called for a plugin instance then a corresponding call + to deactivate() MUST be made before the plugin is destroyed. + */ + virtual ~PluginBase() {} + + /** Connect a port on a plugin instance to a memory location. Plugin writers should be aware that the host may elect to use the same @@ -117,7 +112,7 @@ public: used to read/write data when run() is called. Data present at the time of the connect_port() call MUST NOT be considered meaningful. */ - void connect_port(uint32_t port, void* data_location) {} + virtual void connect_port(uint32_t port, void* data_location) {} /** Initialise a plugin instance and activate it for use. @@ -140,7 +135,7 @@ public: some point in the future. Note that connect_port() may be called before or after activate(). */ - void activate() {} + virtual void activate() {} /** Run a plugin instance for a block. @@ -163,7 +158,7 @@ public: @param sample_count The block size (in samples) for which the plugin instance must run. */ - void run(uint32_t sample_count) {} + virtual void run(uint32_t sample_count) {} /** Deactivate a plugin instance (counterpart to activate()). @@ -183,7 +178,7 @@ public: called. Note that connect_port() may be called before or after deactivate(). */ - void deactivate() {} + virtual void deactivate() {} /** Return additional plugin data defined by some extenion. @@ -199,33 +194,54 @@ public: The host is never responsible for freeing the returned value. */ static const void* extension_data(const char* uri) { return NULL; } +}; - /** - Get an LV2_Descriptor for a plugin class. +/** Empty extension mixin used to terminate mixin list. */ +template<typename Super> +class NoExtension : public Super {}; - @code - static const LV2_Descriptor a = lv2::descriptor<Amp>("http://example.org/amp"); - @endcode - */ - static LV2_Descriptor descriptor(const char* uri) { - const LV2_Descriptor desc = { uri, - &s_instantiate, - &s_connect_port, - &s_activate, - &s_run, - &s_deactivate, - &s_cleanup, - &PluginBase::extension_data }; - return desc; +/** Plugin mixin list. */ +template<template<class Super> class First=NoExtension, + template<class S> class... Rest> +struct Plugin : public First< Plugin<Rest...> > { + Plugin(double r, const char* b, const LV2_Feature* const* f, bool* v) + : First< Plugin<Rest...> >(r, b, f, v) + {} +}; + +template<> +struct Plugin<NoExtension> : public PluginBase { + Plugin(double r, const char* b, const LV2_Feature* const* f, bool* v) + : PluginBase(r, b, f, v) + {} +}; + +/** + Plugin descriptor. + + @code + static const Descriptor<Amp> amp("http://example.org/amp"); + @endcode +*/ +template<typename PluginType> +struct Descriptor : public LV2_Descriptor { + Descriptor(const char* uri) { + URI = uri; + instantiate = s_instantiate; + connect_port = s_connect_port; + activate = s_activate; + run = s_run; + deactivate = s_deactivate; + cleanup = s_cleanup; + extension_data = &PluginType::extension_data; } -private: static LV2_Handle s_instantiate(const LV2_Descriptor* descriptor, double rate, const char* bundle, const LV2_Feature* const* features) { bool valid = true; - Derived* instance = new Derived(rate, bundle, features, &valid); + PluginType* instance = new PluginType(rate, bundle, features, &valid); if (!valid) { delete instance; return nullptr; @@ -234,48 +250,26 @@ private: } static void s_connect_port(LV2_Handle instance, uint32_t port, void* buf) { - reinterpret_cast<Derived*>(instance)->connect_port(port, buf); + reinterpret_cast<PluginType*>(instance)->connect_port(port, buf); } static void s_activate(LV2_Handle instance) { - reinterpret_cast<Derived*>(instance)->activate(); + reinterpret_cast<PluginType*>(instance)->activate(); } static void s_run(LV2_Handle instance, uint32_t sample_count) { - reinterpret_cast<Derived*>(instance)->run(sample_count); + reinterpret_cast<PluginType*>(instance)->run(sample_count); } static void s_deactivate(LV2_Handle instance) { - reinterpret_cast<Derived*>(instance)->deactivate(); + reinterpret_cast<PluginType*>(instance)->deactivate(); } static void s_cleanup(LV2_Handle instance) { - delete reinterpret_cast<Derived*>(instance); + delete reinterpret_cast<PluginType*>(instance); } }; -template<class Derived, template<class S> class First=PluginBase, template<class S> class... Rest> -struct Plugin : public First< Plugin<Derived, Rest...> > { - Plugin(double rate, - const char* bundle_path, - const LV2_Feature* const* features, - bool* valid) - : First< Plugin<Derived, Rest...> >(rate, bundle_path, features, valid) - {} - -}; - -template<class Derived, template<class S> class First> -struct Plugin<Derived, First> : public First< PluginBase<Derived> > { - Plugin(double rate, - const char* bundle_path, - const LV2_Feature* const* features, - bool* valid) - : First< PluginBase<Derived> >(rate, bundle_path, features, valid) - {} - -}; - } /* namespace lv2 */ #endif /* LV2_PLUGIN_HPP */ diff --git a/plugins/eg-midiamp.lv2/midiamp.cpp b/plugins/eg-midiamp.lv2/midiamp.cpp index ac3d055..700624c 100644 --- a/plugins/eg-midiamp.lv2/midiamp.cpp +++ b/plugins/eg-midiamp.lv2/midiamp.cpp @@ -23,17 +23,24 @@ #include "lv2/lv2plug.in/ns/lv2core/Lib.hpp" #include "lv2/lv2plug.in/ns/lv2core/Plugin.hpp" -class MidiAmp; -typedef typename lv2::Plugin<MidiAmp> Base; +template<class Super> +struct Mixin : public Super { + Mixin(double rate, + const char* bundle_path, + const LV2_Feature* const* features, + bool* valid) + : Super(rate, bundle_path, features, valid) + {} +}; /** MIDI-controlled amplifier. */ -class MidiAmp : public Base { +class MidiAmp : public lv2::Plugin<> { public: MidiAmp(double rate, const char* bundle_path, const LV2_Feature* const* features, bool* valid) - : Base(rate, bundle_path, features, valid) + : lv2::Plugin<>(rate, bundle_path, features, valid) , m_map(features, valid) , m_vol(1.0f) { @@ -104,13 +111,12 @@ private: }; /** Plugin library. */ -class MidiAmpLib : public lv2::Lib<MidiAmpLib> +class MidiAmpLib : public lv2::Lib { public: - MidiAmpLib(const char* bundle_path, - const LV2_Feature*const* features) - : lv2::Lib<MidiAmpLib>(bundle_path, features) - , m_amp(MidiAmp::descriptor("http://lv2plug.in/plugins/eg-midiamp")) + MidiAmpLib(const char* bundle_path, const LV2_Feature*const* features) + : lv2::Lib(bundle_path, features) + , m_amp("http://lv2plug.in/plugins/eg-midiamp") {} const LV2_Descriptor* get_plugin(uint32_t index) { @@ -118,13 +124,12 @@ public: } private: - LV2_Descriptor m_amp; + lv2::Descriptor<MidiAmp> m_amp; }; /** Library entry point. */ LV2_SYMBOL_EXPORT const LV2_Lib_Descriptor* -lv2_lib_descriptor(const char* bundle_path, - const LV2_Feature *const * features) +lv2_lib_descriptor(const char* bundle_path, const LV2_Feature*const* features) { return new MidiAmpLib(bundle_path, features); |