@@ -14,6 +14,7 @@ libs: | |||
plugins: libs | |||
$(MAKE) all -C plugins/openav-ducka | |||
$(MAKE) all -C plugins/openav-roomy | |||
$(MAKE) all -C plugins/Meters | |||
$(MAKE) all -C plugins/Parameters | |||
$(MAKE) all -C plugins/States | |||
@@ -30,6 +31,7 @@ clean: | |||
$(MAKE) clean -C dpf/utils/lv2-ttl-generator | |||
$(MAKE) clean -C plugins/openav-ducka | |||
$(MAKE) clean -C plugins/openav-roomy | |||
$(MAKE) clean -C plugins/Meters | |||
$(MAKE) clean -C plugins/Parameters | |||
$(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/> |