Browse Source

Add plugin-side parameters to cairoui example

Signed-off-by: falkTX <falktx@falktx.com>
pull/443/head
falkTX 1 year ago
parent
commit
77bd69efec
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
8 changed files with 336 additions and 185 deletions
  1. +1
    -2
      examples/CairoUI/CMakeLists.txt
  2. +113
    -22
      examples/CairoUI/CairoExamplePlugin.cpp
  3. +67
    -25
      examples/CairoUI/CairoExampleUI.cpp
  4. +0
    -99
      examples/CairoUI/DemoWidgetBanner.cpp
  5. +73
    -6
      examples/CairoUI/DemoWidgetBanner.hpp
  6. +51
    -21
      examples/CairoUI/DemoWidgetClickable.hpp
  7. +30
    -4
      examples/CairoUI/DistrhoPluginInfo.h
  8. +1
    -6
      examples/CairoUI/Makefile

+ 1
- 2
examples/CairoUI/CMakeLists.txt View File

@@ -2,13 +2,12 @@
# ------------------------------ #

dpf_add_plugin(d_cairoui
TARGETS jack dssi lv2 vst2
TARGETS clap dssi jack lv2_sep vst2 vst3
UI_TYPE cairo
FILES_DSP
CairoExamplePlugin.cpp
FILES_UI
Artwork.cpp
DemoWidgetBanner.cpp
CairoExampleUI.cpp)

target_include_directories(


+ 113
- 22
examples/CairoUI/CairoExamplePlugin.cpp View File

@@ -23,33 +23,62 @@ START_NAMESPACE_DISTRHO

class CairoExamplePlugin : public Plugin
{
float fParameters[kParameterCount];

public:
CairoExamplePlugin()
: Plugin(0, 0, 0)
: Plugin(kParameterCount, 0, 0)
{
std::memset(fParameters, 0, sizeof(fParameters));
}

const char* getLabel() const
/**
Get the plugin label.@n
This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
*/
const char* getLabel() const override
{
return "cairo_ui";
}

/**
Get an extensive comment/description about the plugin.
*/
const char* getDescription() const override
{
return "Cairo DPF Example";
}

const char* getMaker() const
/**
Get the plugin author/maker.
*/
const char* getMaker() const override
{
return "Jean Pierre Cimalando";
return "DISTRHO";
}

const char* getLicense() const
/**
Get the plugin license (a single line of text or a URL).@n
For commercial plugins this should return some short copyright information.
*/
const char* getLicense() const override
{
return "ISC";
}

uint32_t getVersion() const
/**
Get the plugin version, in hexadecimal.
*/
uint32_t getVersion() const override
{
return d_version(1, 0, 0);
}

int64_t getUniqueId() const
/**
Get the plugin unique Id.@n
This value is used by LADSPA, DSSI, VST2 and VST3 plugin formats.
*/
int64_t getUniqueId() const override
{
return d_cconst('d', 'C', 'a', 'i');
}
@@ -58,7 +87,7 @@ public:
Initialize the audio port @a index.@n
This function will be called once, shortly after the plugin is created.
*/
void initAudioPort(bool input, uint32_t index, AudioPort& port) override
void initAudioPort(const bool input, const uint32_t index, AudioPort& port) override
{
// treat meter audio ports as stereo
port.groupId = kPortGroupMono;
@@ -67,29 +96,91 @@ public:
Plugin::initAudioPort(input, index, port);
}

void initParameter(uint32_t index, Parameter& parameter)
/**
Initialize the parameter @a index.@n
This function will be called once, shortly after the plugin is created.
*/
void initParameter(const uint32_t index, Parameter& parameter) override
{
// unused
(void)index;
(void)parameter;
/**
All parameters in this plugin have the same ranges.
*/
switch (index)
{
case kParameterKnob:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Knob";
parameter.symbol = "knob";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 0.0f;
break;
case kParameterTriState:
parameter.hints = kParameterIsAutomatable|kParameterIsInteger;
parameter.name = "Color";
parameter.symbol = "color";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 0.0f;
parameter.enumValues.count = 3;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const values = new ParameterEnumerationValue[3];
parameter.enumValues.values = values;
values[0].label = "Red";
values[0].value = 0;
values[1].label = "Green";
values[1].value = 1;
values[2].label = "Blue";
values[2].value = 2;
}
break;
case kParameterButton:
parameter.hints = kParameterIsAutomatable|kParameterIsBoolean;
parameter.name = "Button";
parameter.symbol = "button";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 0.0f;
parameter.enumValues.count = 2;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const values = new ParameterEnumerationValue[2];
parameter.enumValues.values = values;
values[0].label = "Off";
values[0].value = 0;
values[1].label = "On";
values[1].value = 1;
}
break;
}
}

float getParameterValue(uint32_t index) const
/**
Get the current value of a parameter.@n
The host may call this function from any context, including realtime processing.
*/
float getParameterValue(const uint32_t index) const override
{
return 0;

// unused
(void)index;
return fParameters[index];
}

void setParameterValue(uint32_t index, float value)
/**
Change a parameter value.@n
The host may call this function from any context, including realtime processing.@n
When a parameter is marked as automatable, you must ensure no non-realtime operations are performed.
@note This function will only be called for parameter inputs.
*/
void setParameterValue(const uint32_t index, const float value) override
{
// unused
(void)index;
(void)value;
fParameters[index] = value;
}

void run(const float** inputs, float** outputs, uint32_t frames)
/**
Run/process function for plugins without MIDI input.
@note Some parameters might be null if there are no audio inputs or outputs.
*/
void run(const float** const inputs, float** const outputs, const uint32_t frames) override
{
/**
This plugin does nothing, it just demonstrates cairo UI usage.


+ 67
- 25
examples/CairoUI/CairoExampleUI.cpp View File

@@ -23,42 +23,56 @@

START_NAMESPACE_DISTRHO

/**
We need a few classes from DGL.
*/
// We need a few classes from DGL.
using DGL_NAMESPACE::CairoGraphicsContext;
using DGL_NAMESPACE::CairoImage;
using DGL_NAMESPACE::CairoImageButton;
using DGL_NAMESPACE::CairoImageKnob;
using DGL_NAMESPACE::CairoImageSwitch;

// And from ourselves
using DGL_NAMESPACE::DemoWidgetBanner;

class CairoExampleUI : public UI
class CairoExampleUI : public UI,
public CairoImageKnob::Callback,
public CairoImageSwitch::Callback,
public DemoWidgetClickable::Callback
{
ScopedPointer<CairoImageKnob> fKnob;
ScopedPointer<CairoImageSwitch> fButton;
ScopedPointer<DemoWidgetBanner> fWidgetBanner;
ScopedPointer<DemoWidgetClickable> fWidgetClickable;

public:
CairoExampleUI()
: UI(200, 200)
{
fWidgetClickable = new DemoWidgetClickable(this);
fWidgetClickable->setSize(50, 50);
fWidgetClickable->setAbsolutePos(100, 100);
CairoImage knobSkin;
knobSkin.loadFromPNG(Artwork::knobData, Artwork::knobDataSize);

fWidgetBanner = new DemoWidgetBanner(this);
fWidgetBanner->setSize(180, 80);
fWidgetBanner->setAbsolutePos(10, 10);
fWidgetBanner->setSize(180, 80);

CairoImage knobSkin;
knobSkin.loadFromPNG(Artwork::knobData, Artwork::knobDataSize);
fWidgetClickable = new DemoWidgetClickable(this);
fWidgetClickable->setAbsolutePos(100, 100);
fWidgetClickable->setSize(50, 50);
fWidgetClickable->setCallback(this);
fWidgetClickable->setId(kParameterTriState);

fKnob = new CairoImageKnob(this, knobSkin);
fKnob->setSize(80, 80);
fKnob->setAbsolutePos(10, 100);
fKnob->setSize(80, 80);
fKnob->setCallback(this);
fKnob->setId(kParameterKnob);

CairoImage buttonOn, buttonOff;
buttonOn.loadFromPNG(Artwork::buttonOnData, Artwork::buttonOnDataSize);
buttonOff.loadFromPNG(Artwork::buttonOffData, Artwork::buttonOffDataSize);

fButton = new CairoImageButton(this, buttonOff, buttonOn);
fButton->setSize(60, 35);
fButton = new CairoImageSwitch(this, buttonOff, buttonOn);
fButton->setAbsolutePos(100, 160);
fButton->setSize(60, 35);
fButton->setCallback(this);
fButton->setId(kParameterButton);

#if 0
// we can use this if/when our resources are scalable, for now they are PNGs
@@ -67,7 +81,7 @@ public:
setSize(200 * scaleFactor, 200 * scaleFactor);
#else
// without scalable resources, let DPF handle the scaling internally
setGeometryConstraints(200, 200, true, true);
setGeometryConstraints(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT, true, true);
#endif
}

@@ -101,18 +115,46 @@ protected:
}
#endif

void parameterChanged(uint32_t index, float value) override
void parameterChanged(const uint32_t index, const float value) override
{
// unused
(void)index;
(void)value;
switch (index)
{
case kParameterKnob:
fKnob->setValue(value);
break;
case kParameterTriState:
fWidgetClickable->setColorId(static_cast<int>(value + 0.5f));
break;
case kParameterButton:
fButton->setDown(value > 0.5f);
break;
}
}

private:
ScopedPointer<DemoWidgetClickable> fWidgetClickable;
ScopedPointer<DemoWidgetBanner> fWidgetBanner;
ScopedPointer<CairoImageKnob> fKnob;
ScopedPointer<CairoImageButton> fButton;
void demoWidgetClicked(DemoWidgetClickable*, const uint8_t colorId) override
{
setParameterValue(kParameterTriState, colorId);
}

void imageKnobDragStarted(CairoImageKnob*) override
{
editParameter(kParameterKnob, true);
}

void imageKnobDragFinished(CairoImageKnob*) override
{
editParameter(kParameterKnob, false);
}

void imageKnobValueChanged(CairoImageKnob*, const float value) override
{
setParameterValue(kParameterKnob, value);
}

void imageSwitchClicked(CairoImageSwitch*, bool down) override
{
setParameterValue(kParameterButton, down ? 1.f : 0.f);
}
};

UI* createUI()


+ 0
- 99
examples/CairoUI/DemoWidgetBanner.cpp View File

@@ -1,99 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2019-2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
*
* 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 "DemoWidgetBanner.hpp"

START_NAMESPACE_DGL

// -----------------------------------------------------------------------

static const char* banner =
" "
" * * * * * "
" ** ** * * * * "
" * * * * * * * "
" * * * **** *** * **** * * ** **** * *** "
" * * * * ** * * * * * * ** * "
" * * ***** * * ****** * * * * * * * "
" * * * * * * * * * * * * * * "
" * * * ** * ** * * * * * * * * * * "
" * * *** * *** * **** ** ** ***** ** * * "
" "
" "
" "
" ***** **** ***** "
" * * * * * "
" * * * * * "
" * * * * * "
" * * **** **** "
" * * * * "
" * * * * "
" * * * * "
" ***** * * "
" ";

enum
{
rows = 23,
columns = 72,
};

DemoWidgetBanner::DemoWidgetBanner(SubWidget* parent)
: CairoSubWidget(parent) {}

DemoWidgetBanner::DemoWidgetBanner(TopLevelWidget* parent)
: CairoSubWidget(parent) {}

void DemoWidgetBanner::onCairoDisplay(const CairoGraphicsContext& context)
{
cairo_t* cr = context.handle;

Size<uint> sz = getSize();
int w = sz.getWidth();
int h = sz.getHeight();

double diameter = (double)w / columns;
double radius = 0.5 * diameter;
double xoff = 0;
double yoff = 0.5 * (h - rows * diameter);
for (int r = 0; r < rows; ++r)
{
for (int c = 0; c < columns; ++c)
{
double cx = xoff + radius + c * diameter;
double cy = yoff + radius + r * diameter;

char ch = banner[c + r * columns];
if (ch != ' ')
cairo_set_source_rgb(cr, 0.5, 0.9, 0.2);
else
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);

cairo_save(cr);
cairo_translate(cr, cx, cy);
cairo_scale(cr, radius, radius);
cairo_arc(cr, 0.0, 0.0, 1.0, 0.0, 2 * M_PI);
cairo_restore(cr);

cairo_fill(cr);
}
}
}

// -----------------------------------------------------------------------

END_NAMESPACE_DGL

+ 73
- 6
examples/CairoUI/DemoWidgetBanner.hpp View File

@@ -1,7 +1,7 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2019-2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
* Copyright (C) 2012-2023 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
@@ -23,17 +23,84 @@ START_NAMESPACE_DGL

// -----------------------------------------------------------------------

static constexpr const char banner[] =
" "
" * * * * * "
" ** ** * * * * "
" * * * * * * * "
" * * * **** *** * **** * * ** **** * *** "
" * * * * ** * * * * * * ** * "
" * * ***** * * ****** * * * * * * * "
" * * * * * * * * * * * * * * "
" * * * ** * ** * * * * * * * * * * "
" * * *** * *** * **** ** ** ***** ** * * "
" "
" "
" "
" ***** **** ***** "
" * * * * * "
" * * * * * "
" * * * * * "
" * * **** **** "
" * * * * "
" * * * * "
" * * * * "
" ***** * * "
" ";

enum {
rows = 23,
columns = 72,
};

class DemoWidgetBanner : public CairoSubWidget
{
public:
explicit DemoWidgetBanner(SubWidget* parent);
explicit DemoWidgetBanner(TopLevelWidget* parent);
explicit DemoWidgetBanner(SubWidget* const parent)
: CairoSubWidget(parent) {}

explicit DemoWidgetBanner(TopLevelWidget* const parent)
: CairoSubWidget(parent) {}

protected:
void onCairoDisplay(const CairoGraphicsContext& context) override;
void onCairoDisplay(const CairoGraphicsContext& context) override
{
cairo_t* const cr = context.handle;

Size<uint> sz = getSize();
int w = sz.getWidth();
int h = sz.getHeight();

const double diameter = (double)w / columns;
const double radius = 0.5 * diameter;
const double xoff = 0;
const double yoff = 0.5 * (h - rows * diameter);

for (int r = 0; r < rows; ++r)
{
for (int c = 0; c < columns; ++c)
{
double cx = xoff + radius + c * diameter;
double cy = yoff + radius + r * diameter;

char ch = banner[c + r * columns];
if (ch != ' ')
cairo_set_source_rgb(cr, 0.5, 0.9, 0.2);
else
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);

cairo_save(cr);
cairo_translate(cr, cx, cy);
cairo_scale(cr, radius, radius);
cairo_arc(cr, 0.0, 0.0, 1.0, 0.0, 2 * M_PI);
cairo_restore(cr);

cairo_fill(cr);
}
}
}
};

// -----------------------------------------------------------------------

END_NAMESPACE_DGL

using DGL_NAMESPACE::DemoWidgetBanner;

+ 51
- 21
examples/CairoUI/DemoWidgetClickable.hpp View File

@@ -1,7 +1,7 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2019-2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
* Copyright (C) 2012-2023 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
@@ -23,16 +23,51 @@ START_NAMESPACE_DGL

// -----------------------------------------------------------------------

class DemoWidgetClickable : public CairoSubWidget
class DemoWidgetClickable : public CairoSubWidget,
public ButtonEventHandler,
public ButtonEventHandler::Callback
{
public:
class Callback
{
public:
virtual ~Callback() {}
virtual void demoWidgetClicked(DemoWidgetClickable* widget, uint8_t colorId) = 0;
};

explicit DemoWidgetClickable(SubWidget* const parent)
: CairoSubWidget(parent),
colorId(0) {}
ButtonEventHandler(this),
fCallback(nullptr),
fColorId(0)
{
ButtonEventHandler::setCallback(this);
}

explicit DemoWidgetClickable(TopLevelWidget* const parent)
: CairoSubWidget(parent),
colorId(0) {}
ButtonEventHandler(this),
fCallback(nullptr),
fColorId(0)
{
ButtonEventHandler::setCallback(this);
}

void setCallback(Callback* const callback) noexcept
{
fCallback = callback;
}

uint8_t getColorId() const noexcept
{
return fColorId;
}

void setColorId(uint8_t colorId) noexcept
{
fColorId = colorId;
repaint();
}

protected:
void onCairoDisplay(const CairoGraphicsContext& context) override
@@ -43,7 +78,7 @@ protected:
const int w = sz.getWidth();
const int h = sz.getHeight();

switch (colorId)
switch (fColorId)
{
case 0:
cairo_set_source_rgb(cr, 0.75, 0.0, 0.0);
@@ -72,26 +107,21 @@ protected:

bool onMouse(const MouseEvent& event) override
{
if (event.press)
{
const int w = getWidth();
const int h = getHeight();
const int mx = event.pos.getX();
const int my = event.pos.getY();

// inside
if (mx >= 0 && my >= 0 && mx < w && my < h)
{
colorId = (colorId + 1) % 3;
repaint();
}
}
return ButtonEventHandler::mouseEvent(event);
}

void buttonClicked(SubWidget*, int) override
{
fColorId = (fColorId + 1) % 3;
repaint();

return CairoSubWidget::onMouse(event);
if (fCallback != nullptr)
fCallback->demoWidgetClicked(this, fColorId);
}

private:
uint colorId;
Callback* fCallback;
uint8_t fColorId;
};

// -----------------------------------------------------------------------


+ 30
- 4
examples/CairoUI/DistrhoPluginInfo.h View File

@@ -118,10 +118,36 @@
#define DISTRHO_UI_USE_NANOVG 0

/**
The %UI URI when exporting in LV2 format.@n
By default this is set to @ref DISTRHO_PLUGIN_URI with "#UI" as suffix.
Default UI width to use when creating initial and temporary windows.@n
Setting this macro allows to skip a temporary UI from being created in certain VST2 and VST3 hosts.
(which would normally be done for knowing the UI size before host creates a window for it)

Value must match 1x scale factor.

When this macro is defined, the companion DISTRHO_UI_DEFAULT_HEIGHT macro must be defined as well.
*/
#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI"
#define DISTRHO_UI_DEFAULT_WIDTH 200

#define DISTRHO_UI_FILE_BROWSER 0
/**
Default UI height to use when creating initial and temporary windows.@n
Setting this macro allows to skip a temporary UI from being created in certain VST2 and VST3 hosts.
(which would normally be done for knowing the UI size before host creates a window for it)

Value must match 1x scale factor.

When this macro is defined, the companion DISTRHO_UI_DEFAULT_WIDTH macro must be defined as well.
*/
#define DISTRHO_UI_DEFAULT_HEIGHT 200

// TODO document this
#define DISTRHO_UI_USE_CAIRO 1

// TODO document this
#define DISTRHO_UI_FILE_BROWSER 0

enum Parameters {
kParameterKnob,
kParameterTriState,
kParameterButton,
kParameterCount
};

+ 1
- 6
examples/CairoUI/Makefile View File

@@ -17,7 +17,6 @@ FILES_DSP = \

FILES_UI = \
Artwork.cpp \
DemoWidgetBanner.cpp \
CairoExampleUI.cpp

# --------------------------------------------------------------
@@ -29,11 +28,7 @@ include ../../Makefile.plugins.mk
# --------------------------------------------------------------
# Enable all possible plugin types

TARGETS += clap
TARGETS += dssi
TARGETS += jack
TARGETS += lv2_sep
TARGETS += vst2
TARGETS = clap dssi jack lv2_sep vst2 vst3

all: $(TARGETS)



Loading…
Cancel
Save