DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 28fc6635bc515680dc28916b9a11c69a444e56a7
parent 9d09b5e15b314eba3b96fdd70171e3f1ad1f0072
Author: falkTX <falktx@falktx.com>
Date:   Mon,  9 Mar 2020 19:40:26 +0000

Add simple file handling example, WIP

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
Aexamples/FileHandling/DistrhoPluginInfo.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/FileHandling/FileHandlingPlugin.cpp | 257+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/FileHandling/FileHandlingUI.cpp | 269+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/FileHandling/Makefile | 46++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/FileHandling/NanoButton.cpp | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/FileHandling/NanoButton.hpp | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 783 insertions(+), 0 deletions(-)

diff --git a/examples/FileHandling/DistrhoPluginInfo.h b/examples/FileHandling/DistrhoPluginInfo.h @@ -0,0 +1,47 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED +#define DISTRHO_PLUGIN_INFO_H_INCLUDED + +#define DISTRHO_PLUGIN_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "FileHandling" +#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/FileHandling" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 1 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 1 +#define DISTRHO_PLUGIN_WANT_STATE 1 +#define DISTRHO_PLUGIN_WANT_STATEFILES 1 +#define DISTRHO_UI_USER_RESIZABLE 1 +#define DISTRHO_UI_USE_NANOVG 1 + +enum Parameters { + kParameterFileSize1 = 0, + kParameterFileSize2, + kParameterFileSize3, + kParameterCount +}; + +enum States { + kStateFile1 = 0, + kStateFile2, + kStateFile3, + kStateCount +}; + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/examples/FileHandling/FileHandlingPlugin.cpp b/examples/FileHandling/FileHandlingPlugin.cpp @@ -0,0 +1,257 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPlugin.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------------------------------------------- + +/** + Plugin to demonstrate File handling within DPF. + */ +class FileHandlingExamplePlugin : public Plugin +{ +public: + FileHandlingExamplePlugin() + : Plugin(kParameterCount, 0, kStateCount) + { + std::memset(fParameters, 0, sizeof(fParameters)); + } + +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 "FileHandling"; + } + + /** + Get an extensive comment/description about the plugin. + */ + const char* getDescription() const override + { + return "Plugin to demonstrate File handling."; + } + + /** + 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/DPF"; + } + + /** + 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(0, 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', 'F', 'i', 'H'); + } + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize the parameter @a index. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& param) override + { + param.hints = kParameterIsOutput|kParameterIsInteger; + + switch (index) + { + case kParameterFileSize1: + param.name = "Size #1"; + param.symbol = "size1"; + break; + case kParameterFileSize2: + param.name = "Size #2"; + param.symbol = "size2"; + break; + case kParameterFileSize3: + param.name = "Size #3"; + param.symbol = "size3"; + break; + } + } + + /** + Set the state key and default value of @a index.@n + This function will be called once, shortly after the plugin is created.@n + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. + */ + void initState(uint32_t index, String& stateKey, String& defaultStateValue) override + { + switch (index) + { + case kStateFile1: + stateKey = "file1"; + break; + case kStateFile2: + stateKey = "file2"; + break; + case kStateFile3: + stateKey = "file3"; + break; + } + + defaultStateValue = ""; + } + + /** + TODO API under construction + */ + bool isStateFile(uint32_t index) override + { + switch (index) + { + case kStateFile1: + case kStateFile2: + case kStateFile3: + return true; + } + + return false; + } + + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter. + The host may call this function from any context, including realtime processing. + We have no parameters in this plugin example, so we do nothing with the function. + */ + float getParameterValue(uint32_t index) const override + { + return fParameters[index]; + } + + /** + Change a parameter value.@n + The host may call this function from any context, including realtime processing. + + This function will only be called for parameter inputs. + Since we have no parameters inputs in this example, so we do nothing with the function. + */ + void setParameterValue(uint32_t, float) override {} + + /** + Change an internal state @a key to @a value. + */ + void setState(const char* key, const char* value) override + { + d_stdout("DSP setState %s %s", key, value); + int fileId = -1; + + /**/ if (std::strcmp(key, "file1") == 0) + fileId = 0; + else if (std::strcmp(key, "file2") == 0) + fileId = 1; + else if (std::strcmp(key, "file3") == 0) + fileId = 2; + + if (fileId == -1) + return; + + if (FILE* const fh = fopen(value, "r")) + { + fseek(fh, 0, SEEK_END); + + // filesize + const long int size = ftell(fh); + d_stdout("size of %s is %li", value, size); + fParameters[kParameterFileSize1 + fileId] = static_cast<float>(size) / 1000.0f; + + fclose(fh); + } + } + + /* -------------------------------------------------------------------------------------------------------- + * 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 doesn't do audio, it just demonstrates file handling 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); + } + + // ------------------------------------------------------------------------------------------------------- + +private: + 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(FileHandlingExamplePlugin) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin entry point, called by DPF to create a new plugin instance. */ + +Plugin* createPlugin() +{ + return new FileHandlingExamplePlugin(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/examples/FileHandling/FileHandlingUI.cpp b/examples/FileHandling/FileHandlingUI.cpp @@ -0,0 +1,269 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoUI.hpp" + +#include "extra/String.hpp" + +#include "DistrhoPluginInfo.h" +#include "NanoButton.hpp" + +START_NAMESPACE_DISTRHO + +const char* kStateKeys[kStateCount] = { + "file1", + "file2", + "file3", +}; + +// ----------------------------------------------------------------------------------------------------------- + +static void setupButton(Button& btn, int y) +{ + btn.setAbsolutePos(5, y); + btn.setLabel("Open..."); + btn.setSize(100, 30); +} + +class FileHandlingExampleUI : public UI, + public Button::Callback +{ +public: + static const uint kInitialWidth = 600; + static const uint kInitialHeight = 350; + + FileHandlingExampleUI() + : UI(kInitialWidth, kInitialHeight), + fButton1(this, this), + fButton2(this, this), + fButton3(this, this), + fScale(1.0f) + { + std::memset(fParameters, 0, sizeof(fParameters)); + std::memset(fStrBuf, 0, sizeof(fStrBuf)); + + setupButton(fButton1, 5); + setupButton(fButton2, 105); + setupButton(fButton3, 205); + +#ifdef DGL_NO_SHARED_RESOURCES + createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); +#else + loadSharedResources(); +#endif + + setGeometryConstraints(kInitialWidth, kInitialHeight, true); + } + +protected: + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks */ + + /** + A parameter has changed on the plugin side.@n + 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(); + } + + /** + A state has changed on the plugin side.@n + This is called by the host to inform the UI about state changes. + */ + void stateChanged(const char* key, const char* value) override + { + States stateId = kStateCount; + + /**/ if (std::strcmp(key, "file1") == 0) + stateId = kStateFile1; + else if (std::strcmp(key, "file2") == 0) + stateId = kStateFile2; + else if (std::strcmp(key, "file3") == 0) + stateId = kStateFile3; + + if (stateId == kStateCount) + return; + + fState[stateId] = value; + repaint(); + } + + /* -------------------------------------------------------------------------------------------------------- + * Widget Callbacks */ + + /** + The NanoVG drawing function. + */ + void onNanoDisplay() override + { + const float lineHeight = 20 * fScale; + float y; + + fontSize(15.0f * fScale); + textLineHeight(lineHeight); + + // --------------------------------------------------------------------------------------- + // File 1 + + y = 45.0f * fScale; + + if (fState[kStateFile1].isNotEmpty()) + { + drawLeft(0.0f, y, "Name:"); + drawRight(0.0f, y, fState[kStateFile1]); + y += lineHeight; + + drawLeft(0.0f, y, "Size:"); + drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize1])); + y += lineHeight; + } + else + { + drawLeft(0.0f, y, "No file loaded"); + } + + // --------------------------------------------------------------------------------------- + // File 2 + + y = 145.0f * fScale; + + if (fState[kStateFile2].isNotEmpty()) + { + drawLeft(0.0f, y, "Name:"); + drawRight(0.0f, y, fState[kStateFile2]); + y += lineHeight; + + drawLeft(0.0f, y, "Size:"); + drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize2])); + y += lineHeight; + } + else + { + drawLeft(0.0f, y, "No file loaded"); + } + + // --------------------------------------------------------------------------------------- + // File 3 + + y = 245.0f * fScale; + + if (fState[kStateFile3].isNotEmpty()) + { + drawLeft(0.0f, y, "Name:"); + drawRight(0.0f, y, fState[kStateFile3]); + y += lineHeight; + + drawLeft(0.0f, y, "Size:"); + drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize3])); + y += lineHeight; + } + else + { + drawLeft(0.0f, y, "No file loaded"); + } + } + + void onResize(const ResizeEvent& ev) override + { + fScale = static_cast<float>(ev.size.getHeight())/kInitialHeight; + + UI::onResize(ev); + } + + void buttonClicked(Button* const button, bool) override + { + States stateId = kStateCount; + + /**/ if (button == &fButton1) + stateId = kStateFile1; + else if (button == &fButton2) + stateId = kStateFile2; + else if (button == &fButton3) + stateId = kStateFile3; + + if (stateId == kStateCount) + return; + + requestStateFile(kStateKeys[stateId]); + } + + // ------------------------------------------------------------------------------------------------------- + +private: + // Parameters + float fParameters[kParameterCount]; + + // State (files) + String fState[kStateCount]; + Button fButton1, fButton2, fButton3; + + // UI stuff + float fScale; + + // temp buf for text + char fStrBuf[0xff]; + + // helpers for putting text into fStrBuf and returning it + const char* getTextBufFileSize(const float value) + { + /**/ if (value > 1024*1024) + std::snprintf(fStrBuf, 0xfe, "%.2f GiB", value/(1024*1024)); + else if (value > 1024) + std::snprintf(fStrBuf, 0xfe, "%.2f MiB", value/1024); + else + std::snprintf(fStrBuf, 0xfe, "%.2f KiB", value); + 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 * fScale, 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 * fScale), y, (kInitialWidth - x) * fScale, text); + closePath(); + } + + /** + Set our UI class as non-copyable and add a leak detector just in case. + */ + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FileHandlingExampleUI) +}; + +/* ------------------------------------------------------------------------------------------------------------ + * UI entry point, called by DPF to create a new UI instance. */ + +UI* createUI() +{ + return new FileHandlingExampleUI(); +} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/examples/FileHandling/Makefile b/examples/FileHandling/Makefile @@ -0,0 +1,46 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = d_files + +# -------------------------------------------------------------- +# Files to build + +FILES_DSP = \ + FileHandlingPlugin.cpp + +FILES_UI = \ + FileHandlingUI.cpp \ + NanoButton.cpp + +# -------------------------------------------------------------- +# Do some magic + +include ../../Makefile.plugins.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +ifeq ($(HAVE_JACK),true) +ifeq ($(HAVE_OPENGL),true) +TARGETS += jack +endif +endif + +ifeq ($(HAVE_OPENGL),true) +TARGETS += lv2_sep +else +TARGETS += lv2_dsp +endif + +TARGETS += vst + +all: $(TARGETS) + +# -------------------------------------------------------------- diff --git a/examples/FileHandling/NanoButton.cpp b/examples/FileHandling/NanoButton.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2018-2019 Rob van den Berg <rghvdberg at gmail dot org> + * + * This file is part of CharacterCompressor + * + * Nnjas2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CharacterCompressor is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CharacterCompressor. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "NanoButton.hpp" +#include "Window.hpp" + +START_NAMESPACE_DISTRHO + +Button::Button(Widget *parent, Callback *cb) + : NanoWidget(parent), + fCallback(cb), + buttonActive(false) +{ + loadSharedResources(); + fNanoFont = findFont(NANOVG_DEJAVU_SANS_TTF); + labelColor = Color(255, 255, 255); + backgroundColor = Color(32,32,32); + Label = "button"; +} + +void Button::onNanoDisplay() +{ + auto w = getWidth(); + auto h = getHeight(); + auto margin = 1.0f; + + // Background + beginPath(); + fillColor(backgroundColor); + strokeColor(borderColor); + rect(margin, margin, w - 2 * margin, h-2*margin); + fill(); + stroke(); + closePath(); + + //Label + beginPath(); + fontFaceId(fNanoFont); + fontSize(14); + fillColor(labelColor); + Rectangle<float> bounds; + textBounds(0, 0, Label.c_str(), NULL, bounds); + // float tw = bounds.getWidth(); + // float th = bounds.getHeight(); + float tx = w / 2.0f ; + float ty = h / 2.0f; + textAlign(ALIGN_CENTER | ALIGN_MIDDLE); + + fillColor(255, 255, 255, 255); + text(tx, ty, Label.c_str(), NULL); + closePath(); +} + +void Button::setLabel(std::string label) +{ + Label = label; +} + +void Button::setLabelColor(const Color color) +{ + labelColor = color; + borderColor = color; +} +void Button::setBackgroundColor(const Color color) +{ + backgroundColor = color; +} + +bool Button::onMouse(const MouseEvent &ev) +{ + if (ev.press & contains(ev.pos)) + { + buttonActive = true; + setLabelColor(labelColor); + fCallback->buttonClicked(this, true); + return true; + } + else if (buttonActive) + { + buttonActive = false; + //setLabelColor(Color(128,128,128)); + return true; + } + + return false; +} + +END_NAMESPACE_DISTRHO diff --git a/examples/FileHandling/NanoButton.hpp b/examples/FileHandling/NanoButton.hpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018-2019 Rob van den Berg <rghvdberg at gmail dot org> + * + * This file is part of CharacterCompressor + * + * Nnjas2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CharacterCompressor is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CharacterCompressor. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BUTTON_HPP_INCLUDED +#define BUTTON_HPP_INCLUDED + +#include "Widget.hpp" +#include "NanoVG.hpp" + +#include <string> + +START_NAMESPACE_DISTRHO + +class Button : public NanoWidget +{ +public: + class Callback + { + public: + virtual ~Callback() {} + virtual void buttonClicked(Button *button, bool value) = 0; + }; + explicit Button(Widget *parent, Callback *cb); + + void setLabel(std::string label); + void setLabelColor(Color color); + void setBackgroundColor(Color color); + +protected: + void onNanoDisplay() override; + bool onMouse(const MouseEvent &ev) override; + +private: + std::string Label; + Color labelColor,backgroundColor,borderColor; + Callback *const fCallback; + bool buttonActive; + FontId fNanoFont; + DISTRHO_LEAK_DETECTOR(Button) +}; + +END_NAMESPACE_DISTRHO + +#endif