/* * DISTRHO Cardinal Plugin * Copyright (C) 2021-2022 Filipe Coelho * * This program 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 any later version. * * This program 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. * * For a full copy of the GNU General Public License see the LICENSE file. */ /** * This file contains a substantial amount of code from VCVRack, adjusted for inline use * Copyright (C) 2016-2021 VCV. * * This program 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. */ #pragma once #include #include #include #include #include #include #include #include struct NVGcolor { float a; }; struct NVGpaint {}; inline NVGcolor nvgRGB(int r, int g, int b) { return {}; } inline NVGcolor nvgRGBA(int r, int g, int b, int a) { return {}; } inline NVGcolor nvgRGBf(float r, float g, float b) { return {}; } inline NVGcolor nvgRGBAf(float r, float g, float b, float a) { return {}; } inline void nvgBeginPath(void* vg) {} inline void nvgFillColor(void* vg, NVGcolor) {} inline void nvgFillPaint(void* vg, NVGpaint) {} inline void nvgFill(void* vg) {} inline void nvgStrokeColor(void* vg, NVGcolor) {} inline void nvgStrokeWidth(void* vg, float) {} inline void nvgStroke(void* vg) {} inline void nvgRect(void* vg, float a, float b, float c, float d) {} inline void nvgImageSize(void*, int, void*, void*) {} inline NVGpaint nvgImagePattern(void*, float, float, float, float, float, int handle, float) { return {}; } struct json_t {}; json_t* json_integer(int) { return NULL; } json_t* json_object() { return NULL; } json_t* json_object_get(json_t*, const char*) { return NULL; } int json_integer_value(json_t*) { return 0; } void json_object_set_new(json_t*, const char*, json_t*) {} namespace rack { struct Quantity { virtual ~Quantity() {} virtual void setValue(float value) {} virtual float getValue() { return 0.f; } virtual float getMinValue() { return 0.f; } virtual float getMaxValue() { return 1.f; } virtual float getDefaultValue() { return 0.f; } // virtual float getDisplayValue(); // virtual void setDisplayValue(float displayValue); // virtual int getDisplayPrecision(); // virtual std::string getDisplayValueString(); // virtual void setDisplayValueString(std::string s); virtual std::string getLabel() { return ""; } virtual std::string getUnit() { return ""; } // virtual std::string getString(); // virtual void reset(); // virtual void randomize(); // bool isMin(); // bool isMax(); // void setMin(); // void setMax(); // void toggle(); // void moveValue(float deltaValue); // float getRange(); // bool isBounded(); // float toScaled(float value); // float fromScaled(float scaledValue); // void setScaledValue(float scaledValue); // float getScaledValue(); // void moveScaledValue(float deltaScaledValue); }; namespace ui { struct Menu; } namespace math { inline int clamp(int x, int a, int b) { return std::max(std::min(x, b), a); } inline float clamp(float x, float a = 0.f, float b = 1.f) { return std::fmax(std::fmin(x, b), a); } struct Vec { float x = 0.f; float y = 0.f; Vec() {} Vec(float xy) : x(xy), y(xy) {} Vec(float x, float y) : x(x), y(y) {} Vec neg() const { return Vec(-x, -y); } Vec plus(Vec b) const { return Vec(x + b.x, y + b.y); } Vec minus(Vec b) const { return Vec(x - b.x, y - b.y); } Vec mult(float s) const { return Vec(x * s, y * s); } Vec mult(Vec b) const { return Vec(x * b.x, y * b.y); } }; struct Rect { Vec pos; Vec size; }; } // namespace math namespace engine { static constexpr const int PORT_MAX_CHANNELS = 16; struct Module; struct Engine { float getSampleRate() { return sampleRate; } // custom float sampleRate = 0.f; }; struct Light { float value = 0.f; void setBrightness(float brightness) { value = brightness; } float getBrightness() { return value; } void setBrightnessSmooth(float brightness, float deltaTime, float lambda = 30.f) { if (brightness < value) { // Fade out light value += (brightness - value) * lambda * deltaTime; } else { // Immediately illuminate light value = brightness; } } void setSmoothBrightness(float brightness, float deltaTime) { setBrightnessSmooth(brightness, deltaTime); } void setBrightnessSmooth(float brightness, int frames = 1) { setBrightnessSmooth(brightness, frames / 44100.f); } }; struct Param { float value = 0.f; float getValue() { return value; } void setValue(float value) { this->value = value; } }; struct Port { union { float voltages[PORT_MAX_CHANNELS] = {}; float value; }; union { uint8_t channels = 0; uint8_t active; }; Light plugLights[3]; enum Type { INPUT, OUTPUT, }; void setVoltage(float voltage, int channel = 0) { voltages[channel] = voltage; } float getVoltage(int channel = 0) { return voltages[channel]; } float getPolyVoltage(int channel) { return isMonophonic() ? getVoltage(0) : getVoltage(channel); } float getNormalVoltage(float normalVoltage, int channel = 0) { return isConnected() ? getVoltage(channel) : normalVoltage; } float getNormalPolyVoltage(float normalVoltage, int channel) { return isConnected() ? getPolyVoltage(channel) : normalVoltage; } float* getVoltages(int firstChannel = 0) { return &voltages[firstChannel]; } void readVoltages(float* v) { for (int c = 0; c < channels; c++) { v[c] = voltages[c]; } } void writeVoltages(const float* v) { for (int c = 0; c < channels; c++) { voltages[c] = v[c]; } } void clearVoltages() { for (int c = 0; c < channels; c++) { voltages[c] = 0.f; } } float getVoltageSum() { float sum = 0.f; for (int c = 0; c < channels; c++) { sum += voltages[c]; } return sum; } float getVoltageRMS() { if (channels == 0) { return 0.f; } else if (channels == 1) { return std::fabs(voltages[0]); } else { float sum = 0.f; for (int c = 0; c < channels; c++) { sum += std::pow(voltages[c], 2); } return std::sqrt(sum); } } // template // T getVoltageSimd(int firstChannel) { // return T::load(&voltages[firstChannel]); // } // // template // T getPolyVoltageSimd(int firstChannel) { // return isMonophonic() ? getVoltage(0) : getVoltageSimd(firstChannel); // } // // template // T getNormalVoltageSimd(T normalVoltage, int firstChannel) { // return isConnected() ? getVoltageSimd(firstChannel) : normalVoltage; // } // // template // T getNormalPolyVoltageSimd(T normalVoltage, int firstChannel) { // return isConnected() ? getPolyVoltageSimd(firstChannel) : normalVoltage; // } // // template // void setVoltageSimd(T voltage, int firstChannel) { // voltage.store(&voltages[firstChannel]); // } void setChannels(int channels) { if (this->channels == 0) { return; } for (int c = channels; c < this->channels; c++) { voltages[c] = 0.f; } if (channels == 0) { channels = 1; } this->channels = channels; } int getChannels() { return channels; } bool isConnected() { return channels > 0; } bool isMonophonic() { return channels == 1; } bool isPolyphonic() { return channels > 1; } float normalize(float normalVoltage) { return getNormalVoltage(normalVoltage); } }; struct Output : Port {}; struct Input : Port {}; struct PortInfo { Module* module = NULL; Port::Type type = Port::INPUT; int portId = -1; std::string name; std::string description; virtual ~PortInfo() {} virtual std::string getName() { if (name == "") return std::string("#") + std::to_string(portId + 1); return name; } std::string getFullName() { std::string name = getName(); name += " "; name += (type == Port::INPUT) ? "input" : "output"; return name; } virtual std::string getDescription() { return description; } }; struct ParamQuantity : Quantity { Module* module = NULL; int paramId = -1; float minValue = 0.f; float maxValue = 1.f; float defaultValue = 0.f; std::string name; std::string unit; float displayBase = 0.f; float displayMultiplier = 1.f; float displayOffset = 0.f; int displayPrecision = 5; std::string description; bool resetEnabled = true; bool randomizeEnabled = true; bool smoothEnabled = false; bool snapEnabled = false; // Param* getParam(); // /** If smoothEnabled is true, requests to the engine to smoothly move to a target value each sample. */ // void setSmoothValue(float value); // float getSmoothValue(); // void setValue(float value) override; // float getValue() override; float getMinValue() override { return minValue; } float getMaxValue() override { return maxValue; } float getDefaultValue() override { return defaultValue; } // float getDisplayValue() override; // void setDisplayValue(float displayValue) override; // std::string getDisplayValueString() override; // void setDisplayValueString(std::string s) override; // int getDisplayPrecision() override; // std::string getLabel() override; // std::string getUnit() override; // void reset() override; // void randomize() override; virtual std::string getDescription() { return description; } // virtual json_t* toJson(); // virtual void fromJson(json_t* rootJ); }; struct SwitchQuantity : ParamQuantity { // std::vector labels; // std::string getDisplayValueString() override; // void setDisplayValueString(std::string s) override; }; struct Module { std::vector params; std::vector inputs; std::vector outputs; std::vector lights; std::vector paramQuantities; std::vector inputInfos; std::vector outputInfos; // std::vector lightInfos; virtual ~Module() { for (ParamQuantity* paramQuantity : paramQuantities) { if (paramQuantity) delete paramQuantity; } for (PortInfo* inputInfo : inputInfos) { if (inputInfo) delete inputInfo; } for (PortInfo* outputInfo : outputInfos) { if (outputInfo) delete outputInfo; } // for (LightInfo* lightInfo : lightInfos) { // if (lightInfo) // delete lightInfo; // } } void config(int numParams, int numInputs, int numOutputs, int numLights = 0) { // // This method should only be called once. // assert(params.empty() && inputs.empty() && outputs.empty() && lights.empty() && paramQuantities.empty()); params.resize(numParams); inputs.resize(numInputs); outputs.resize(numOutputs); lights.resize(numLights); paramQuantities.resize(numParams); for (int i = 0; i < numParams; i++) { configParam(i, 0.f, 1.f, 0.f); } inputInfos.resize(numInputs); for (int i = 0; i < numInputs; i++) { configInput(i); } outputInfos.resize(numOutputs); for (int i = 0; i < numOutputs; i++) { configOutput(i); } // lightInfos.resize(numLights); } template TParamQuantity* configParam(int paramId, float minValue, float maxValue, float defaultValue, std::string name = "", std::string unit = "", float displayBase = 0.f, float displayMultiplier = 1.f, float displayOffset = 0.f) { // assert(paramId < (int) params.size() && paramId < (int) paramQuantities.size()); if (paramQuantities[paramId]) delete paramQuantities[paramId]; TParamQuantity* q = new TParamQuantity; q->ParamQuantity::module = this; q->ParamQuantity::paramId = paramId; q->ParamQuantity::minValue = minValue; q->ParamQuantity::maxValue = maxValue; q->ParamQuantity::defaultValue = defaultValue; q->ParamQuantity::name = name; q->ParamQuantity::unit = unit; q->ParamQuantity::displayBase = displayBase; q->ParamQuantity::displayMultiplier = displayMultiplier; q->ParamQuantity::displayOffset = displayOffset; paramQuantities[paramId] = q; Param* p = ¶ms[paramId]; p->value = q->getDefaultValue(); return q; } template TSwitchQuantity* configSwitch(int paramId, float minValue, float maxValue, float defaultValue, std::string name = "", std::vector labels = {}) { TSwitchQuantity* sq = configParam(paramId, minValue, maxValue, defaultValue, name); sq->labels = labels; return sq; } template TSwitchQuantity* configButton(int paramId, std::string name = "") { TSwitchQuantity* sq = configParam(paramId, 0.f, 1.f, 0.f, name); sq->randomizeEnabled = false; return sq; } template TPortInfo* configInput(int portId, std::string name = "") { // assert(portId < (int) inputs.size() && portId < (int) inputInfos.size()); if (inputInfos[portId]) delete inputInfos[portId]; TPortInfo* info = new TPortInfo; info->PortInfo::module = this; info->PortInfo::type = Port::INPUT; info->PortInfo::portId = portId; info->PortInfo::name = name; inputInfos[portId] = info; return info; } template TPortInfo* configOutput(int portId, std::string name = "") { // assert(portId < (int) outputs.size() && portId < (int) outputInfos.size()); if (outputInfos[portId]) delete outputInfos[portId]; TPortInfo* info = new TPortInfo; info->PortInfo::module = this; info->PortInfo::type = Port::OUTPUT; info->PortInfo::portId = portId; info->PortInfo::name = name; outputInfos[portId] = info; return info; } // template // TLightInfo* configLight(int lightId, std::string name = "") { // assert(lightId < (int) lights.size() && lightId < (int) lightInfos.size()); // if (lightInfos[lightId]) // delete lightInfos[lightId]; // // TLightInfo* info = new TLightInfo; // info->LightInfo::module = this; // info->LightInfo::lightId = lightId; // info->LightInfo::name = name; // lightInfos[lightId] = info; // return info; // } void configBypass(int inputId, int outputId) { // assert(inputId < (int) inputs.size()); // assert(outputId < (int) outputs.size()); // // Check that output is not yet routed // for (BypassRoute& br : bypassRoutes) { // assert(br.outputId != outputId); // } // // BypassRoute br; // br.inputId = inputId; // br.outputId = outputId; // bypassRoutes.push_back(br); } int getNumParams() { return params.size(); } Param& getParam(int index) { return params[index]; } int getNumInputs() { return inputs.size(); } Input& getInput(int index) { return inputs[index]; } int getNumOutputs() { return outputs.size(); } Output& getOutput(int index) { return outputs[index]; } int getNumLights() { return lights.size(); } Light& getLight(int index) { return lights[index]; } ParamQuantity* getParamQuantity(int index) { return paramQuantities[index]; } PortInfo* getInputInfo(int index) { return inputInfos[index]; } PortInfo* getOutputInfo(int index) { return outputInfos[index]; } // LightInfo* getLightInfo(int index) { return lightInfos[index]; } struct ProcessArgs { float sampleRate; float sampleTime; int64_t frame; }; virtual void process(const ProcessArgs& args) { step(); } virtual void step() {} // virtual void processBypass(const ProcessArgs& args); // virtual json_t* toJson(); // virtual void fromJson(json_t* rootJ); /** Serializes the "params" object. */ // virtual json_t* paramsToJson(); // virtual void paramsFromJson(json_t* rootJ); virtual json_t* dataToJson() { return NULL; } virtual void dataFromJson(json_t* rootJ) {} struct SampleRateChangeEvent { float sampleRate; float sampleTime; }; virtual void onSampleRateChange(const SampleRateChangeEvent& e) { onSampleRateChange(); } struct ResetEvent {}; virtual void onReset(const ResetEvent& e) {} // TODO virtual void onAdd() {} virtual void onRemove() {} virtual void onReset() {} virtual void onRandomize() {} virtual void onSampleRateChange() {} // private void doProcess(const ProcessArgs& args) { // if (!internal->bypassed) process(args); // else // processBypass(args); // if (args.frame % PORT_DIVIDER == 0) { // float portTime = args.sampleTime * PORT_DIVIDER; // for (Input& input : inputs) { // Port_step(&input, portTime); // } // for (Output& output : outputs) { // Port_step(&output, portTime); // } // } } }; } // namespace engine namespace widget { struct BaseEvent { }; struct Widget { math::Rect box; Widget* parent = NULL; std::list children; bool visible = true; bool requestedDelete = false; using BaseEvent = widget::BaseEvent; struct ActionEvent : BaseEvent {}; virtual void onAction(const ActionEvent& e) {} struct ChangeEvent : BaseEvent {}; virtual void onChange(const ChangeEvent& e) {} bool hasChild(Widget* child) { return false; } void addChild(Widget* child) {} void addChildBottom(Widget* child) {} void addChildBelow(Widget* child, Widget* sibling) {} void addChildAbove(Widget* child, Widget* sibling) {} void removeChild(Widget* child) {} void clearChildren() {} virtual void step() {} struct DrawArgs { void* vg = NULL; math::Rect clipBox; void* fb = NULL; }; virtual void draw(const DrawArgs& args); }; struct OpaqueWidget : Widget { }; struct SvgWidget : Widget { void wrap() {} void setSvg(void* svg) {} }; struct TransparentWidget : Widget { }; } // namespace widget namespace app { static constexpr const float RACK_GRID_WIDTH = 15; static constexpr const float RACK_GRID_HEIGHT = 380; // static constexpr const math::Vec RACK_GRID_SIZE = math::Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT); // static constexpr const math::Vec RACK_OFFSET = RACK_GRID_SIZE.mult(math::Vec(2000, 100)); struct CircularShadow : widget::TransparentWidget { float blurRadius; float opacity; }; struct LightWidget : widget::TransparentWidget { NVGcolor bgColor, color, borderColor; }; struct ModuleWidget : widget::OpaqueWidget { // plugin::Model* model = NULL; engine::Module* module = NULL; void setModel(void*) {} void setModule(void*) {} void setPanel(void*) {} void addParam(void*) {} void addInput(void*) {} void addOutput(void*) {} virtual void appendContextMenu(ui::Menu* menu) {} }; struct MultiLightWidget : LightWidget { // std::vector baseColors; // int getNumColors(); void addBaseColor(NVGcolor baseColor) {} // void setBrightnesses(const std::vector& brightnesses); }; struct ModuleLightWidget : MultiLightWidget { // engine::Module* module = NULL; // int firstLightId = -1; // ModuleLightWidget(); // ~ModuleLightWidget(); // engine::Light* getLight(int colorId); // engine::LightInfo* getLightInfo(); // void createTooltip(); // void destroyTooltip(); }; struct ParamWidget : widget::OpaqueWidget { engine::Module* module = NULL; int paramId = -1; virtual void initParamQuantity() {} engine::ParamQuantity* getParamQuantity() { return module ? module->paramQuantities[paramId] : NULL; } void createTooltip() {} void destroyTooltip() {} void createContextMenu(); virtual void appendContextMenu(void* menu) {} void resetAction(); }; struct PortWidget : widget::OpaqueWidget { }; struct Knob : ParamWidget { bool horizontal = false; bool smooth = true; bool snap = false; float speed = 1.f; bool forceLinear = false; float minAngle = -M_PI; float maxAngle = M_PI; }; struct SliderKnob : Knob { }; struct Switch : ParamWidget { bool momentary = false; }; struct SvgKnob : Knob { CircularShadow* shadow; void setSvg(void* svg) {} }; struct SvgPanel : widget::Widget { // widget::FramebufferWidget* fb; // widget::SvgWidget* sw; // PanelBorder* panelBorder; void setBackground(void* svg) {} }; struct SvgPort : PortWidget { // widget::FramebufferWidget* fb; CircularShadow* shadow; // widget::SvgWidget* sw; void setSvg(void* svg) {} }; struct SvgScrew : widget::Widget { // widget::FramebufferWidget* fb; widget::SvgWidget* sw; void setSvg(void* svg) {} }; struct SvgSlider : app::SliderKnob { // widget::FramebufferWidget* fb; widget::SvgWidget* background; // widget::SvgWidget* handle; math::Vec minHandlePos, maxHandlePos; void setBackgroundSvg(void* svg) {} void setHandleSvg(void* svg) {} void setHandlePos(math::Vec minHandlePos, math::Vec maxHandlePos) {} void setHandlePosCentered(math::Vec minHandlePosCentered, math::Vec maxHandlePosCentered) {} }; struct SvgSwitch : Switch { // widget::FramebufferWidget* fb; // CircularShadow* shadow; // widget::SvgWidget* sw; // std::vector> frames; bool latch = false; void addFrame(void* svg) {} }; } // namespace app namespace asset { const char* plugin(void* instance, const char* path) { return NULL; } } // namespace asset namespace componentlibrary { static constexpr const NVGcolor SCHEME_LIGHT_GRAY = {}; template struct TSvgLight : TBase { // widget::FramebufferWidget* fb; // widget::SvgWidget* sw; void setSvg(void* svg) {} }; using SvgLight = TSvgLight<>; template struct TGrayModuleLightWidget : TBase { }; using GrayModuleLightWidget = TGrayModuleLightWidget<>; template struct TWhiteLight : TBase { }; using WhiteLight = TWhiteLight<>; template struct TRedLight : TBase { }; using RedLight = TRedLight<>; template struct TGreenLight : TBase { }; using GreenLight = TGreenLight<>; template struct TBlueLight : TBase { }; using BlueLight = TBlueLight<>; template struct TYellowLight : TBase { }; using YellowLight = TYellowLight<>; template struct TGreenRedLight : TBase { }; using GreenRedLight = TGreenRedLight<>; template struct TRedGreenBlueLight : TBase { }; using RedGreenBlueLight = TRedGreenBlueLight<>; template struct LargeLight : TSvgLight { }; template struct MediumLight : TSvgLight { }; template struct SmallLight : TSvgLight { }; template struct TinyLight : TSvgLight { }; struct ScrewBlack : app::SvgScrew { }; } // namespace componentlibrary namespace dsp { inline float sinc(float x) { if (x == 0.f) return 1.f; x *= M_PI; return std::sin(x) / x; } // template // T sinc(T x) { // T zeromask = (x == 0.f); // x *= M_PI; // x = simd::sin(x) / x; // return simd::ifelse(zeromask, 1.f, x); // } template inline T blackmanHarris(T p) { return + T(0.35875) - T(0.48829) * std::cos(2 * T(M_PI) * p) + T(0.14128) * std::cos(4 * T(M_PI) * p) - T(0.01168) * std::cos(6 * T(M_PI) * p); } inline void blackmanHarrisWindow(float* x, int len) { for (int i = 0; i < len; i++) { x[i] *= blackmanHarris(float(i) / (len - 1)); } } inline void boxcarLowpassIR(float* out, int len, float cutoff = 0.5f) { for (int i = 0; i < len; i++) { float t = i - (len - 1) / 2.f; out[i] = 2 * cutoff * sinc(2 * cutoff * t); } } template struct Decimator { T inBuffer[OVERSAMPLE * QUALITY]; float kernel[OVERSAMPLE * QUALITY]; int inIndex; Decimator(float cutoff = 0.9f) { boxcarLowpassIR(kernel, OVERSAMPLE * QUALITY, cutoff * 0.5f / OVERSAMPLE); blackmanHarrisWindow(kernel, OVERSAMPLE * QUALITY); reset(); } void reset() { inIndex = 0; std::memset(inBuffer, 0, sizeof(inBuffer)); } T process(T* in) { std::memcpy(&inBuffer[inIndex], in, OVERSAMPLE * sizeof(T)); inIndex += OVERSAMPLE; inIndex %= OVERSAMPLE * QUALITY; T out = 0.f; for (int i = 0; i < OVERSAMPLE * QUALITY; i++) { int index = inIndex - 1 - i; index = (index + OVERSAMPLE * QUALITY) % (OVERSAMPLE * QUALITY); out += kernel[i] * inBuffer[index]; } return out; } }; struct PulseGenerator { float remaining = 0.f; void reset() { remaining = 0.f; } bool process(float deltaTime) { if (remaining > 0.f) { remaining -= deltaTime; return true; } return false; } void trigger(float duration = 1e-3f) { if (duration > remaining) { remaining = duration; } } }; } // namespace dsp namespace event { // using Base = widget::BaseEvent; // using PositionBase = widget::Widget::PositionBaseEvent; // using KeyBase = widget::Widget::KeyBaseEvent; // using TextBase = widget::Widget::TextBaseEvent; // using Hover = widget::Widget::HoverEvent; // using Button = widget::Widget::ButtonEvent; // using DoubleClick = widget::Widget::DoubleClickEvent; // using HoverKey = widget::Widget::HoverKeyEvent; // using HoverText = widget::Widget::HoverTextEvent; // using HoverScroll = widget::Widget::HoverScrollEvent; // using Enter = widget::Widget::EnterEvent; // using Leave = widget::Widget::LeaveEvent; // using Select = widget::Widget::SelectEvent; // using Deselect = widget::Widget::DeselectEvent; // using SelectKey = widget::Widget::SelectKeyEvent; // using SelectText = widget::Widget::SelectTextEvent; // using DragBase = widget::Widget::DragBaseEvent; // using DragStart = widget::Widget::DragStartEvent; // using DragEnd = widget::Widget::DragEndEvent; // using DragMove = widget::Widget::DragMoveEvent; // using DragHover = widget::Widget::DragHoverEvent; // using DragEnter = widget::Widget::DragEnterEvent; // using DragLeave = widget::Widget::DragLeaveEvent; // using DragDrop = widget::Widget::DragDropEvent; // using PathDrop = widget::Widget::PathDropEvent; using Action = widget::Widget::ActionEvent; using Change = widget::Widget::ChangeEvent; // using Dirty = widget::Widget::DirtyEvent; // using Reposition = widget::Widget::RepositionEvent; // using Resize = widget::Widget::ResizeEvent; // using Add = widget::Widget::AddEvent; // using Remove = widget::Widget::RemoveEvent; // using Show = widget::Widget::ShowEvent; // using Hide = widget::Widget::HideEvent; } // namespace event namespace plugin { struct Model { virtual ~Model() {} virtual engine::Module* createModule() = 0; }; struct Plugin { }; } // namespace plugin namespace ui { struct Menu : widget::OpaqueWidget { // Menu* parentMenu = NULL; // Menu* childMenu = NULL; // MenuEntry* activeEntry = NULL; // BNDcornerFlags cornerFlags = BND_CORNER_NONE; // void setChildMenu(Menu* menu) {} }; struct MenuEntry : widget::OpaqueWidget { }; struct MenuItem : MenuEntry { std::string text; std::string rightText; bool disabled = false; }; struct MenuLabel : MenuEntry { std::string text; }; } // namespace ui namespace window { static constexpr const float SVG_DPI = 75.f; static constexpr const float MM_PER_IN = 25.4f; inline float in2px(float in) { return in * SVG_DPI; } inline math::Vec in2px(math::Vec in) { return in.mult(SVG_DPI); } inline float mm2px(float mm) { return mm * (SVG_DPI / MM_PER_IN); } inline math::Vec mm2px(math::Vec mm) { return mm.mult(SVG_DPI / MM_PER_IN); } struct Image { int handle; }; struct Window { std::shared_ptr loadImage(const std::string&) { return {}; } void* loadSvg(const void*) { return NULL; } }; }; using namespace app; using namespace componentlibrary; using namespace engine; using namespace math; using namespace ui; using namespace widget; using namespace window; using plugin::Plugin; using plugin::Model; template plugin::Model* createModel(std::string slug) { struct TModel : plugin::Model { engine::Module* createModule() override { return new TModule; } }; return new TModel; } template T* construct() { return NULL; } template T* construct(F f, V v, Args... args) { return NULL; } template TWidget* createWidget(math::Vec pos) { return NULL; } template TParamWidget* createParam(math::Vec pos, engine::Module* module, int paramId) { return NULL; } template TParamWidget* createParamCentered(math::Vec pos, engine::Module* module, int paramId) { return NULL; } template TPortWidget* createInput(math::Vec pos, engine::Module* module, int inputId) { return NULL; } template TPortWidget* createInputCentered(math::Vec pos, engine::Module* module, int inputId) { return NULL; } template TPortWidget* createOutput(math::Vec pos, engine::Module* module, int outputId) { return NULL; } template TPortWidget* createOutputCentered(math::Vec pos, engine::Module* module, int outputId) { return NULL; } template TModuleLightWidget* createLight(math::Vec pos, engine::Module* module, int firstLightId) { return NULL; } template TModuleLightWidget* createLightCentered(math::Vec pos, engine::Module* module, int firstLightId) { return NULL; } struct Context { engine::Engine _engine; window::Window _window; engine::Engine* engine = &_engine; window::Window* window = &_window; }; Context* contextGet(); void contextSet(Context* context); } // namespace rack #define APP rack::contextGet()