diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb6938d --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.a +*.d +*.o + +*.exe +*.dll +*.dylib +*.so +*.zip + +.kdev_include_paths +.kdev4/ +.DS_Store + +bin/*-dssi/ +bin/*.lv2/ +bin/d_* +bin/ducka +bin/roomy diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2d642d1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dpf"] + path = dpf + url = git://github.com/DISTRHO/DPF.git diff --git a/.project.kdev4 b/.project.kdev4 new file mode 100644 index 0000000..7f79b15 --- /dev/null +++ b/.project.kdev4 @@ -0,0 +1,9 @@ +[Project] +Manager=KDevCustomMakeManager +Name=DPF Plugins + +[Filters] +Excludes=*/.*,*/*~,*/*.a,*/*.d,*/*.o,*/*.so + +[Project] +VersionControlSupport=kdevgit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6ecc24c --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +DISTRHO Plugin Framework (DPF) +Copyright (C) 2012-2014 Filipe Coelho + +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e8d0d89 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +include Makefile.mk + +all: libs plugins gen + +# -------------------------------------------------------------- + +libs: +ifeq ($(HAVE_DGL),true) + $(MAKE) -C dpf/dgl +endif + +plugins: libs + $(MAKE) all -C plugins/Info + $(MAKE) all -C plugins/Latency + $(MAKE) all -C plugins/Meters + $(MAKE) all -C plugins/MidiThrough + $(MAKE) all -C plugins/Parameters + $(MAKE) all -C plugins/States + +gen: plugins dpf/utils/lv2_ttl_generator + @$(CURDIR)/dpf/utils/generate-ttl.sh +ifeq ($(MACOS),true) + @$(CURDIR)/dpf/utils/generate-vst-bundles.sh +endif + +dpf/utils/lv2_ttl_generator: + $(MAKE) -C dpf/utils/lv2-ttl-generator + +# -------------------------------------------------------------- + +clean: +ifeq ($(HAVE_DGL),true) + $(MAKE) clean -C dpf/dgl +endif + $(MAKE) clean -C dpf/utils/lv2-ttl-generator + $(MAKE) clean -C plugins/Info + $(MAKE) clean -C plugins/Latency + $(MAKE) clean -C plugins/Meters + $(MAKE) clean -C plugins/MidiThrough + $(MAKE) clean -C plugins/Parameters + $(MAKE) clean -C plugins/States + +# -------------------------------------------------------------- + +.PHONY: plugins diff --git a/Makefile.mk b/Makefile.mk new file mode 100644 index 0000000..9100500 --- /dev/null +++ b/Makefile.mk @@ -0,0 +1,147 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +AR ?= ar +CC ?= gcc +CXX ?= g++ + +# -------------------------------------------------------------- +# Fallback to Linux if no other OS defined + +ifneq ($(HAIKU),true) +ifneq ($(MACOS),true) +ifneq ($(WIN32),true) +LINUX=true +endif +endif +endif + +# -------------------------------------------------------------- +# Set build and link flags + +BASE_FLAGS = -Wall -Wextra -pipe +BASE_OPTS = -O2 -ffast-math -mtune=generic -msse -msse2 -fdata-sections -ffunction-sections + +ifneq ($(MACOS),true) +# MacOS doesn't support this +BASE_OPTS += -mfpmath=sse +endif + +ifeq ($(MACOS),true) +# MacOS linker flags +LINK_OPTS = -fdata-sections -ffunction-sections -Wl,-dead_strip -Wl,-dead_strip_dylibs +else +# Common linker flags +LINK_OPTS = -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all +endif + +ifeq ($(RASPPI),true) +# Raspberry-Pi optimization flags +BASE_OPTS = -O2 -ffast-math -march=armv6 -mfpu=vfp -mfloat-abi=hard +LINK_OPTS = -Wl,-O1 -Wl,--as-needed -Wl,--strip-all +endif + +ifeq ($(PANDORA),true) +# OpenPandora optimization flags +BASE_OPTS = -O2 -ffast-math -march=armv7-a -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp +LINK_OPTS = -Wl,-O1 -Wl,--as-needed -Wl,--strip-all +endif + +ifeq ($(NOOPT),true) +# No optimization flags +BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections +endif + +ifneq ($(WIN32),true) +# not needed for Windows +BASE_FLAGS += -fPIC -DPIC +endif + +ifeq ($(DEBUG),true) +BASE_FLAGS += -DDEBUG -O0 -g +LINK_OPTS = +else +BASE_FLAGS += -DNDEBUG $(BASE_OPTS) -fvisibility=hidden +CXXFLAGS += -fvisibility-inlines-hidden +endif + +BUILD_C_FLAGS = $(BASE_FLAGS) -std=c99 -std=gnu99 $(CFLAGS) +BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=c++0x -std=gnu++0x $(CXXFLAGS) $(CPPFLAGS) +LINK_FLAGS = $(LINK_OPTS) -Wl,--no-undefined $(LDFLAGS) + +ifeq ($(MACOS),true) +# No C++11 support +BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) $(CPPFLAGS) +LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS) +endif + +# -------------------------------------------------------------- +# Check for optional libs + +ifeq ($(LINUX),true) +HAVE_DGL = $(shell pkg-config --exists gl x11 && echo true) +HAVE_JACK = $(shell pkg-config --exists jack && echo true) +HAVE_LIBLO = $(shell pkg-config --exists liblo && echo true) +endif + +ifeq ($(MACOS),true) +HAVE_DGL = true +endif + +ifeq ($(WIN32),true) +HAVE_DGL = true +endif + +# -------------------------------------------------------------- +# Set libs stuff + +ifeq ($(HAVE_DGL),true) + +ifeq ($(LINUX),true) +DGL_FLAGS = $(shell pkg-config --cflags gl x11) +DGL_LIBS = $(shell pkg-config --libs gl x11) +endif + +ifeq ($(MACOS),true) +DGL_LIBS = -framework OpenGL -framework Cocoa +endif + +ifeq ($(WIN32),true) +DGL_LIBS = -lopengl32 -lgdi32 +endif + +endif # HAVE_DGL + +# -------------------------------------------------------------- +# Set app extension + +ifeq ($(WIN32),true) +APP_EXT = .exe +endif + +# -------------------------------------------------------------- +# Set shared lib extension + +LIB_EXT = .so + +ifeq ($(MACOS),true) +LIB_EXT = .dylib +endif + +ifeq ($(WIN32),true) +LIB_EXT = .dll +endif + +# -------------------------------------------------------------- +# Set shared library CLI arg + +SHARED = -shared + +ifeq ($(MACOS),true) +SHARED = -dynamiclib +endif + +# -------------------------------------------------------------- diff --git a/README.md b/README.md index 2d4c67c..3f4052e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # DPF Plugin Examples -NOTE: Plugin examples have been moved inside DPF, please visit https://github.com/DISTRHO/DPF. +This repository contains plugin examples and test code for DPF. diff --git a/bin/README b/bin/README new file mode 100644 index 0000000..f90c628 --- /dev/null +++ b/bin/README @@ -0,0 +1,3 @@ +All final plugin builds will be placed in this folder. + +There is no "make install" process, simply copy those files to their appropriate place. diff --git a/plugins/Info/DistrhoPluginInfo.h b/plugins/Info/DistrhoPluginInfo.h new file mode 100644 index 0000000..03e80b9 --- /dev/null +++ b/plugins/Info/DistrhoPluginInfo.h @@ -0,0 +1,47 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "Info" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/Info" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 +#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 +#define DISTRHO_UI_USE_NANOVG 1 + +enum Parameters { + kParameterBufferSize = 0, + kParameterTimePlaying, + kParameterTimeFrame, + kParameterTimeValidBBT, + kParameterTimeBar, + kParameterTimeBeat, + kParameterTimeTick, + kParameterTimeBarStartTick, + kParameterTimeBeatsPerBar, + kParameterTimeBeatType, + kParameterTimeTicksPerBeat, + kParameterTimeBeatsPerMinute, + kParameterCount +}; + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/plugins/Info/InfoExamplePlugin.cpp b/plugins/Info/InfoExamplePlugin.cpp new file mode 100644 index 0000000..f9a508b --- /dev/null +++ b/plugins/Info/InfoExamplePlugin.cpp @@ -0,0 +1,288 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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 show how to get some basic information sent to the UI. + */ +class InfoExamplePlugin : public Plugin +{ +public: + InfoExamplePlugin() + : Plugin(kParameterCount, 0, 0) + { + // clear all parameters + std::memset(fParameters, 0, sizeof(float)*kParameterCount); + + // we can know buffer-size right at the start + fParameters[kParameterBufferSize] = getBufferSize(); + } + +protected: + /* -------------------------------------------------------------------------------------------------------- + * Information */ + + /** + Get the plugin label. + This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters. + */ + const char* getLabel() const override + { + return "Info"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Plugin to show how to get some basic information sent to the UI."; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DISTRHO"; + } + + /** + Get the plugin homepage. + */ + const char* getHomePage() const override + { + return "https://github.com/DISTRHO/plugin-examples"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "ISC"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + int64_t getUniqueId() const override + { + return d_cconst('d', 'N', 'f', 'o'); + } + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize the parameter @a index. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& parameter) override + { + parameter.hints = kParameterIsAutomable|kParameterIsOutput; + parameter.ranges.def = 0.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 16777216.0f; + + switch (index) + { + case kParameterBufferSize: + parameter.name = "BufferSize"; + parameter.symbol = "buffer_size"; + break; + case kParameterTimePlaying: + parameter.hints |= kParameterIsBoolean; + parameter.name = "TimePlaying"; + parameter.symbol = "time_playing"; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + break; + case kParameterTimeFrame: + parameter.name = "TimeFrame"; + parameter.symbol = "time_frame"; + break; + case kParameterTimeValidBBT: + parameter.hints |= kParameterIsBoolean; + parameter.name = "TimeValidBBT"; + parameter.symbol = "time_validbbt"; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + break; + case kParameterTimeBar: + parameter.name = "TimeBar"; + parameter.symbol = "time_bar"; + break; + case kParameterTimeBeat: + parameter.name = "TimeBeat"; + parameter.symbol = "time_beat"; + break; + case kParameterTimeTick: + parameter.name = "TimeTick"; + parameter.symbol = "time_tick"; + break; + case kParameterTimeBarStartTick: + parameter.name = "TimeBarStartTick"; + parameter.symbol = "time_barstarttick"; + break; + case kParameterTimeBeatsPerBar: + parameter.name = "TimeBeatsPerBar"; + parameter.symbol = "time_beatsperbar"; + break; + case kParameterTimeBeatType: + parameter.name = "TimeBeatType"; + parameter.symbol = "time_beattype"; + break; + case kParameterTimeTicksPerBeat: + parameter.name = "TimeTicksPerBeat"; + parameter.symbol = "time_ticksperbeat"; + break; + case kParameterTimeBeatsPerMinute: + parameter.name = "TimeBeatsPerMinute"; + parameter.symbol = "time_beatsperminute"; + break; + } + } + + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter. + The host may call this function from any context, including realtime processing. + */ + float getParameterValue(uint32_t index) const override + { + return fParameters[index]; + + } + + /** + Change a parameter value. + The host may call this function from any context, including realtime processing. + 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. + */ + void setParameterValue(uint32_t, float) override + { + // this is only called for input paramters, which we have none of. + } + + /* -------------------------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + /** + 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** inputs, float** outputs, uint32_t frames) override + { + /** + This plugin does nothing, it just demonstrates information usage. + So here we directly copy inputs over outputs, leaving the audio untouched. + We need to be careful in case the host re-uses the same buffer for both ins and outs. + */ + 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); + + // get time position + const TimePosition& timePos(getTimePosition()); + + // set basic values + fParameters[kParameterTimePlaying] = timePos.playing ? 1.0f : 0.0f; + fParameters[kParameterTimeFrame] = timePos.frame; + fParameters[kParameterTimeValidBBT] = timePos.bbt.valid ? 1.0f : 0.0f; + + // set bbt + if (timePos.bbt.valid) + { + fParameters[kParameterTimeBar] = timePos.bbt.bar; + fParameters[kParameterTimeBeat] = timePos.bbt.beat; + fParameters[kParameterTimeTick] = timePos.bbt.tick; + fParameters[kParameterTimeBarStartTick] = timePos.bbt.barStartTick; + fParameters[kParameterTimeBeatsPerBar] = timePos.bbt.beatsPerBar; + fParameters[kParameterTimeBeatType] = timePos.bbt.beatType; + fParameters[kParameterTimeTicksPerBeat] = timePos.bbt.ticksPerBeat; + fParameters[kParameterTimeBeatsPerMinute] = timePos.bbt.beatsPerMinute; + } + else + { + fParameters[kParameterTimeBar] = 0.0f; + fParameters[kParameterTimeBeat] = 0.0f; + fParameters[kParameterTimeTick] = 0.0f; + fParameters[kParameterTimeBarStartTick] = 0.0f; + fParameters[kParameterTimeBeatsPerBar] = 0.0f; + fParameters[kParameterTimeBeatType] = 0.0f; + fParameters[kParameterTimeTicksPerBeat] = 0.0f; + fParameters[kParameterTimeBeatsPerMinute] = 0.0f; + } + } + + /* -------------------------------------------------------------------------------------------------------- + * Callbacks (optional) */ + + /** + Optional callback to inform the plugin about a buffer size change.@ + This function will only be called when the plugin is deactivated. + @note This value is only a hint! + Hosts might call run() with a higher or lower number of frames. + */ + void bufferSizeChanged(uint32_t newBufferSize) override + { + fParameters[kParameterBufferSize] = newBufferSize; + } + + // ------------------------------------------------------------------------------------------------------- + +private: + // Parameters + float fParameters[kParameterCount]; + + /** + Set our plugin class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(InfoExamplePlugin) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin entry point, called by DPF to create a new plugin instance. */ + +Plugin* createPlugin() +{ + return new InfoExamplePlugin(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/Info/InfoExampleUI.cpp b/plugins/Info/InfoExampleUI.cpp new file mode 100644 index 0000000..0ba5649 --- /dev/null +++ b/plugins/Info/InfoExampleUI.cpp @@ -0,0 +1,222 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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 "DistrhoPluginInfo.h" + +#include "DistrhoUI.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------------------------------------------- + +class InfoExampleUI : public UI +{ +public: + InfoExampleUI() + : UI(405, 256) + { + std::memset(fParameters, 0, sizeof(float)*kParameterCount); + std::memset(fStrBuf, 0, sizeof(char)*(0xff+1)); + + fSampleRate = getSampleRate(); + fFont = createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); + } + +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 parameterChanged(uint32_t index, float value) override + { + fParameters[index] = value; + repaint(); + } + + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks (optional) */ + + /** + Optional callback to inform the UI about a sample rate change on the plugin side. + */ + void sampleRateChanged(double newSampleRate) override + { + fSampleRate = newSampleRate; + repaint(); + } + + /* -------------------------------------------------------------------------------------------------------- + * Widget Callbacks */ + + /** + The NanoVG drawing function. + */ + void onNanoDisplay() override + { + static const float lineHeight = 20; + + fontSize(15.0f); + textLineHeight(lineHeight); + + float x = 0; + float y = 15; + + // buffer size + drawLeft(x, y, "Buffer Size:"); + drawRight(x, y, getTextBufInt(fParameters[kParameterBufferSize])); + y+=lineHeight; + + // sample rate + drawLeft(x, y, "Sample Rate:"); + drawRight(x, y, getTextBufFloat(fSampleRate)); + y+=lineHeight; + + // nothing + y+=lineHeight; + + // time stuff + drawLeft(x, y, "Playing:"); + drawRight(x, y, (fParameters[kParameterTimePlaying] > 0.5f) ? "Yes" : "No"); + y+=lineHeight; + + drawLeft(x, y, "Frame:"); + drawRight(x, y, getTextBufInt(fParameters[kParameterTimeFrame])); + y+=lineHeight; + + drawLeft(x, y, "Time:"); + drawRight(x, y, getTextBufTime(fParameters[kParameterTimeFrame])); + y+=lineHeight; + + // BBT + x = 200; + y = 15; + + const bool validBBT(fParameters[kParameterTimeValidBBT] > 0.5f); + drawLeft(x, y, "BBT Valid:"); + drawRight(x, y, validBBT ? "Yes" : "No"); + y+=lineHeight; + + if (! validBBT) + return; + + drawLeft(x, y, "Bar:"); + drawRight(x, y, getTextBufInt(fParameters[kParameterTimeBar])); + y+=lineHeight; + + drawLeft(x, y, "Beat:"); + drawRight(x, y, getTextBufInt(fParameters[kParameterTimeBeat])); + y+=lineHeight; + + drawLeft(x, y, "Tick:"); + drawRight(x, y, getTextBufInt(fParameters[kParameterTimeTick])); + y+=lineHeight; + + drawLeft(x, y, "Bar Start Tick:"); + drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBarStartTick])); + y+=lineHeight; + + drawLeft(x, y, "Beats Per Bar:"); + drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatsPerBar])); + y+=lineHeight; + + drawLeft(x, y, "Beat Type:"); + drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatType])); + y+=lineHeight; + + drawLeft(x, y, "Ticks Per Beat:"); + drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeTicksPerBeat])); + y+=lineHeight; + + drawLeft(x, y, "BPM:"); + drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatsPerMinute])); + y+=lineHeight; + } + + // ------------------------------------------------------------------------------------------------------- + +private: + // Parameters + float fParameters[kParameterCount]; + double fSampleRate; + + // font + FontId fFont; + + // temp buf for text + char fStrBuf[0xff+1]; + + // helpers for putting text into fStrBuf and returning it + const char* getTextBufInt(const int value) + { + std::snprintf(fStrBuf, 0xff, "%i", value); + return fStrBuf; + } + + const char* getTextBufFloat(const float value) + { + std::snprintf(fStrBuf, 0xff, "%.1f", value); + return fStrBuf; + } + + const char* getTextBufTime(const uint64_t frame) + { + const uint32_t time = frame / uint64_t(fSampleRate); + const uint32_t secs = time % 60; + const uint32_t mins = (time / 60) % 60; + const uint32_t hrs = (time / 3600) % 60; + std::snprintf(fStrBuf, 0xff, "%02i:%02i:%02i", hrs, mins, secs); + return fStrBuf; + } + + // helpers for drawing text + void drawLeft(const float x, const float y, const char* const text) + { + beginPath(); + fillColor(200, 200, 200); + textAlign(ALIGN_RIGHT|ALIGN_TOP); + textBox(x, y, 100, text); + closePath(); + } + + void drawRight(const float x, const float y, const char* const text) + { + beginPath(); + fillColor(255, 255, 255); + textAlign(ALIGN_LEFT|ALIGN_TOP); + textBox(x+105, y, 100, text); + closePath(); + } + + /** + Set our UI class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(InfoExampleUI) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * UI entry point, called by DPF to create a new UI instance. */ + +UI* createUI() +{ + return new InfoExampleUI(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/Info/Makefile b/plugins/Info/Makefile new file mode 100644 index 0000000..252a1cc --- /dev/null +++ b/plugins/Info/Makefile @@ -0,0 +1,45 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = d_info + +# -------------------------------------------------------------- +# Files to build + +OBJS_DSP = \ + InfoExamplePlugin.cpp.o + +OBJS_UI = \ + InfoExampleUI.cpp.o + +# -------------------------------------------------------------- +# Do some magic + +include ../Makefile.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +ifeq ($(HAVE_DGL),true) +ifeq ($(HAVE_JACK),true) +TARGETS += jack +endif +endif + +ifeq ($(HAVE_DGL),true) +TARGETS += lv2_sep +else +TARGETS += lv2_dsp +endif + +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/plugins/Info/README.md b/plugins/Info/README.md new file mode 100644 index 0000000..b3fff70 --- /dev/null +++ b/plugins/Info/README.md @@ -0,0 +1,10 @@ +# Information example + +This example will show how to get some basic information sent to the UI.
+ +The Plugin has a lot of parameter outputs which the UI uses to get info from.
+This includes buffer-size and time position.
+Sample-rate can be requested directly from the UI.
+The UI will show this information as text.
+ +The plugin will not do any audio processing.
diff --git a/plugins/Latency/DistrhoPluginInfo.h b/plugins/Latency/DistrhoPluginInfo.h new file mode 100644 index 0000000..f763bc5 --- /dev/null +++ b/plugins/Latency/DistrhoPluginInfo.h @@ -0,0 +1,30 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "Latency" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/Latency" + +#define DISTRHO_PLUGIN_HAS_UI 0 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 1 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 1 +#define DISTRHO_PLUGIN_WANT_LATENCY 1 + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/plugins/Latency/LatencyExamplePlugin.cpp b/plugins/Latency/LatencyExamplePlugin.cpp new file mode 100644 index 0000000..5dce73f --- /dev/null +++ b/plugins/Latency/LatencyExamplePlugin.cpp @@ -0,0 +1,251 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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 that demonstrates the latency API in DPF. + */ +class LatencyExamplePlugin : public Plugin +{ +public: + LatencyExamplePlugin() + : Plugin(1, 0, 0), // 1 parameter + fLatency(1.0f), + fLatencyInFrames(0), + fBuffer(nullptr), + fBufferPos(0) + { + // allocates buffer + sampleRateChanged(getSampleRate()); + } + + ~LatencyExamplePlugin() override + { + delete[] fBuffer; + } + +protected: + /* -------------------------------------------------------------------------------------------------------- + * Information */ + + /** + Get the plugin label. + This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters. + */ + const char* getLabel() const override + { + return "Latency"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Plugin that demonstrates the latency API in DPF."; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DISTRHO"; + } + + /** + Get the plugin homepage. + */ + const char* getHomePage() const override + { + return "https://github.com/DISTRHO/plugin-examples"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "ISC"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + int64_t getUniqueId() const override + { + return d_cconst('d', 'L', 'a', 't'); + } + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize the parameter @a index. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& parameter) override + { + if (index != 0) + return; + + parameter.hints = kParameterIsAutomable; + parameter.name = "Latency"; + parameter.symbol = "latency"; + parameter.unit = "s"; + parameter.ranges.def = 1.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 5.0f; + } + + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter. + The host may call this function from any context, including realtime processing. + */ + float getParameterValue(uint32_t index) const override + { + if (index != 0) + return 0.0f; + + return fLatency; + } + + /** + Change a parameter value. + The host may call this function from any context, including realtime processing. + 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. + */ + void setParameterValue(uint32_t index, float value) override + { + if (index != 0) + return; + + fLatency = value; + fLatencyInFrames = value*getSampleRate(); + + setLatency(fLatencyInFrames); + } + + /* -------------------------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + /** + 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** inputs, float** outputs, uint32_t frames) override + { + const float* const in = inputs[0]; + /* */ float* const out = outputs[0]; + + if (fLatencyInFrames == 0) + { + if (out != in) + std::memcpy(out, in, sizeof(float)*frames); + return; + } + + // Put the new audio in the buffer. + std::memcpy(fBuffer+fBufferPos, in, sizeof(float)*frames); + fBufferPos += frames; + + // buffer is not filled enough yet + if (fBufferPos < fLatencyInFrames+frames) + { + // silence output + std::memset(out, 0, sizeof(float)*frames); + } + // buffer is ready to copy + else + { + // copy latency buffer to output + const uint32_t readPos = fBufferPos-fLatencyInFrames-frames; + std::memcpy(out, fBuffer+readPos, sizeof(float)*frames); + + // move latency buffer back by some frames + std::memmove(fBuffer, fBuffer+frames, sizeof(float)*fBufferPos); + fBufferPos -= frames; + } + } + + /* -------------------------------------------------------------------------------------------------------- + * Callbacks (optional) */ + + /** + Optional callback to inform the plugin about a sample rate change. + This function will only be called when the plugin is deactivated. + */ + void sampleRateChanged(double newSampleRate) override + { + if (fBuffer != nullptr) + delete[] fBuffer; + + const uint32_t maxFrames = newSampleRate*6; // 6 seconds + + fBuffer = new float[maxFrames]; + std::memset(fBuffer, 0, sizeof(float)*maxFrames); + + fLatencyInFrames = fLatency*newSampleRate; + fBufferPos = 0; + } + + // ------------------------------------------------------------------------------------------------------- + +private: + // Parameters + float fLatency; + uint32_t fLatencyInFrames; + + // Buffer for previous audio, size depends on sample rate + float* fBuffer; + uint32_t fBufferPos; + + /** + Set our plugin class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LatencyExamplePlugin) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin entry point, called by DPF to create a new plugin instance. */ + +Plugin* createPlugin() +{ + return new LatencyExamplePlugin(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/Latency/Makefile b/plugins/Latency/Makefile new file mode 100644 index 0000000..8a635e1 --- /dev/null +++ b/plugins/Latency/Makefile @@ -0,0 +1,36 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = d_latency + +# -------------------------------------------------------------- +# Files to build + +OBJS_DSP = \ + LatencyExamplePlugin.cpp.o + +# -------------------------------------------------------------- +# Do some magic + +include ../Makefile.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +ifeq ($(LINUX),true) +TARGETS += ladspa +TARGETS += dssi +endif + +TARGETS += lv2_dsp +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/plugins/Latency/README.md b/plugins/Latency/README.md new file mode 100644 index 0000000..9696f5f --- /dev/null +++ b/plugins/Latency/README.md @@ -0,0 +1,8 @@ +# Latency example + +This example will show how to use latency in DPF based plugins.
+ +The plugin will delay its audio signal by a variable amount of time, specified by a parameter.
+Good hosts will receive this hint and compensate accordingly.
+ +The plugin has no UI because there's no need for one in this case.
diff --git a/plugins/Makefile.mk b/plugins/Makefile.mk new file mode 100644 index 0000000..00d82fa --- /dev/null +++ b/plugins/Makefile.mk @@ -0,0 +1,153 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# NAME, OBJS_DSP and OBJS_UI have been defined before + +include ../../Makefile.mk + +ifeq ($(OBJS_UI),) +HAVE_DGL = false +endif + +# -------------------------------------------------------------- +# Basic setup + +TARGET_DIR = ../../bin + +BUILD_C_FLAGS += -I. +BUILD_CXX_FLAGS += -I. -I../../dpf/distrho -I../../dpf/dgl + +ifeq ($(HAVE_DGL),true) +BASE_FLAGS += -DHAVE_DGL +endif + +ifeq ($(HAVE_JACK),true) +BASE_FLAGS += -DHAVE_JACK +endif + +ifeq ($(HAVE_LIBLO),true) +BASE_FLAGS += -DHAVE_LIBLO +endif + +# -------------------------------------------------------------- +# Set plugin binary file targets + +jack = $(TARGET_DIR)/$(NAME)$(APP_EXT) +ladspa_dsp = $(TARGET_DIR)/$(NAME)-ladspa$(LIB_EXT) +dssi_dsp = $(TARGET_DIR)/$(NAME)-dssi$(LIB_EXT) +dssi_ui = $(TARGET_DIR)/$(NAME)-dssi/$(NAME)_ui$(APP_EXT) +lv2 = $(TARGET_DIR)/$(NAME).lv2/$(NAME)$(LIB_EXT) +lv2_dsp = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_dsp$(LIB_EXT) +lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT) +vst = $(TARGET_DIR)/$(NAME)-vst$(LIB_EXT) + +# -------------------------------------------------------------- +# Set distrho code files + +DISTRHO_PLUGIN_FILES = ../../dpf/distrho/DistrhoPluginMain.cpp + +ifeq ($(HAVE_DGL),true) +DISTRHO_UI_FILES = ../../dpf/distrho/DistrhoUIMain.cpp ../../dpf/libdgl.a +endif + +# -------------------------------------------------------------- +# Handle plugins without UI + +ifneq ($(HAVE_DGL),true) +dssi_ui = +lv2_ui = +DISTRHO_UI_FILES = +DGL_LIBS = +OBJS_UI = +endif + +# -------------------------------------------------------------- +# all needs to be first + +all: + +# -------------------------------------------------------------- +# Common + +%.c.o: %.c + $(CC) $< $(BUILD_C_FLAGS) -MD -MP -c -o $@ + +%.cpp.o: %.cpp + $(CXX) $< $(BUILD_CXX_FLAGS) -MD -MP -c -o $@ + +clean: + rm -f *.d *.o + rm -rf $(TARGET_DIR)/$(NAME) $(TARGET_DIR)/$(NAME)-* $(TARGET_DIR)/$(NAME).lv2/ + +# -------------------------------------------------------------- +# JACK + +jack: $(jack) + +$(jack): $(OBJS_DSP) $(OBJS_UI) $(DISTRHO_PLUGIN_FILES) $(DISTRHO_UI_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --cflags --libs jack) -DDISTRHO_PLUGIN_TARGET_JACK -o $@ + +# -------------------------------------------------------------- +# LADSPA + +ladspa: $(ladspa_dsp) + +$(ladspa_dsp): $(OBJS_DSP) $(DISTRHO_PLUGIN_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -DDISTRHO_PLUGIN_TARGET_LADSPA -o $@ + +# -------------------------------------------------------------- +# DSSI + +dssi: $(dssi_dsp) $(dssi_ui) +dssi_dsp: $(dssi_dsp) +dssi_ui: $(dssi_ui) + +$(dssi_dsp): $(OBJS_DSP) $(DISTRHO_PLUGIN_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -DDISTRHO_PLUGIN_TARGET_DSSI -o $@ + +$(dssi_ui): $(OBJS_UI) $(DISTRHO_UI_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --cflags --libs liblo) -DDISTRHO_PLUGIN_TARGET_DSSI -o $@ + +# -------------------------------------------------------------- +# LV2 + +lv2_one: $(lv2) +lv2_dsp: $(lv2_dsp) +lv2_sep: $(lv2_dsp) $(lv2_ui) + +$(lv2): $(OBJS_DSP) $(OBJS_UI) $(DISTRHO_PLUGIN_FILES) $(DISTRHO_UI_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -DDISTRHO_PLUGIN_TARGET_LV2 -o $@ + +$(lv2_dsp): $(OBJS_DSP) $(DISTRHO_PLUGIN_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) -DDISTRHO_PLUGIN_TARGET_LV2 -o $@ + +$(lv2_ui): $(OBJS_UI) $(DISTRHO_UI_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -DDISTRHO_PLUGIN_TARGET_LV2 -o $@ + +# -------------------------------------------------------------- +# VST + +vst: $(vst) + +$(vst): $(OBJS_DSP) $(OBJS_UI) $(DISTRHO_PLUGIN_FILES) $(DISTRHO_UI_FILES) + mkdir -p $(shell dirname $@) + $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -DDISTRHO_PLUGIN_TARGET_VST -o $@ + +# -------------------------------------------------------------- + +-include $(OBJS_DSP:%.o=%.d) +ifeq ($(HAVE_DGL),true) +-include $(OBJS_UI:%.o=%.d) +endif + +# -------------------------------------------------------------- diff --git a/plugins/Meters/DistrhoPluginInfo.h b/plugins/Meters/DistrhoPluginInfo.h new file mode 100644 index 0000000..f00d09a --- /dev/null +++ b/plugins/Meters/DistrhoPluginInfo.h @@ -0,0 +1,34 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2018 Filipe Coelho + * + * 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_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "Meters" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/Meters" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 +#define DISTRHO_PLUGIN_WANT_STATE 1 +#define DISTRHO_UI_USE_NANOVG 1 + +#define METER_COLOR_GREEN 0 +#define METER_COLOR_BLUE 1 + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/plugins/Meters/ExamplePluginMeters.cpp b/plugins/Meters/ExamplePluginMeters.cpp new file mode 100644 index 0000000..40f7951 --- /dev/null +++ b/plugins/Meters/ExamplePluginMeters.cpp @@ -0,0 +1,284 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2018 Filipe Coelho + * + * 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* getLabel() const override + { + return "meters"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Plugin to demonstrate parameter outputs using meters."; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DISTRHO"; + } + + /** + Get the plugin homepage. + */ + const char* getHomePage() const override + { + return "https://github.com/DISTRHO/plugin-examples"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "ISC"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + int64_t 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 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"; + parameter.enumValues.count = 2; + parameter.enumValues.restrictedMode = true; + { + ParameterEnumerationValue* const values = new ParameterEnumerationValue[2]; + parameter.enumValues.values = values; + + values[0].label = "Green"; + values[0].value = METER_COLOR_GREEN; + values[1].label = "Blue"; + values[1].value = METER_COLOR_BLUE; + } + 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 initState(uint32_t, String&, 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 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 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 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 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 tmpLeft) + tmpLeft = tmp; + + // right + tmp = std::abs(inputs[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 diff --git a/plugins/Meters/ExampleUIMeters.cpp b/plugins/Meters/ExampleUIMeters.cpp new file mode 100644 index 0000000..e42a8b1 --- /dev/null +++ b/plugins/Meters/ExampleUIMeters.cpp @@ -0,0 +1,254 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2018 Filipe Coelho + * + * 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(128, 512), + // 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) + { + } + +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 parameterChanged(uint32_t index, float value) override + { + switch (index) + { + case 0: // color + updateColor(std::round(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; + } + } + + /** + A state has changed on the plugin side. + This is called by the host to inform the UI about state changes. + */ + void 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 + setState("reset", ""); + + // useful vars + const float halfWidth = static_cast(getWidth())/2; + const float redYellowHeight = static_cast(getHeight())*0.2f; + const float yellowBaseHeight = static_cast(getHeight())*0.4f; + const float baseBaseHeight = static_cast(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); + 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 METER_COLOR_GREEN: + fColor = Color(93, 231, 61); + break; + case METER_COLOR_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 diff --git a/plugins/Meters/Makefile b/plugins/Meters/Makefile new file mode 100644 index 0000000..b642ff9 --- /dev/null +++ b/plugins/Meters/Makefile @@ -0,0 +1,53 @@ +#!/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 ($(HAVE_DGL),true) +ifeq ($(HAVE_JACK),true) +TARGETS += jack +endif +endif + +ifeq ($(LINUX),true) +ifeq ($(HAVE_DGL),true) +ifeq ($(HAVE_LIBLO),true) +TARGETS += dssi +endif +endif +endif + +ifeq ($(HAVE_DGL),true) +TARGETS += lv2_sep +else +TARGETS += lv2_dsp +endif + +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/plugins/Meters/README.md b/plugins/Meters/README.md new file mode 100644 index 0000000..a2386d7 --- /dev/null +++ b/plugins/Meters/README.md @@ -0,0 +1,8 @@ +# Meters example + +This example will show how parameter outputs can be used for UI meters in DPF.
+The plugin will inspect the host audio buffer but it won't change it in any way.
+ +In this example the UI will display a simple meter based on the plugin's parameter outputs.
+In order to make drawing easier the UI uses NanoVG instead of raw OpenGL.
+Please see the Parameters and States examples before studying this one.
diff --git a/plugins/MidiThrough/DistrhoPluginInfo.h b/plugins/MidiThrough/DistrhoPluginInfo.h new file mode 100644 index 0000000..5ba03b3 --- /dev/null +++ b/plugins/MidiThrough/DistrhoPluginInfo.h @@ -0,0 +1,31 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2018 Filipe Coelho + * + * 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_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "MidiThrough" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/MidiThrough" + +#define DISTRHO_PLUGIN_HAS_UI 0 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 0 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 0 +#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 +#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1 + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/plugins/MidiThrough/Makefile b/plugins/MidiThrough/Makefile new file mode 100644 index 0000000..258863f --- /dev/null +++ b/plugins/MidiThrough/Makefile @@ -0,0 +1,35 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = d_midiThrough + +# -------------------------------------------------------------- +# Files to build + +OBJS_DSP = \ + MidiThroughExamplePlugin.cpp.o + +# -------------------------------------------------------------- +# Do some magic + +include ../Makefile.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +ifeq ($(LINUX),true) +TARGETS += jack +endif + +TARGETS += lv2_dsp +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/plugins/MidiThrough/MidiThroughExamplePlugin.cpp b/plugins/MidiThrough/MidiThroughExamplePlugin.cpp new file mode 100644 index 0000000..7f7d372 --- /dev/null +++ b/plugins/MidiThrough/MidiThroughExamplePlugin.cpp @@ -0,0 +1,137 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2018 Filipe Coelho + * + * 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 that demonstrates the latency API in DPF. + */ +class MidiThroughExamplePlugin : public Plugin +{ +public: + MidiThroughExamplePlugin() + : Plugin(0, 0, 0) {} + +protected: + /* -------------------------------------------------------------------------------------------------------- + * Information */ + + /** + Get the plugin label. + This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters. + */ + const char* getLabel() const override + { + return "MidiThrough"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Plugin that demonstrates the latency API in DPF."; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DISTRHO"; + } + + /** + Get the plugin homepage. + */ + const char* getHomePage() const override + { + return "https://github.com/DISTRHO/plugin-examples"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "ISC"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + int64_t getUniqueId() const override + { + return d_cconst('d', 'M', 'T', 'r'); + } + + /* -------------------------------------------------------------------------------------------------------- + * Init and Internal data, unused in this plugin */ + + void initParameter(uint32_t, Parameter&) override {} + float getParameterValue(uint32_t) const override { return 0.0f;} + void setParameterValue(uint32_t, float) override {} + + /* -------------------------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + /** + Run/process function for plugins with MIDI input. + In this case we just pass-through all MIDI events. + */ + void run(const float**, float**, uint32_t, + const MidiEvent* midiEvents, uint32_t midiEventCount) override + { + for (uint32_t i=0; i + +It simply calls writeMidiEvent() in its process function for every event it receives. + diff --git a/plugins/Parameters/DistrhoPluginInfo.h b/plugins/Parameters/DistrhoPluginInfo.h new file mode 100644 index 0000000..2c116cd --- /dev/null +++ b/plugins/Parameters/DistrhoPluginInfo.h @@ -0,0 +1,30 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho + * + * 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_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "Parameters" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/Parameters" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 +#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/plugins/Parameters/ExamplePluginParameters.cpp b/plugins/Parameters/ExamplePluginParameters.cpp new file mode 100644 index 0000000..c740cc7 --- /dev/null +++ b/plugins/Parameters/ExamplePluginParameters.cpp @@ -0,0 +1,292 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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 + +// ----------------------------------------------------------------------------------------------------------- + +/** + Simple plugin to demonstrate parameter usage (including UI). + The plugin will be treated as an effect, but it will not change the host audio. + */ +class ExamplePluginParameters : public Plugin +{ +public: + ExamplePluginParameters() + : Plugin(9, 2, 0) // 9 parameters, 2 programs, 0 states + { + /** + Initialize all our parameters to their defaults. + In this example all parameters have 0 as default, so we can simply zero them. + */ + std::memset(fParamGrid, 0, sizeof(float)*9); + } + +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* getLabel() const override + { + return "parameters"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Simple plugin to demonstrate parameter usage (including UI).\n\ +The plugin will be treated as an effect, but it will not change the host audio."; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DISTRHO"; + } + + /** + Get the plugin homepage. + */ + const char* getHomePage() const override + { + return "https://github.com/DISTRHO/plugin-examples"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "ISC"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + int64_t getUniqueId() const override + { + return d_cconst('d', 'P', 'r', 'm'); + } + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize the parameter @a index. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& parameter) override + { + /** + All parameters in this plugin are similar except for name. + As such, we initialize the common details first, then set the unique name later. + */ + + /** + Changing parameters does not cause any realtime-unsafe operations, so we can mark them as automable. + Also set as boolean because they work as on/off switches. + */ + parameter.hints = kParameterIsAutomable|kParameterIsBoolean; + + /** + Minimum 0 (off), maximum 1 (on). + Default is off. + */ + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + parameter.ranges.def = 0.0f; + + /** + Set the (unique) parameter name. + @see fParamGrid + */ + switch (index) + { + case 0: + parameter.name = "top-left"; + break; + case 1: + parameter.name = "top-center"; + break; + case 2: + parameter.name = "top-right"; + break; + case 3: + parameter.name = "middle-left"; + break; + case 4: + parameter.name = "middle-center"; + break; + case 5: + parameter.name = "middle-right"; + break; + case 6: + parameter.name = "bottom-left"; + break; + case 7: + parameter.name = "bottom-center"; + break; + case 8: + parameter.name = "bottom-right"; + break; + } + + /** + Our parameter names are valid symbols except for "-". + */ + parameter.symbol = parameter.name; + parameter.symbol.replace('-', '_'); + } + + /** + Set the name of the program @a index. + This function will be called once, shortly after the plugin is created. + */ + void initProgramName(uint32_t index, String& programName) override + { + switch (index) + { + case 0: + programName = "Default"; + break; + case 1: + programName = "Custom"; + break; + } + } + + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter. + */ + float getParameterValue(uint32_t index) const override + { + return fParamGrid[index]; + } + + /** + Change a parameter value. + */ + void setParameterValue(uint32_t index, float value) override + { + fParamGrid[index] = value; + } + + /** + Load a program. + The host may call this function from any context, including realtime processing. + */ + void loadProgram(uint32_t index) override + { + switch (index) + { + case 0: + fParamGrid[0] = 0.0f; + fParamGrid[1] = 0.0f; + fParamGrid[2] = 0.0f; + fParamGrid[3] = 0.0f; + fParamGrid[4] = 0.0f; + fParamGrid[5] = 0.0f; + fParamGrid[6] = 0.0f; + fParamGrid[7] = 0.0f; + fParamGrid[8] = 0.0f; + break; + case 1: + fParamGrid[0] = 1.0f; + fParamGrid[1] = 1.0f; + fParamGrid[2] = 0.0f; + fParamGrid[3] = 0.0f; + fParamGrid[4] = 1.0f; + fParamGrid[5] = 1.0f; + fParamGrid[6] = 1.0f; + fParamGrid[7] = 0.0f; + fParamGrid[8] = 1.0f; + break; + } + } + + /* -------------------------------------------------------------------------------------------------------- + * Process */ + + /** + Run/process function for plugins without MIDI input. + */ + void run(const float** inputs, float** outputs, uint32_t frames) override + { + /** + This plugin does nothing, it just demonstrates parameter usage. + So here we directly copy inputs over outputs, leaving the audio untouched. + We need to be careful in case the host re-uses the same buffer for both ins and outs. + */ + 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: + /** + Our parameters are used to display a 3x3 grid like this: + 0 1 2 + 3 4 5 + 6 7 8 + + The index matches its grid position. + */ + float fParamGrid[9]; + + /** + Set our plugin class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExamplePluginParameters) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin entry point, called by DPF to create a new plugin instance. */ + +Plugin* createPlugin() +{ + return new ExamplePluginParameters(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/Parameters/ExampleUIParameters.cpp b/plugins/Parameters/ExampleUIParameters.cpp new file mode 100644 index 0000000..e02c77a --- /dev/null +++ b/plugins/Parameters/ExampleUIParameters.cpp @@ -0,0 +1,244 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho + * + * 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 rectangle class from DGL. + */ +using DGL::Rectangle; + +// ----------------------------------------------------------------------------------------------------------- + +class ExampleUIParameters : public UI +{ +public: + /** + For simplicity this UI will be of constant size. + */ + static const int kUIWidth = 512; + static const int kUIHeight = 512; + + /* constructor */ + ExampleUIParameters() + : UI(kUIWidth, kUIHeight) + { + /** + Initialize all our parameters to their defaults. + In this example all default values are false, so we can simply zero them. + */ + std::memset(fParamGrid, 0, sizeof(bool)*9); + } + +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 parameterChanged(uint32_t index, float value) override + { + // update our grid state to match the plugin side + fParamGrid[index] = (value > 0.5f); + + // trigger repaint + repaint(); + } + + /** + A program has been loaded on the plugin side. + This is called by the host to inform the UI about program changes. + */ + void programLoaded(uint32_t index) override + { + switch (index) + { + case 0: + fParamGrid[0] = false; + fParamGrid[1] = false; + fParamGrid[2] = false; + fParamGrid[3] = false; + fParamGrid[4] = false; + fParamGrid[5] = false; + fParamGrid[6] = false; + fParamGrid[7] = false; + fParamGrid[8] = false; + break; + case 1: + fParamGrid[0] = true; + fParamGrid[1] = true; + fParamGrid[2] = false; + fParamGrid[3] = false; + fParamGrid[4] = true; + fParamGrid[5] = true; + fParamGrid[6] = true; + fParamGrid[7] = false; + fParamGrid[8] = true; + break; + } + repaint(); + } + + /* -------------------------------------------------------------------------------------------------------- + * Widget Callbacks */ + + /** + The OpenGL drawing function. + This UI will draw a 3x3 grid, with on/off states according to plugin parameters. + */ + void onDisplay() override + { + Rectangle r; + + r.setWidth(kUIWidth/3 - 6); + r.setHeight(kUIHeight/3 - 6); + + // draw left, center and right columns + for (int i=0; i<3; ++i) + { + r.setX(3 + i*kUIWidth/3); + + // top + r.setY(3); + + if (fParamGrid[0+i]) + glColor3f(0.8f, 0.5f, 0.3f); + else + glColor3f(0.3f, 0.5f, 0.8f); + + r.draw(); + + // middle + r.setY(3 + kUIHeight/3); + + if (fParamGrid[3+i]) + glColor3f(0.8f, 0.5f, 0.3f); + else + glColor3f(0.3f, 0.5f, 0.8f); + + r.draw(); + + // bottom + r.setY(3 + kUIHeight*2/3); + + if (fParamGrid[6+i]) + glColor3f(0.8f, 0.5f, 0.3f); + else + glColor3f(0.3f, 0.5f, 0.8f); + + r.draw(); + } + } + + /** + Mouse press event. + This UI will de/activate blocks when you click them and reports it as a parameter change to the plugin. + */ + bool onMouse(const MouseEvent& ev) override + { + // Test for left-clicked + pressed first. + if (ev.button != 1 || ! ev.press) + return false; + + Rectangle r; + + r.setWidth(kUIWidth/3 - 6); + r.setHeight(kUIHeight/3 - 6); + + // handle left, center and right columns + for (int i=0; i<3; ++i) + { + r.setX(3 + i*kUIWidth/3); + + // top + r.setY(3); + + if (r.contains(ev.pos)) + { + // parameter index that this block applies to + const uint32_t index = 0+i; + + // invert block state + fParamGrid[index] = !fParamGrid[index]; + + // report change to host (and thus plugin) + setParameterValue(index, fParamGrid[index] ? 1.0f : 0.0f); + + // trigger repaint + repaint(); + break; + } + + // middle + r.setY(3 + kUIHeight/3); + + if (r.contains(ev.pos)) + { + // same as before + const uint32_t index = 3+i; + fParamGrid[index] = !fParamGrid[index]; + setParameterValue(index, fParamGrid[index] ? 1.0f : 0.0f); + repaint(); + break; + } + + // bottom + r.setY(3 + kUIHeight*2/3); + + if (r.contains(ev.pos)) + { + // same as before + const uint32_t index = 6+i; + fParamGrid[index] = !fParamGrid[index]; + setParameterValue(index, fParamGrid[index] ? 1.0f : 0.0f); + repaint(); + break; + } + } + + return true; + } + + // ------------------------------------------------------------------------------------------------------- + +private: + /** + Our parameters used to display the grid on/off states. + They match the parameters on the plugin side, but here we define them as booleans. + */ + bool fParamGrid[9]; + + /** + Set our UI class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIParameters) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * UI entry point, called by DPF to create a new UI instance. */ + +UI* createUI() +{ + return new ExampleUIParameters(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/Parameters/Makefile b/plugins/Parameters/Makefile new file mode 100644 index 0000000..95644b2 --- /dev/null +++ b/plugins/Parameters/Makefile @@ -0,0 +1,54 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = d_parameters + +# -------------------------------------------------------------- +# Files to build + +OBJS_DSP = \ + ExamplePluginParameters.cpp.o + +OBJS_UI = \ + ExampleUIParameters.cpp.o + +# -------------------------------------------------------------- +# Do some magic + +include ../Makefile.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +ifeq ($(HAVE_DGL),true) +ifeq ($(HAVE_JACK),true) +TARGETS += jack +endif +endif + +ifeq ($(LINUX),true) +ifeq ($(HAVE_DGL),true) +ifeq ($(HAVE_LIBLO),true) +TARGETS += ladspa +TARGETS += dssi +endif +endif +endif + +ifeq ($(HAVE_DGL),true) +TARGETS += lv2_sep +else +TARGETS += lv2_dsp +endif + +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/plugins/Parameters/README.md b/plugins/Parameters/README.md new file mode 100644 index 0000000..36f6d03 --- /dev/null +++ b/plugins/Parameters/README.md @@ -0,0 +1,9 @@ +# Parameters example + +This example will show how parameters work in DPF.
+The plugin will not do any audio processing.
+ +In this example the UI will display a 3x3 grid of colors which can be changed or automated by the host.
+There are 2 colors: blue and orange. Blue means off, orange means on.
+When a grid block is clicked its color will change and the host will receive a parameter change.
+When the host changes a plugin parameter the UI will update accordingly.
diff --git a/plugins/States/DistrhoPluginInfo.h b/plugins/States/DistrhoPluginInfo.h new file mode 100644 index 0000000..bbdeb78 --- /dev/null +++ b/plugins/States/DistrhoPluginInfo.h @@ -0,0 +1,31 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho + * + * 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_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "States" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/States" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 +#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 +#define DISTRHO_PLUGIN_WANT_STATE 1 + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/plugins/States/ExamplePluginStates.cpp b/plugins/States/ExamplePluginStates.cpp new file mode 100644 index 0000000..3e5a019 --- /dev/null +++ b/plugins/States/ExamplePluginStates.cpp @@ -0,0 +1,316 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 Filipe Coelho + * + * 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 + +// ----------------------------------------------------------------------------------------------------------- + +/** + Simple plugin to demonstrate state usage (including UI). + The plugin will be treated as an effect, but it will not change the host audio. + */ +class ExamplePluginStates : public Plugin +{ +public: + ExamplePluginStates() + : Plugin(0, 2, 9) // 0 parameters, 2 programs, 9 states + { + /** + Initialize all our parameters to their defaults. + In this example all default values are false, so we can simply zero them. + */ + std::memset(fParamGrid, 0, sizeof(bool)*9); + } + +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* getLabel() const override + { + return "states"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Simple plugin to demonstrate state usage (including UI).\n\ +The plugin will be treated as an effect, but it will not change the host audio."; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DISTRHO"; + } + + /** + Get the plugin homepage. + */ + const char* getHomePage() const override + { + return "https://github.com/DISTRHO/plugin-examples"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "ISC"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + int64_t getUniqueId() const override + { + return d_cconst('d', 'S', 't', 's'); + } + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + This plugin has no parameters.. + */ + void initParameter(uint32_t, Parameter&) override {} + + /** + Set the name of the program @a index. + This function will be called once, shortly after the plugin is created. + */ + void initProgramName(uint32_t index, String& programName) override + { + switch (index) + { + case 0: + programName = "Default"; + break; + case 1: + programName = "Custom"; + break; + } + } + + /** + Set the state key and default value of @a index. + This function will be called once, shortly after the plugin is created. + */ + void initState(uint32_t index, String& stateKey, String& defaultStateValue) override + { + switch (index) + { + case 0: + stateKey = "top-left"; + break; + case 1: + stateKey = "top-center"; + break; + case 2: + stateKey = "top-right"; + break; + case 3: + stateKey = "middle-left"; + break; + case 4: + stateKey = "middle-center"; + break; + case 5: + stateKey = "middle-right"; + break; + case 6: + stateKey = "bottom-left"; + break; + case 7: + stateKey = "bottom-center"; + break; + case 8: + stateKey = "bottom-right"; + break; + } + + defaultStateValue = "false"; + } + + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + + /** + This plugin has no parameters.. + */ + void setParameterValue(uint32_t, float) override {} + float getParameterValue(uint32_t) const override { return 0.0f; } + + /** + Load a program. + The host may call this function from any context, including realtime processing. + */ + void loadProgram(uint32_t index) override + { + switch (index) + { + case 0: + fParamGrid[0] = false; + fParamGrid[1] = false; + fParamGrid[2] = false; + fParamGrid[3] = false; + fParamGrid[4] = false; + fParamGrid[5] = false; + fParamGrid[6] = false; + fParamGrid[7] = false; + fParamGrid[8] = false; + break; + case 1: + fParamGrid[0] = true; + fParamGrid[1] = true; + fParamGrid[2] = false; + fParamGrid[3] = false; + fParamGrid[4] = true; + fParamGrid[5] = true; + fParamGrid[6] = true; + fParamGrid[7] = false; + fParamGrid[8] = true; + break; + } + } + + /** + Get the value of an internal state. + The host may call this function from any non-realtime context. + */ + String getState(const char* key) const override + { + static const String sTrue ("true"); + static const String sFalse("false"); + + // check which block changed + /**/ if (std::strcmp(key, "top-left") == 0) + return fParamGrid[0] ? sTrue : sFalse; + else if (std::strcmp(key, "top-center") == 0) + return fParamGrid[1] ? sTrue : sFalse; + else if (std::strcmp(key, "top-right") == 0) + return fParamGrid[2] ? sTrue : sFalse; + else if (std::strcmp(key, "middle-left") == 0) + return fParamGrid[3] ? sTrue : sFalse; + else if (std::strcmp(key, "middle-center") == 0) + return fParamGrid[4] ? sTrue : sFalse; + else if (std::strcmp(key, "middle-right") == 0) + return fParamGrid[5] ? sTrue : sFalse; + else if (std::strcmp(key, "bottom-left") == 0) + return fParamGrid[6] ? sTrue : sFalse; + else if (std::strcmp(key, "bottom-center") == 0) + return fParamGrid[7] ? sTrue : sFalse; + else if (std::strcmp(key, "bottom-right") == 0) + return fParamGrid[8] ? sTrue : sFalse; + + return sFalse; + } + + /** + Change an internal state. + */ + void setState(const char* key, const char* value) override + { + const bool valueOnOff = (std::strcmp(value, "true") == 0); + + // check which block changed + /**/ if (std::strcmp(key, "top-left") == 0) + fParamGrid[0] = valueOnOff; + else if (std::strcmp(key, "top-center") == 0) + fParamGrid[1] = valueOnOff; + else if (std::strcmp(key, "top-right") == 0) + fParamGrid[2] = valueOnOff; + else if (std::strcmp(key, "middle-left") == 0) + fParamGrid[3] = valueOnOff; + else if (std::strcmp(key, "middle-center") == 0) + fParamGrid[4] = valueOnOff; + else if (std::strcmp(key, "middle-right") == 0) + fParamGrid[5] = valueOnOff; + else if (std::strcmp(key, "bottom-left") == 0) + fParamGrid[6] = valueOnOff; + else if (std::strcmp(key, "bottom-center") == 0) + fParamGrid[7] = valueOnOff; + else if (std::strcmp(key, "bottom-right") == 0) + fParamGrid[8] = valueOnOff; + } + + /* -------------------------------------------------------------------------------------------------------- + * Process */ + + /** + Run/process function for plugins without MIDI input. + */ + void run(const float** inputs, float** outputs, uint32_t frames) override + { + /** + This plugin does nothing, it just demonstrates parameter usage. + So here we directly copy inputs over outputs, leaving the audio untouched. + We need to be careful in case the host re-uses the same buffer for both ins and outs. + */ + 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: + /** + Our parameters used to display the grid on/off states. + */ + bool fParamGrid[9]; + + + /** + Set our plugin class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExamplePluginStates) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin entry point, called by DPF to create a new plugin instance. */ + +Plugin* createPlugin() +{ + return new ExamplePluginStates(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/States/ExampleUIStates.cpp b/plugins/States/ExampleUIStates.cpp new file mode 100644 index 0000000..d7da8de --- /dev/null +++ b/plugins/States/ExampleUIStates.cpp @@ -0,0 +1,287 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho + * + * 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 + +// ----------------------------------------------------------------------------------------------------------- + +class ExampleUIParameters : public UI +{ +public: + /** + For simplicity this UI will be of constant size. + */ + static const int kUIWidth = 512; + static const int kUIHeight = 512; + + /** + Get key name from an index. + */ + static const char* getStateKeyFromIndex(const uint32_t index) noexcept + { + switch (index) + { + case 0: return "top-left"; + case 1: return "top-center"; + case 2: return "top-right"; + case 3: return "middle-left"; + case 4: return "middle-center"; + case 5: return "middle-right"; + case 6: return "bottom-left"; + case 7: return "bottom-center"; + case 8: return "bottom-right"; + } + + return "unknown"; + } + + /* constructor */ + ExampleUIParameters() + : UI() + { + /** + Initialize the grid to all off per default. + */ + std::memset(fParamGrid, 0, sizeof(bool)*9); + + setSize(kUIWidth, kUIHeight); + } + +protected: + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks */ + + /** + This plugin has no parameters, so we can safely ignore this. + */ + void parameterChanged(uint32_t, float) override {} + + /** + A program has been loaded on the plugin side. + This is called by the host to inform the UI about program changes. + */ + void programLoaded(uint32_t index) override + { + d_stdout("UI programLoaded %i", index); + + switch (index) + { + case 0: + fParamGrid[0] = false; + fParamGrid[1] = false; + fParamGrid[2] = false; + fParamGrid[3] = false; + fParamGrid[4] = false; + fParamGrid[5] = false; + fParamGrid[6] = false; + fParamGrid[7] = false; + fParamGrid[8] = false; + break; + case 1: + fParamGrid[0] = true; + fParamGrid[1] = true; + fParamGrid[2] = false; + fParamGrid[3] = false; + fParamGrid[4] = true; + fParamGrid[5] = true; + fParamGrid[6] = true; + fParamGrid[7] = false; + fParamGrid[8] = true; + break; + } + repaint(); + } + + /** + A state has changed on the plugin side. + This is called by the host to inform the UI about state changes. + */ + void stateChanged(const char* key, const char* value) override + { + const bool valueOnOff = (std::strcmp(value, "true") == 0); + + // check which block changed + /**/ if (std::strcmp(key, "top-left") == 0) + fParamGrid[0] = valueOnOff; + else if (std::strcmp(key, "top-center") == 0) + fParamGrid[1] = valueOnOff; + else if (std::strcmp(key, "top-right") == 0) + fParamGrid[2] = valueOnOff; + else if (std::strcmp(key, "middle-left") == 0) + fParamGrid[3] = valueOnOff; + else if (std::strcmp(key, "middle-center") == 0) + fParamGrid[4] = valueOnOff; + else if (std::strcmp(key, "middle-right") == 0) + fParamGrid[5] = valueOnOff; + else if (std::strcmp(key, "bottom-left") == 0) + fParamGrid[6] = valueOnOff; + else if (std::strcmp(key, "bottom-center") == 0) + fParamGrid[7] = valueOnOff; + else if (std::strcmp(key, "bottom-right") == 0) + fParamGrid[8] = valueOnOff; + + // trigger repaint + repaint(); + } + + /* -------------------------------------------------------------------------------------------------------- + * Widget Callbacks */ + + /** + The OpenGL drawing function. + This UI will draw a 3x3 grid, with on/off states according to plugin state. + */ + void onDisplay() override + { + Rectangle r; + + r.setWidth(kUIWidth/3 - 6); + r.setHeight(kUIHeight/3 - 6); + + // draw left, center and right columns + for (int i=0; i<3; ++i) + { + r.setX(3 + i*kUIWidth/3); + + // top + r.setY(3); + + if (fParamGrid[0+i]) + glColor3f(0.8f, 0.5f, 0.3f); + else + glColor3f(0.3f, 0.5f, 0.8f); + + r.draw(); + + // middle + r.setY(3 + kUIHeight/3); + + if (fParamGrid[3+i]) + glColor3f(0.8f, 0.5f, 0.3f); + else + glColor3f(0.3f, 0.5f, 0.8f); + + r.draw(); + + // bottom + r.setY(3 + kUIHeight*2/3); + + if (fParamGrid[6+i]) + glColor3f(0.8f, 0.5f, 0.3f); + else + glColor3f(0.3f, 0.5f, 0.8f); + + r.draw(); + } + } + + /** + Mouse press event. + This UI will de/activate blocks when you click them and reports it as a state change to the plugin. + */ + bool onMouse(const MouseEvent& ev) override + { + // Test for left-clicked + pressed first. + if (ev.button != 1 || ! ev.press) + return false; + + Rectangle r; + + r.setWidth(kUIWidth/3 - 6); + r.setHeight(kUIHeight/3 - 6); + + // handle left, center and right columns + for (int i=0; i<3; ++i) + { + r.setX(3 + i*kUIWidth/3); + + // top + r.setY(3); + + if (r.contains(ev.pos)) + { + // index that this block applies to + const uint32_t index = 0+i; + + // invert block state + fParamGrid[index] = !fParamGrid[index]; + + // report change to host (and thus plugin) + setState(getStateKeyFromIndex(index), fParamGrid[index] ? "true" : "false"); + + // trigger repaint + repaint(); + break; + } + + // middle + r.setY(3 + kUIHeight/3); + + if (r.contains(ev.pos)) + { + // same as before + const uint32_t index = 3+i; + fParamGrid[index] = !fParamGrid[index]; + setState(getStateKeyFromIndex(index), fParamGrid[index] ? "true" : "false"); + repaint(); + break; + } + + // bottom + r.setY(3 + kUIHeight*2/3); + + if (r.contains(ev.pos)) + { + // same as before + const uint32_t index = 6+i; + fParamGrid[index] = !fParamGrid[index]; + setState(getStateKeyFromIndex(index), fParamGrid[index] ? "true" : "false"); + repaint(); + break; + } + } + + return true; + } + + // ------------------------------------------------------------------------------------------------------- + +private: + /** + Our states used to display the grid. + The host does not know about these. + */ + bool fParamGrid[9]; + + /** + Set our UI class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIParameters) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * UI entry point, called by DPF to create a new UI instance. */ + +UI* createUI() +{ + return new ExampleUIParameters(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/States/Makefile b/plugins/States/Makefile new file mode 100644 index 0000000..c0cf622 --- /dev/null +++ b/plugins/States/Makefile @@ -0,0 +1,53 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = d_states + +# -------------------------------------------------------------- +# Files to build + +OBJS_DSP = \ + ExamplePluginStates.cpp.o + +OBJS_UI = \ + ExampleUIStates.cpp.o + +# -------------------------------------------------------------- +# Do some magic + +include ../Makefile.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +ifeq ($(HAVE_DGL),true) +ifeq ($(HAVE_JACK),true) +TARGETS += jack +endif +endif + +ifeq ($(LINUX),true) +ifeq ($(HAVE_DGL),true) +ifeq ($(HAVE_LIBLO),true) +TARGETS += dssi +endif +endif +endif + +ifeq ($(HAVE_DGL),true) +TARGETS += lv2_sep +else +TARGETS += lv2_dsp +endif + +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/plugins/States/README.md b/plugins/States/README.md new file mode 100644 index 0000000..06f02d6 --- /dev/null +++ b/plugins/States/README.md @@ -0,0 +1,9 @@ +# States example + +This example will show how states work in DPF.
+The plugin will not do any audio processing.
+ +In this example the UI will display a 3x3 grid of colors which can *not* be changed by the host.
+There are 2 colors: blue and orange. Blue means off, orange means on.
+When a grid block is clicked its color will change and the host will receive a message which is auto-saved.
+When the UI is opened it will receive messages indicating the last used block states.