diff options
| author | David Robillard <d@drobilla.net> | 2016-09-01 01:29:20 -0400 | 
|---|---|---|
| committer | David Robillard <d@drobilla.net> | 2017-02-26 14:59:00 +0100 | 
| commit | 651a1d285eeccdc39e33103e8e0b49d98d0175ba (patch) | |
| tree | ae8432c32ee25e63ea4677b0621aecfa89bee5a2 | |
| parent | 6b5eedca8ed4c761de2202a5d4fe7711af7be198 (diff) | |
| download | lv2-651a1d285eeccdc39e33103e8e0b49d98d0175ba.tar.xz | |
Use virtual plugin methods and simplify templatec++
| -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);  |