DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 6d29d5d83d856ada7aef96400c99bdd567796a2e
parent e44a908375610d7f46b507532b4602c9f89f085a
Author: falkTX <falktx@falktx.com>
Date:   Sun, 19 Sep 2021 11:38:49 +0100

Reduce amount of Plugin pure virtual methods, use runtime warnings

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
M.github/workflows/example-plugins.yml | 2+-
MMakefile.plugins.mk | 1+
Mdistrho/DistrhoPlugin.hpp | 14+++++++-------
Mdistrho/src/DistrhoPlugin.cpp | 38+++++++++++++++++++++++++++++++++-----
Mdistrho/src/DistrhoPluginChecks.h | 5+++--
Mdistrho/src/DistrhoPluginInternal.hpp | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 139 insertions(+), 15 deletions(-)

diff --git a/.github/workflows/example-plugins.yml b/.github/workflows/example-plugins.yml @@ -255,7 +255,7 @@ jobs: - name: Build plugins env: CFLAGS: -g - CXXFLAGS: -g + CXXFLAGS: -g -DDPF_ABORT_ON_ERROR LDFLAGS: -static-libgcc -static-libstdc++ run: | make features diff --git a/Makefile.plugins.mk b/Makefile.plugins.mk @@ -33,6 +33,7 @@ endif BUILD_C_FLAGS += -I. BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl +BUILD_CXX_FLAGS += -Wno-pmf-conversions ifeq ($(HAVE_ALSA),true) BASE_FLAGS += -DHAVE_ALSA diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp @@ -943,7 +943,7 @@ protected: Initialize the parameter @a index.@n This function will be called once, shortly after the plugin is created. */ - virtual void initParameter(uint32_t index, Parameter& parameter) = 0; + virtual void initParameter(uint32_t index, Parameter& parameter); /** Initialize the port group @a groupId.@n @@ -967,7 +967,7 @@ protected: This function will be called once, shortly after the plugin is created.@n Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. */ - virtual void initState(uint32_t index, String& stateKey, String& defaultStateValue) = 0; + virtual void initState(uint32_t index, String& stateKey, String& defaultStateValue); #endif #if DISTRHO_PLUGIN_WANT_STATEFILES @@ -984,7 +984,7 @@ protected: Get the current value of a parameter.@n The host may call this function from any context, including realtime processing. */ - virtual float getParameterValue(uint32_t index) const = 0; + virtual float getParameterValue(uint32_t index) const; /** Change a parameter value.@n @@ -992,7 +992,7 @@ protected: When a parameter is marked as automable, you must ensure no non-realtime operations are performed. @note This function will only be called for parameter inputs. */ - virtual void setParameterValue(uint32_t index, float value) = 0; + virtual void setParameterValue(uint32_t index, float value); #if DISTRHO_PLUGIN_WANT_PROGRAMS /** @@ -1000,7 +1000,7 @@ protected: The host may call this function from any context, including realtime processing.@n Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled. */ - virtual void loadProgram(uint32_t index) = 0; + virtual void loadProgram(uint32_t index); #endif #if DISTRHO_PLUGIN_WANT_FULL_STATE @@ -1010,7 +1010,7 @@ protected: Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_FULL_STATE is enabled. @note The use of this function breaks compatibility with the DSSI format. */ - virtual String getState(const char* key) const = 0; + virtual String getState(const char* key) const; #endif #if DISTRHO_PLUGIN_WANT_STATE @@ -1018,7 +1018,7 @@ protected: Change an internal state @a key to @a value.@n Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. */ - virtual void setState(const char* key, const char* value) = 0; + virtual void setState(const char* key, const char* value); #endif /* -------------------------------------------------------------------------------------------------------- diff --git a/distrho/src/DistrhoPlugin.cpp b/distrho/src/DistrhoPlugin.cpp @@ -56,8 +56,6 @@ Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCou pData->programCount = programCount; pData->programNames = new String[programCount]; } -#else - DISTRHO_SAFE_ASSERT(programCount == 0); #endif #if DISTRHO_PLUGIN_WANT_STATE @@ -67,8 +65,6 @@ Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCou pData->stateKeys = new String[stateCount]; pData->stateDefValues = new String[stateCount]; } -#else - DISTRHO_SAFE_ASSERT(stateCount == 0); #endif } @@ -144,16 +140,48 @@ void Plugin::initAudioPort(bool input, uint32_t index, AudioPort& port) } } +void Plugin::initParameter(uint32_t, Parameter&) {} + void Plugin::initPortGroup(const uint32_t groupId, PortGroup& portGroup) { fillInPredefinedPortGroupData(groupId, portGroup); } +#if DISTRHO_PLUGIN_WANT_PROGRAMS +void Plugin::initProgramName(uint32_t, String&) {} +#endif + +#if DISTRHO_PLUGIN_WANT_STATE +void Plugin::initState(uint32_t, String&, String&) {} +#endif + +#if DISTRHO_PLUGIN_WANT_STATEFILES +bool Plugin::isStateFile(uint32_t index) { return false; } +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * Init */ + +float Plugin::getParameterValue(uint32_t) const { return 0.0f; } +void Plugin::setParameterValue(uint32_t, float) {} + +#if DISTRHO_PLUGIN_WANT_PROGRAMS +void Plugin::loadProgram(uint32_t) {} +#endif + +#if DISTRHO_PLUGIN_WANT_FULL_STATE +String Plugin::getState(const char*) const { return String(); } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE +void Plugin::setState(const char*, const char*) {} +#endif + /* ------------------------------------------------------------------------------------------------------------ * Callbacks (optional) */ void Plugin::bufferSizeChanged(uint32_t) {} -void Plugin::sampleRateChanged(double) {} +void Plugin::sampleRateChanged(double) {} // ----------------------------------------------------------------------------------------------------------- diff --git a/distrho/src/DistrhoPluginChecks.h b/distrho/src/DistrhoPluginChecks.h @@ -87,6 +87,7 @@ #ifndef DISTRHO_PLUGIN_WANT_FULL_STATE # define DISTRHO_PLUGIN_WANT_FULL_STATE 0 +# define DISTRHO_PLUGIN_WANT_FULL_STATE_WAS_NOT_SET #endif #ifndef DISTRHO_PLUGIN_WANT_TIMEPOS @@ -146,8 +147,8 @@ // ----------------------------------------------------------------------- // Enable full state if plugin exports presets -#if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE && ! DISTRHO_PLUGIN_WANT_FULL_STATE -# warning Plugins with programs and state need to implement full state API too +#if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE && defined(DISTRHO_PLUGIN_WANT_FULL_STATE_WAS_NOT_SET) +# warning Plugins with programs and state should implement full state API too # undef DISTRHO_PLUGIN_WANT_FULL_STATE # define DISTRHO_PLUGIN_WANT_FULL_STATE 1 #endif diff --git a/distrho/src/DistrhoPluginInternal.hpp b/distrho/src/DistrhoPluginInternal.hpp @@ -247,6 +247,100 @@ public: DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + /* Verify that virtual functions are overriden if parameters, programs or states are in use. + * This does not work on all compilers, but we use it purely as informational check anyway. */ +#ifdef __GNUC__ +# ifdef DPF_ABORT_ON_ERROR +# define DPF_ABORT abort(); +# else +# define DPF_ABORT +# endif + if (fData->parameterCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::initParameter)) == (void*)&Plugin::initParameter) + { + d_stderr2("DPF warning: Plugins with parameters must implement `initParameter`"); + DPF_ABORT + } + if ((void*)(fPlugin->*(&Plugin::getParameterValue)) == (void*)&Plugin::getParameterValue) + { + d_stderr2("DPF warning: Plugins with parameters must implement `getParameterValue`"); + DPF_ABORT + } + if ((void*)(fPlugin->*(&Plugin::setParameterValue)) == (void*)&Plugin::setParameterValue) + { + d_stderr2("DPF warning: Plugins with parameters must implement `setParameterValue`"); + DPF_ABORT + } + } + +# if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fData->programCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::initProgramName)) == (void*)&Plugin::initProgramName) + { + d_stderr2("DPF warning: Plugins with programs must implement `initProgramName`"); + DPF_ABORT + } + if ((void*)(fPlugin->*(&Plugin::loadProgram)) == (void*)&Plugin::loadProgram) + { + d_stderr2("DPF warning: Plugins with programs must implement `loadProgram`"); + DPF_ABORT + } + } +# else + if (fData->programCount != 0) + { + d_stderr2("DPF warning: Plugins with programs must define `DISTRHO_PLUGIN_WANT_PROGRAMS` to 1"); + DPF_ABORT + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + if (fData->stateCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::initState)) == (void*)&Plugin::initState) + { + d_stderr2("DPF warning: Plugins with state must implement `initState`"); + DPF_ABORT + } + + if ((void*)(fPlugin->*(&Plugin::setState)) == (void*)&Plugin::setState) + { + d_stderr2("DPF warning: Plugins with state must implement `setState`"); + DPF_ABORT + } + } +# else + if (fData->stateCount != 0) + { + d_stderr2("DPF warning: Plugins with state must define `DISTRHO_PLUGIN_WANT_STATE` to 1"); + DPF_ABORT + } +# endif + +# if DISTRHO_PLUGIN_WANT_FULL_STATE + if (fData->stateCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::getState)) == (void*)&Plugin::getState) + { + d_stderr2("DPF warning: Plugins with full state must implement `getState`"); + DPF_ABORT + } + } + else + { + if (fData->stateCount == 0) + { + d_stderr2("DPF warning: Plugins with full state must have at least 1 state"); + DPF_ABORT + } + } +# endif + +# undef DPF_ABORT +#endif + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 { uint32_t j=0;