| @@ -14,6 +14,7 @@ libs: | |||||
| plugins: libs | plugins: libs | ||||
| $(MAKE) all -C plugins/openav-ducka | $(MAKE) all -C plugins/openav-ducka | ||||
| $(MAKE) all -C plugins/openav-roomy | $(MAKE) all -C plugins/openav-roomy | ||||
| $(MAKE) all -C plugins/Meters | |||||
| $(MAKE) all -C plugins/Parameters | $(MAKE) all -C plugins/Parameters | ||||
| $(MAKE) all -C plugins/States | $(MAKE) all -C plugins/States | ||||
| @@ -30,6 +31,7 @@ clean: | |||||
| $(MAKE) clean -C dpf/utils/lv2-ttl-generator | $(MAKE) clean -C dpf/utils/lv2-ttl-generator | ||||
| $(MAKE) clean -C plugins/openav-ducka | $(MAKE) clean -C plugins/openav-ducka | ||||
| $(MAKE) clean -C plugins/openav-roomy | $(MAKE) clean -C plugins/openav-roomy | ||||
| $(MAKE) clean -C plugins/Meters | |||||
| $(MAKE) clean -C plugins/Parameters | $(MAKE) clean -C plugins/Parameters | ||||
| $(MAKE) clean -C plugins/States | $(MAKE) clean -C plugins/States | ||||
| @@ -0,0 +1,38 @@ | |||||
| /* | |||||
| * DISTRHO Plugin Framework (DPF) | |||||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||||
| * permission notice appear in all copies. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
| * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
| * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
| */ | |||||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||||
| #define DISTRHO_PLUGIN_NAME "Meters" | |||||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||||
| #define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | |||||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 0 | |||||
| #define DISTRHO_PLUGIN_WANT_STATE 1 | |||||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/Meters" | |||||
| #define DISTRHO_UI_USE_NANOVG 1 | |||||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||||
| @@ -0,0 +1,257 @@ | |||||
| /* | |||||
| * DISTRHO Plugin Framework (DPF) | |||||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||||
| * permission notice appear in all copies. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
| * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
| * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
| */ | |||||
| #include "DistrhoPlugin.hpp" | |||||
| START_NAMESPACE_DISTRHO | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| /** | |||||
| Plugin to demonstrate parameter outputs using meters. | |||||
| */ | |||||
| class ExamplePluginMeters : public Plugin | |||||
| { | |||||
| public: | |||||
| ExamplePluginMeters() | |||||
| : Plugin(3, 0, 0), // 3 parameters, 0 programs, 0 states | |||||
| fColor(0.0f), | |||||
| fOutLeft(0.0f), | |||||
| fOutRight(0.0f), | |||||
| fNeedsReset(true) | |||||
| { | |||||
| } | |||||
| protected: | |||||
| /* -------------------------------------------------------------------------------------------------------- | |||||
| * Information */ | |||||
| /** | |||||
| Get the plugin label. | |||||
| A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers. | |||||
| */ | |||||
| const char* d_getLabel() const override | |||||
| { | |||||
| return "meters"; | |||||
| } | |||||
| /** | |||||
| Get the plugin author/maker. | |||||
| */ | |||||
| const char* d_getMaker() const override | |||||
| { | |||||
| return "DISTRHO"; | |||||
| } | |||||
| /** | |||||
| Get the plugin license name (a single line of text). | |||||
| */ | |||||
| const char* d_getLicense() const override | |||||
| { | |||||
| return "ISC"; | |||||
| } | |||||
| /** | |||||
| Get the plugin version, in hexadecimal. | |||||
| TODO format to be defined | |||||
| */ | |||||
| uint32_t d_getVersion() const override | |||||
| { | |||||
| return 0x1000; | |||||
| } | |||||
| /** | |||||
| Get the plugin unique Id. | |||||
| This value is used by LADSPA, DSSI and VST plugin formats. | |||||
| */ | |||||
| int64_t d_getUniqueId() const override | |||||
| { | |||||
| return d_cconst('d', 'M', 't', 'r'); | |||||
| } | |||||
| /* -------------------------------------------------------------------------------------------------------- | |||||
| * Init */ | |||||
| /** | |||||
| Initialize the parameter @a index. | |||||
| This function will be called once, shortly after the plugin is created. | |||||
| */ | |||||
| void d_initParameter(uint32_t index, Parameter& parameter) override | |||||
| { | |||||
| /** | |||||
| All parameters in this plugin have the same ranges. | |||||
| */ | |||||
| parameter.ranges.min = 0.0f; | |||||
| parameter.ranges.max = 1.0f; | |||||
| parameter.ranges.def = 0.0f; | |||||
| /** | |||||
| Set parameter data. | |||||
| */ | |||||
| switch (index) | |||||
| { | |||||
| case 0: | |||||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||||
| parameter.name = "color"; | |||||
| parameter.symbol = "color"; | |||||
| break; | |||||
| case 1: | |||||
| parameter.hints = kParameterIsAutomable|kParameterIsOutput; | |||||
| parameter.name = "out-left"; | |||||
| parameter.symbol = "out_left"; | |||||
| break; | |||||
| case 2: | |||||
| parameter.hints = kParameterIsAutomable|kParameterIsOutput; | |||||
| parameter.name = "out-right"; | |||||
| parameter.symbol = "out_right"; | |||||
| break; | |||||
| } | |||||
| } | |||||
| /** | |||||
| Set a state key and default value. | |||||
| This function will be called once, shortly after the plugin is created. | |||||
| */ | |||||
| void d_initState(uint32_t, d_string&, d_string&) override | |||||
| { | |||||
| // we are using states but don't want them saved in the host | |||||
| } | |||||
| /* -------------------------------------------------------------------------------------------------------- | |||||
| * Internal data */ | |||||
| /** | |||||
| Get the current value of a parameter. | |||||
| */ | |||||
| float d_getParameterValue(uint32_t index) const override | |||||
| { | |||||
| switch (index) | |||||
| { | |||||
| case 0: return fColor; | |||||
| case 1: return fOutLeft; | |||||
| case 2: return fOutRight; | |||||
| } | |||||
| return 0.0f; | |||||
| } | |||||
| /** | |||||
| Change a parameter value. | |||||
| */ | |||||
| void d_setParameterValue(uint32_t index, float value) override | |||||
| { | |||||
| // this is only called for input paramters, and we only have one of those. | |||||
| if (index != 0) return; | |||||
| fColor = value; | |||||
| } | |||||
| /** | |||||
| Change an internal state. | |||||
| */ | |||||
| void d_setState(const char* key, const char*) override | |||||
| { | |||||
| if (std::strcmp(key, "reset") != 0) | |||||
| return; | |||||
| fNeedsReset = true; | |||||
| } | |||||
| /* -------------------------------------------------------------------------------------------------------- | |||||
| * Process */ | |||||
| /** | |||||
| Run/process function for plugins without MIDI input. | |||||
| */ | |||||
| void d_run(const float** inputs, float** outputs, uint32_t frames) override | |||||
| { | |||||
| float tmp; | |||||
| float tmpLeft = 0.0f; | |||||
| float tmpRight = 0.0f; | |||||
| for (uint32_t i=0; i<frames; ++i) | |||||
| { | |||||
| // left | |||||
| tmp = std::abs(outputs[0][i]); | |||||
| if (tmp > tmpLeft) | |||||
| tmpLeft = tmp; | |||||
| // right | |||||
| tmp = std::abs(outputs[1][i]); | |||||
| if (tmp > tmpRight) | |||||
| tmpRight = tmp; | |||||
| } | |||||
| if (tmpLeft > 1.0f) | |||||
| tmpLeft = 1.0f; | |||||
| if (tmpRight > 1.0f) | |||||
| tmpRight = 1.0f; | |||||
| if (fNeedsReset) | |||||
| { | |||||
| fOutLeft = tmpLeft; | |||||
| fOutRight = tmpRight; | |||||
| fNeedsReset = false; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (tmpLeft > fOutLeft) | |||||
| fOutLeft = tmpLeft; | |||||
| if (tmpRight > fOutRight) | |||||
| fOutRight = tmpRight; | |||||
| } | |||||
| // copy inputs over outputs if needed | |||||
| if (outputs[0] != inputs[0]) | |||||
| std::memcpy(outputs[0], inputs[0], sizeof(float)*frames); | |||||
| if (outputs[1] != inputs[1]) | |||||
| std::memcpy(outputs[1], inputs[1], sizeof(float)*frames); | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------- | |||||
| private: | |||||
| /** | |||||
| Parameters. | |||||
| */ | |||||
| float fColor, fOutLeft, fOutRight; | |||||
| /** | |||||
| Boolean used to reset meter values. | |||||
| The UI will send a "reset" message which sets this as true. | |||||
| */ | |||||
| volatile bool fNeedsReset; | |||||
| /** | |||||
| Set our plugin class as non-copyable and add a leak detector just in case. | |||||
| */ | |||||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExamplePluginMeters) | |||||
| }; | |||||
| /* ------------------------------------------------------------------------------------------------------------ | |||||
| * Plugin entry point, called by DPF to create a new plugin instance. */ | |||||
| Plugin* createPlugin() | |||||
| { | |||||
| return new ExamplePluginMeters(); | |||||
| } | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| END_NAMESPACE_DISTRHO | |||||
| @@ -0,0 +1,258 @@ | |||||
| /* | |||||
| * DISTRHO Plugin Framework (DPF) | |||||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||||
| * permission notice appear in all copies. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
| * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
| * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
| */ | |||||
| #include "DistrhoUI.hpp" | |||||
| START_NAMESPACE_DISTRHO | |||||
| /** | |||||
| We need the Color class from DGL. | |||||
| */ | |||||
| using DGL::Color; | |||||
| /** | |||||
| Smooth meters a bit. | |||||
| */ | |||||
| static const float kSmoothMultiplier = 3.0f; | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| class ExampleUIMeters : public UI | |||||
| { | |||||
| public: | |||||
| ExampleUIMeters() | |||||
| : UI(), | |||||
| // default color is green | |||||
| fColor(93, 231, 61), | |||||
| // which is value 0 | |||||
| fColorValue(0), | |||||
| // init meter values to 0 | |||||
| fOutLeft(0.0f), | |||||
| fOutRight(0.0f) | |||||
| { | |||||
| setSize(128, 512); | |||||
| } | |||||
| protected: | |||||
| /* -------------------------------------------------------------------------------------------------------- | |||||
| * DSP/Plugin Callbacks */ | |||||
| /** | |||||
| A parameter has changed on the plugin side. | |||||
| This is called by the host to inform the UI about parameter changes. | |||||
| */ | |||||
| void d_parameterChanged(uint32_t index, float value) override | |||||
| { | |||||
| switch (index) | |||||
| { | |||||
| case 0: // color | |||||
| updateColor(value); | |||||
| break; | |||||
| case 1: // out-left | |||||
| value = (fOutLeft * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f); | |||||
| /**/ if (value < 0.001f) value = 0.0f; | |||||
| else if (value > 0.999f) value = 1.0f; | |||||
| if (fOutLeft != value) | |||||
| { | |||||
| fOutLeft = value; | |||||
| repaint(); | |||||
| } | |||||
| break; | |||||
| case 2: // out-right | |||||
| value = (fOutRight * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f); | |||||
| /**/ if (value < 0.001f) value = 0.0f; | |||||
| else if (value > 0.999f) value = 1.0f; | |||||
| if (fOutRight != value) | |||||
| { | |||||
| fOutRight = value; | |||||
| repaint(); | |||||
| } | |||||
| break; | |||||
| } | |||||
| // trigger repaint | |||||
| repaint(); | |||||
| } | |||||
| /** | |||||
| A state has changed on the plugin side. | |||||
| This is called by the host to inform the UI about state changes. | |||||
| */ | |||||
| void d_stateChanged(const char*, const char*) | |||||
| { | |||||
| // nothing here | |||||
| } | |||||
| /* -------------------------------------------------------------------------------------------------------- | |||||
| * Widget Callbacks */ | |||||
| /** | |||||
| The NanoVG drawing function. | |||||
| */ | |||||
| void onNanoDisplay() override | |||||
| { | |||||
| static const Color kColorBlack(0, 0, 0); | |||||
| static const Color kColorRed(255, 0, 0); | |||||
| static const Color kColorYellow(255, 255, 0); | |||||
| // get meter values | |||||
| const float outLeft(fOutLeft); | |||||
| const float outRight(fOutRight); | |||||
| // tell DSP side to reset meter values | |||||
| d_setState("reset", ""); | |||||
| // useful vars | |||||
| const float halfWidth = static_cast<float>(getWidth())/2; | |||||
| const float redYellowHeight = static_cast<float>(getHeight())*0.2f; | |||||
| const float yellowBaseHeight = static_cast<float>(getHeight())*0.4f; | |||||
| const float baseBaseHeight = static_cast<float>(getHeight())*0.6f; | |||||
| // create gradients | |||||
| Paint fGradient1 = linearGradient(0.0f, 0.0f, 0.0f, redYellowHeight, kColorRed, kColorYellow); | |||||
| Paint fGradient2 = linearGradient(0.0f, redYellowHeight, 0.0f, yellowBaseHeight, kColorYellow, fColor); | |||||
| // paint left meter | |||||
| beginPath(); | |||||
| rect(0.0f, 0.0f, halfWidth-1.0f, redYellowHeight); | |||||
| fillPaint(fGradient1); | |||||
| fill(); | |||||
| closePath(); | |||||
| beginPath(); | |||||
| rect(0.0f, redYellowHeight-0.5f, halfWidth-1.0f, yellowBaseHeight); | |||||
| fillPaint(fGradient2); | |||||
| fill(); | |||||
| closePath(); | |||||
| beginPath(); | |||||
| rect(0.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-1.0f, baseBaseHeight); | |||||
| fillColor(fColor); | |||||
| fill(); | |||||
| closePath(); | |||||
| // paint left black matching output level | |||||
| beginPath(); | |||||
| rect(0.0f, 0.0f, halfWidth-1.0f, (1.0f-outLeft)*getHeight()); | |||||
| fillColor(kColorBlack); | |||||
| fill(); | |||||
| closePath(); | |||||
| // paint right meter | |||||
| beginPath(); | |||||
| rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, redYellowHeight); | |||||
| fillPaint(fGradient1); | |||||
| fill(); | |||||
| closePath(); | |||||
| beginPath(); | |||||
| rect(halfWidth+1.0f, redYellowHeight-0.5f, halfWidth-2.0f, yellowBaseHeight); | |||||
| fillPaint(fGradient2); | |||||
| fill(); | |||||
| closePath(); | |||||
| beginPath(); | |||||
| rect(halfWidth+1.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-2.0f, baseBaseHeight); | |||||
| fillColor(fColor); | |||||
| fill(); | |||||
| closePath(); | |||||
| // paint right black matching output level | |||||
| beginPath(); | |||||
| rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, (1.0f-outRight)*getHeight()); | |||||
| fillColor(kColorBlack); | |||||
| fill(); | |||||
| closePath(); | |||||
| } | |||||
| /** | |||||
| Mouse press event. | |||||
| This UI will change color when clicked. | |||||
| */ | |||||
| bool onMouse(const MouseEvent& ev) override | |||||
| { | |||||
| // Test for left-clicked + pressed first. | |||||
| if (ev.button != 1 || ! ev.press) | |||||
| return false; | |||||
| const int newColor(fColorValue == 0 ? 1 : 0); | |||||
| updateColor(newColor); | |||||
| d_setParameterValue(0, newColor); | |||||
| return true; | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------- | |||||
| private: | |||||
| /** | |||||
| Color and its matching parameter value. | |||||
| */ | |||||
| Color fColor; | |||||
| int fColorValue; | |||||
| /** | |||||
| Meter values. | |||||
| These are the parameter outputs from the DSP side. | |||||
| */ | |||||
| float fOutLeft, fOutRight; | |||||
| /** | |||||
| Update color if needed. | |||||
| */ | |||||
| void updateColor(const int color) | |||||
| { | |||||
| if (fColorValue == color) | |||||
| return; | |||||
| fColorValue = color; | |||||
| switch (color) | |||||
| { | |||||
| case 0: // green | |||||
| fColor = Color(93, 231, 61); | |||||
| break; | |||||
| case 1: // blue | |||||
| fColor = Color(82, 238, 248); | |||||
| break; | |||||
| } | |||||
| repaint(); | |||||
| } | |||||
| /** | |||||
| Set our UI class as non-copyable and add a leak detector just in case. | |||||
| */ | |||||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIMeters) | |||||
| }; | |||||
| /* ------------------------------------------------------------------------------------------------------------ | |||||
| * UI entry point, called by DPF to create a new UI instance. */ | |||||
| UI* createUI() | |||||
| { | |||||
| return new ExampleUIMeters(); | |||||
| } | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| END_NAMESPACE_DISTRHO | |||||
| @@ -0,0 +1,35 @@ | |||||
| #!/usr/bin/make -f | |||||
| # Makefile for DISTRHO Plugins # | |||||
| # ---------------------------- # | |||||
| # Created by falkTX | |||||
| # | |||||
| # -------------------------------------------------------------- | |||||
| # Project name, used for binaries | |||||
| NAME = d_meters | |||||
| # -------------------------------------------------------------- | |||||
| # Files to build | |||||
| OBJS_DSP = \ | |||||
| ExamplePluginMeters.cpp.o | |||||
| OBJS_UI = \ | |||||
| ExampleUIMeters.cpp.o | |||||
| # -------------------------------------------------------------- | |||||
| # Do some magic | |||||
| include ../Makefile.mk | |||||
| # -------------------------------------------------------------- | |||||
| # Enable all possible plugin types | |||||
| ifeq ($(LINUX),true) | |||||
| all: jack dssi lv2_sep vst | |||||
| else | |||||
| all: dssi lv2_sep vst | |||||
| endif | |||||
| # -------------------------------------------------------------- | |||||
| @@ -0,0 +1,8 @@ | |||||
| # Meters example | |||||
| This example will show how parameter outputs can be used for UI meters in DPF.<br/> | |||||
| The plugin will inspect the host audio buffer but it won't change it in any way.<br/> | |||||
| In this example the UI will display a simple meter based on the plugin's parameter outputs.<br/> | |||||
| In order to make drawing easier the UI uses NanoVG instead of raw OpenGL.<br/> | |||||
| Please see the Parameters and States examples before studying this one.<br/> | |||||