From 651a1d285eeccdc39e33103e8e0b49d98d0175ba Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 1 Sep 2016 01:29:20 -0400 Subject: Use virtual plugin methods and simplify template --- lv2/lv2plug.in/ns/lv2core/Lib.hpp | 17 ++--- lv2/lv2plug.in/ns/lv2core/Plugin.hpp | 132 +++++++++++++++++------------------ 2 files changed, 70 insertions(+), 79 deletions(-) (limited to 'lv2') 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 + Copyright 2015-2016 David Robillard 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 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(handle); + delete reinterpret_cast(handle); } static const LV2_Descriptor* s_get_plugin(LV2_Lib_Handle handle, uint32_t index) { - return reinterpret_cast(handle)->get_plugin(index); + return reinterpret_cast(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 { // ... }; - - 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 PluginBase -{ +class PluginBase { public: /** Instantiate the plugin. @@ -79,12 +66,20 @@ 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. @@ -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 +class NoExtension : public Super {}; - @code - static const LV2_Descriptor a = lv2::descriptor("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 class First=NoExtension, + template class... Rest> +struct Plugin : public First< Plugin > { + Plugin(double r, const char* b, const LV2_Feature* const* f, bool* v) + : First< Plugin >(r, b, f, v) + {} +}; + +template<> +struct Plugin : 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("http://example.org/amp"); + @endcode +*/ +template +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(instance)->connect_port(port, buf); + reinterpret_cast(instance)->connect_port(port, buf); } static void s_activate(LV2_Handle instance) { - reinterpret_cast(instance)->activate(); + reinterpret_cast(instance)->activate(); } static void s_run(LV2_Handle instance, uint32_t sample_count) { - reinterpret_cast(instance)->run(sample_count); + reinterpret_cast(instance)->run(sample_count); } static void s_deactivate(LV2_Handle instance) { - reinterpret_cast(instance)->deactivate(); + reinterpret_cast(instance)->deactivate(); } static void s_cleanup(LV2_Handle instance) { - delete reinterpret_cast(instance); + delete reinterpret_cast(instance); } }; -template class First=PluginBase, template class... Rest> -struct Plugin : public First< Plugin > { - Plugin(double rate, - const char* bundle_path, - const LV2_Feature* const* features, - bool* valid) - : First< Plugin >(rate, bundle_path, features, valid) - {} - -}; - -template class First> -struct Plugin : public First< PluginBase > { - Plugin(double rate, - const char* bundle_path, - const LV2_Feature* const* features, - bool* valid) - : First< PluginBase >(rate, bundle_path, features, valid) - {} - -}; - } /* namespace lv2 */ #endif /* LV2_PLUGIN_HPP */ -- cgit v1.2.1