Browse Source

Add Meters example

pull/2/head
falkTX 8 years ago
parent
commit
5794133242
6 changed files with 598 additions and 0 deletions
  1. +2
    -0
      Makefile
  2. +38
    -0
      plugins/Meters/DistrhoPluginInfo.h
  3. +257
    -0
      plugins/Meters/ExamplePluginMeters.cpp
  4. +258
    -0
      plugins/Meters/ExampleUIMeters.cpp
  5. +35
    -0
      plugins/Meters/Makefile
  6. +8
    -0
      plugins/Meters/README.md

+ 2
- 0
Makefile View File

@@ -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



+ 38
- 0
plugins/Meters/DistrhoPluginInfo.h View File

@@ -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

+ 257
- 0
plugins/Meters/ExamplePluginMeters.cpp View File

@@ -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

+ 258
- 0
plugins/Meters/ExampleUIMeters.cpp View File

@@ -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

+ 35
- 0
plugins/Meters/Makefile View File

@@ -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

# --------------------------------------------------------------

+ 8
- 0
plugins/Meters/README.md View File

@@ -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/>

Loading…
Cancel
Save