From e861389537446e8bb249033ce599f9b8f082dd72 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 23 May 2022 03:56:01 +0100 Subject: [PATCH] Add Host Parameters Map module, functional but still WIP Signed-off-by: falkTX --- plugins/Cardinal/plugin.json | 9 + plugins/Cardinal/src/HostMIDI-Map.cpp | 74 +-- plugins/Cardinal/src/HostParameters-Map.cpp | 589 ++++++++++++++++++++ plugins/Cardinal/src/HostParameters.cpp | 1 - plugins/Cardinal/src/plugin.hpp | 1 + plugins/Makefile | 2 +- plugins/plugins.cpp | 2 + 7 files changed, 639 insertions(+), 39 deletions(-) create mode 100644 plugins/Cardinal/src/HostParameters-Map.cpp diff --git a/plugins/Cardinal/plugin.json b/plugins/Cardinal/plugin.json index dfeed6e..ff96849 100644 --- a/plugins/Cardinal/plugin.json +++ b/plugins/Cardinal/plugin.json @@ -90,6 +90,15 @@ "External" ] }, + { + "slug": "HostParametersMap", + "name": "Host Parameters Map", + "description": "Allows host-controlled plugin parameters to control other module parameters", + "manualUrl": "https://github.com/DISTRHO/Cardinal/blob/main/docs/CARDINAL-MODULES.md#host-parameters-map", + "tags": [ + "External" + ] + }, { "slug": "HostTime", "name": "Host Time", diff --git a/plugins/Cardinal/src/HostMIDI-Map.cpp b/plugins/Cardinal/src/HostMIDI-Map.cpp index de8c123..46bb16e 100644 --- a/plugins/Cardinal/src/HostMIDI-Map.cpp +++ b/plugins/Cardinal/src/HostMIDI-Map.cpp @@ -59,6 +59,7 @@ struct HostMIDIMap : TerminalModule { uint32_t lastProcessCounter; int nextLearningId; uint8_t channel; + bool bypassed = false; // from Rack bool smooth; @@ -95,12 +96,10 @@ struct HostMIDIMap : TerminalModule { { paramHandles[id].color = nvgRGBf(0.76f, 0.11f, 0.22f); paramHandles[id].text.reserve(25); + valueFilters[id].setTau(1 / 30.f); pcontext->engine->addParamHandle(¶mHandles[id]); } - for (int i = 0; i < MAX_MIDI_CONTROL; i++) - valueFilters[i].setTau(1 / 30.f); - divider.setDivision(32); onReset(); } @@ -141,13 +140,14 @@ struct HostMIDIMap : TerminalModule { if (processCounterChanged) { + bypassed = isBypassed(); lastProcessCounter = processCounter; midiEvents = pcontext->midiEvents; midiEventsLeft = pcontext->midiEventCount; midiEventFrame = 0; } - if (isBypassed() || !divider.process()) + if (bypassed || !divider.process()) { ++midiEventFrame; return; @@ -262,21 +262,6 @@ struct HostMIDIMap : TerminalModule { void processTerminalOutput(const ProcessArgs&) override {} - void clearMap(int id) - { - nextLearningId = -1; - learningId = -1; - learnedCc = false; - learnedParam = false; - - ccs[id] = -1; - values[id] = -1; - pcontext->engine->updateParamHandle(¶mHandles[id], -1, 0, true); - valueFilters[id].reset(); - refreshParamHandleText(id); - updateMapLen(); - } - // ---------------------------------------------------------------------------------------------------------------- // stuff for resetting state @@ -308,7 +293,21 @@ struct HostMIDIMap : TerminalModule { // ---------------------------------------------------------------------------------------------------------------- // stuff called from panel side, must lock engine - // called from onSelect + void clearMap(int id) + { + nextLearningId = -1; + learningId = -1; + learnedCc = false; + learnedParam = false; + + ccs[id] = -1; + values[id] = -1; + pcontext->engine->updateParamHandle(¶mHandles[id], -1, 0, true); + valueFilters[id].reset(); + refreshParamHandleText(id); + updateMapLen(); + } + void enableLearn(const int id) { if (learningId == id) @@ -321,16 +320,6 @@ struct HostMIDIMap : TerminalModule { learnedParam = false; } - // called from onDeselect - void disableLearn(const int id) - { - nextLearningId = -1; - - if (learningId == id) - learningId = -1; - } - - // called from onDeselect void learnParam(const int id, const int64_t moduleId, const int paramId) { pcontext->engine->updateParamHandle(¶mHandles[id], moduleId, paramId, true); @@ -339,6 +328,16 @@ struct HostMIDIMap : TerminalModule { updateMapLen(); } + /* + void disableLearn(const int id) + { + nextLearningId = -1; + + if (learningId == id) + learningId = -1; + } + */ + // ---------------------------------------------------------------------------------------------------------------- // common utils @@ -371,14 +370,16 @@ struct HostMIDIMap : TerminalModule { // this is called during RT!! void refreshParamHandleText(const int id) { - char textBuf[25]; - if (ccs[id] >= 0) + { + char textBuf[25]; std::sprintf(textBuf, "CC%02d", ccs[id]); + paramHandles[id].text.assign(textBuf); + } else - std::strcpy(textBuf, "MIDI-Map"); - - paramHandles[id].text.assign(textBuf); + { + paramHandles[id].text.clear(); + } } void updateMapLen() @@ -471,7 +472,6 @@ struct HostMIDIMap : TerminalModule { struct CardinalMIDIMapChoice : CardinalLedDisplayChoice { HostMIDIMap* const module; const int id; - int disableLearnFrames = -1; ParamWidget* lastTouchedParam = nullptr; CardinalMIDIMapChoice(HostMIDIMap* const m, const int i) @@ -576,10 +576,10 @@ struct CardinalMIDIMapChoice : CardinalLedDisplayChoice { switch (e.button) { case GLFW_MOUSE_BUTTON_RIGHT: + APP->scene->rack->touchedParam = lastTouchedParam = nullptr; module->clearMap(id); e.consume(this); break; - // fall-through case GLFW_MOUSE_BUTTON_LEFT: APP->scene->rack->touchedParam = lastTouchedParam = nullptr; module->enableLearn(id); diff --git a/plugins/Cardinal/src/HostParameters-Map.cpp b/plugins/Cardinal/src/HostParameters-Map.cpp new file mode 100644 index 0000000..fd1763d --- /dev/null +++ b/plugins/Cardinal/src/HostParameters-Map.cpp @@ -0,0 +1,589 @@ +/* + * 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 portions from VCVRack's core/MIDIMap.cpp + * 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. + */ + +#include "plugincontext.hpp" +#include "ModuleWidgets.hpp" +#include "Widgets.hpp" + +// ----------------------------------------------------------------------------------------------------------- + +static constexpr const uint8_t MAX_MAPPED_PARAMS = 64; + +struct HostParametersMap : TerminalModule { + enum ParamIds { + NUM_PARAMS + }; + enum InputIds { + NUM_INPUTS + }; + enum OutputIds { + NUM_OUTPUTS + }; + enum LightIds { + NUM_LIGHTS + }; + + struct Mapping { + uint8_t hostParamId = UINT8_MAX; + bool inverted = false; + bool smooth = false; + ParamHandle paramHandle; + }; + + Mapping mappings[MAX_MAPPED_PARAMS]; + dsp::ExponentialFilter valueFilters[MAX_MAPPED_PARAMS]; + bool filterInitialized[MAX_MAPPED_PARAMS] = {}; + bool valueReached[MAX_MAPPED_PARAMS] = {}; + + uint8_t numMappedParmeters = 1; + uint8_t learningId = UINT8_MAX; + + CardinalPluginContext* const pcontext; + bool parametersChanged[kModuleParameters] = {}; + float parameterValues[kModuleParameters]; + bool bypassed = false; + bool firstRun = true; + uint32_t lastProcessCounter = 0; + + HostParametersMap() + : pcontext(static_cast(APP)) + { + if (pcontext == nullptr) + throw rack::Exception("Plugin context is null."); + + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); + + for (uint8_t id = 0; id < MAX_MAPPED_PARAMS; ++id) + { + mappings[id].paramHandle.color = nvgRGBf(0.76f, 0.11f, 0.22f); + valueFilters[id].setTau(1 / 30.f); + pcontext->engine->addParamHandle(&mappings[id].paramHandle); + } + + std::memcpy(parameterValues, pcontext->parameters, sizeof(parameterValues)); + } + + ~HostParametersMap() + { + if (pcontext == nullptr) + return; + + for (uint8_t id = 0; id < MAX_MAPPED_PARAMS; ++id) + pcontext->engine->removeParamHandle(&mappings[id].paramHandle); + } + + void onReset() override + { + lastProcessCounter = 0; + + // Use NoLock because we're already in an Engine write-lock if Engine::resetModule(). + // We also might be in the MIDIMap() constructor, which could cause problems, but when constructing, all ParamHandles will point to no Modules anyway. + clearMaps_NoLock(); + numMappedParmeters = 1; + } + + void clearMaps_NoLock() + { + learningId = UINT8_MAX; + + for (uint8_t id = 0; id < MAX_MAPPED_PARAMS; ++id) + { + pcontext->engine->updateParamHandle_NoLock(&mappings[id].paramHandle, -1, 0, true); + valueReached[id] = false; + valueFilters[id].reset(); + mappings[id].hostParamId = UINT8_MAX; + } + + firstRun = true; + std::memcpy(parameterValues, pcontext->parameters, sizeof(parameterValues)); + std::memset(parametersChanged, 0, sizeof(parametersChanged)); + } + + void processTerminalInput(const ProcessArgs& args) override + { + const uint32_t processCounter = pcontext->processCounter; + + if (lastProcessCounter == processCounter) + return; + + lastProcessCounter = processCounter; + + if (isBypassed()) + return; + + for (uint32_t i = 0; i < kModuleParameters; ++i) + { + if (d_isEqual(pcontext->parameters[i], parameterValues[i])) + continue; + + parameterValues[i] = pcontext->parameters[i]; + parametersChanged[i] = true; + } + + for (uint id = 0; id < numMappedParmeters; ++id) + { + ParamHandle& paramHandle(mappings[id].paramHandle); + + if (paramHandle.module == nullptr) + continue; + + // Get ParamQuantity from ParamHandle + const int paramId = paramHandle.paramId; + ParamQuantity* const paramQuantity = paramHandle.module->paramQuantities[paramId]; + if (!paramQuantity) + continue; + if (!paramQuantity->isBounded()) + continue; + + // Validate hostParamId + const uint8_t hostParamId = mappings[id].hostParamId; + if (hostParamId >= kModuleParameters) + continue; + + // Set filter from param value if filter is uninitialized + if (!filterInitialized[id]) + { + valueFilters[id].out = paramQuantity->getScaledValue(); + filterInitialized[id] = true; + continue; + } + + // Check if parameter was changed by the host + if (parametersChanged[hostParamId] && !firstRun) + valueReached[id] = false; + else if (valueReached[id]) + continue; + + // Apply value, smooth as needed. + const float value = 0.1f * (mappings[id].inverted ? 10.f - parameterValues[hostParamId] + : parameterValues[hostParamId]); + + if (mappings[id].smooth && std::fabs(valueFilters[id].out - value) < 1.f) + { + // Smooth value with filter + if (d_isEqual(valueFilters[id].process(args.sampleTime * pcontext->bufferSize, value), value)) + { + valueReached[id] = true; + continue; + } + } + else + { + // Jump value + if (d_isEqual(valueFilters[id].out, value)) + { + valueReached[id] = true; + continue; + } + + valueFilters[id].out = value; + } + + paramQuantity->setScaledValue(valueFilters[id].out); + } + + firstRun = false; + std::memset(parametersChanged, 0, sizeof(parametersChanged)); + } + + void processTerminalOutput(const ProcessArgs&) override + {} + + // ---------------------------------------------------------------------------------------------------------------- + // save and load json stuff + + json_t* dataToJson() override + { + json_t* const rootJ = json_object(); + DISTRHO_SAFE_ASSERT_RETURN(rootJ != nullptr, nullptr); + + if (json_t* const mapsJ = json_array()) + { + for (uint id = 0; id < numMappedParmeters; ++id) + { + json_t* const mapJ = json_object(); + DISTRHO_SAFE_ASSERT_CONTINUE(mapJ != nullptr); + json_object_set_new(mapJ, "hostParamId", json_integer(mappings[id].hostParamId)); + json_object_set_new(mapJ, "inverted", json_boolean(mappings[id].inverted)); + json_object_set_new(mapJ, "smooth", json_boolean(mappings[id].smooth)); + json_object_set_new(mapJ, "moduleId", json_integer(mappings[id].paramHandle.moduleId)); + json_object_set_new(mapJ, "paramId", json_integer(mappings[id].paramHandle.paramId)); + json_array_append_new(mapsJ, mapJ); + } + json_object_set_new(rootJ, "maps", mapsJ); + } + + return rootJ; + } + + void dataFromJson(json_t* const rootJ) override + { + // Use NoLock because we're already in an Engine write-lock. + clearMaps_NoLock(); + + if (json_t* const mapsJ = json_object_get(rootJ, "maps")) + { + json_t* mapJ; + size_t id; + json_array_foreach(mapsJ, id, mapJ) + { + if (id >= MAX_MAPPED_PARAMS) + break; + json_t* const hostParamIdJ = json_object_get(mapJ, "hostParamId"); + json_t* const invertedJ = json_object_get(mapJ, "inverted"); + json_t* const smoothJ = json_object_get(mapJ, "smooth"); + json_t* const moduleIdJ = json_object_get(mapJ, "moduleId"); + json_t* const paramIdJ = json_object_get(mapJ, "paramId"); + if (hostParamIdJ == nullptr) + continue; + if (invertedJ == nullptr) + continue; + if (smoothJ == nullptr) + continue; + if (moduleIdJ == nullptr) + continue; + if (paramIdJ == nullptr) + continue; + + filterInitialized[id] = false; + valueReached[id] = true; + valueFilters[id].reset(); + mappings[id].hostParamId = json_integer_value(hostParamIdJ); + mappings[id].inverted = json_boolean_value(invertedJ); + mappings[id].smooth = json_boolean_value(smoothJ); + pcontext->engine->updateParamHandle_NoLock(&mappings[id].paramHandle, + json_integer_value(moduleIdJ), + json_integer_value(paramIdJ), + false); + } + } + + updateMapLen(); + } + + // ---------------------------------------------------------------------------------------------------------------- + // stuff called from panel side + + void clearMap(const uint8_t id) + { + learningId = UINT8_MAX; + + mappings[id].hostParamId = UINT8_MAX; + pcontext->engine->updateParamHandle(&mappings[id].paramHandle, -1, 0, true); + updateMapLen(); + } + + void learnParam(const uint8_t hostParamId, const bool inverted, const bool smooth, + const int64_t moduleId, const int paramId) + { + const uint8_t id = learningId; + learningId = UINT8_MAX; + DISTRHO_SAFE_ASSERT_RETURN(id < MAX_MAPPED_PARAMS,); + + filterInitialized[id] = false; + valueFilters[id].reset(); + valueReached[id] = true; + mappings[id].inverted = inverted; + mappings[id].smooth = smooth; + mappings[id].hostParamId = hostParamId; + + if (mappings[id].paramHandle.moduleId != moduleId || mappings[id].paramHandle.paramId != paramId) + pcontext->engine->updateParamHandle(&mappings[id].paramHandle, moduleId, paramId, true); + + updateMapLen(); + } + + void updateMapLen() + { + // Find last nonempty map + int16_t id; + for (id = MAX_MAPPED_PARAMS; --id >= 0;) + { + if (mappings[id].paramHandle.moduleId >= 0) + break; + } + + numMappedParmeters = static_cast(id + 1); + + // Add an empty "Mapping..." slot + if (numMappedParmeters < MAX_MAPPED_PARAMS) + ++numMappedParmeters; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +#ifndef HEADLESS +struct HostParametersMapChoice : CardinalLedDisplayChoice { + HostParametersMap* const module; + const uint8_t id; + uint8_t hostParamId = UINT8_MAX; + bool inverted = false; + bool smooth = true; + + HostParametersMapChoice(HostParametersMap* const m, const uint8_t i) + : CardinalLedDisplayChoice(), + module(m), + id(i) + { + alignTextCenter = false; + + // Module browser setup + if (m == nullptr) + { + bgColor = nvgRGB(0, 0, 0); + color.a = 0.75f; + text = "Click here to map"; + } + } + + void draw(const DrawArgs& args) override + { + if (bgColor.a > 0.0f) + { + nvgBeginPath(args.vg); + nvgRoundedRect(args.vg, 0, 0, box.size.x, box.size.y, 4); + nvgFillColor(args.vg, bgColor); + nvgFill(args.vg); + } + + Widget::draw(args); + } + + void step() override + { + if (module == nullptr) + return; + + // Set bgColor and selected state + if (module->learningId == id) + { + bgColor = color; + bgColor.a = 0.125f; + + if (ParamWidget* const touchedParam = APP->scene->rack->touchedParam) + { + APP->scene->rack->touchedParam = nullptr; + DISTRHO_SAFE_ASSERT_RETURN(hostParamId < kModuleParameters,); + + const int64_t moduleId = touchedParam->module->id; + const int paramId = touchedParam->paramId; + module->learnParam(hostParamId, inverted, smooth, moduleId, paramId); + } + } + else + { + bgColor = nvgRGB(0, 0, 0); + } + + // Set text + text.clear(); + + // mapped + if (module->mappings[id].hostParamId < kModuleParameters) + text += string::f("P%02d: ", module->mappings[id].hostParamId + 1); + if (module->mappings[id].paramHandle.moduleId >= 0) + text += getParamName(); + + // Set text color + if (text.empty() && module->learningId != id) + color.a = 0.75f; + else + color.a = 1.0f; + + // unmapped + if (text.empty()) + { + if (module->learningId == id) + text = "Mapping..."; + else + text = module->numMappedParmeters == 1 ? "Click here to map" : "Unmapped"; + } + } + + void onButton(const ButtonEvent& e) override + { + DISTRHO_SAFE_ASSERT_RETURN(module != nullptr,); + + e.stopPropagating(); + + if (e.action != GLFW_PRESS) + return; + + switch (e.button) + { + case GLFW_MOUSE_BUTTON_RIGHT: + APP->scene->rack->touchedParam = nullptr; + module->clearMap(id); + e.consume(this); + break; + case GLFW_MOUSE_BUTTON_LEFT: + APP->scene->rack->touchedParam = nullptr; + e.consume(this); + // reset before dialog + module->learningId = hostParamId = UINT8_MAX; + inverted = smooth = false; + HostParametersMapChoice* const self = this; + // open dialog + async_dialog_text_input("Plugin-exposed parameter index to map to", "1", [self](char* newText){ + if (self == nullptr || newText == nullptr) + return; + // FIXME use a proper dialog + const int hostParamIdTry = std::atoi(newText); + if (hostParamIdTry > 0 && hostParamIdTry < (int)kModuleParameters) + { + self->module->learningId = self->id; + self->hostParamId = static_cast(hostParamIdTry - 1); + self->inverted = false; + self->smooth = false; + } + std::free(newText); + }); + break; + } + } + + std::string getParamName() const + { + DISTRHO_SAFE_ASSERT_RETURN(module != nullptr, "error"); + DISTRHO_SAFE_ASSERT_RETURN(id < module->numMappedParmeters, "error"); + + ParamHandle paramHandle(module->mappings[id].paramHandle); + + Module* const paramModule = paramHandle.module; + DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN("paramModule is null", paramModule != nullptr, "error"); + + const int paramId = paramHandle.paramId; + DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN("paramId is out of bounds", paramId < (int) paramModule->params.size(), "error"); + + ParamQuantity* const paramQuantity = paramModule->paramQuantities[paramId]; + std::string s = paramQuantity->name; + if (s.empty()) + s = "Unnamed"; + s += " ("; + s += paramModule->model->name; + s += ")"; + return s; + } +}; + +struct HostParametersMapDisplay : Widget { + HostParametersMap* module; + ScrollWidget* scroll; + HostParametersMapChoice* choices[MAX_MAPPED_PARAMS]; + LedDisplaySeparator* separators[MAX_MAPPED_PARAMS]; + + void drawLayer(const DrawArgs& args, int layer) override + { + nvgScissor(args.vg, RECT_ARGS(args.clipBox)); + Widget::drawLayer(args, layer); + nvgResetScissor(args.vg); + } + + void setModule(HostParametersMap* const module) + { + this->module = module; + + scroll = new ScrollWidget; + scroll->box.size = box.size; + addChild(scroll); + + float posY = 0.0f; + for (uint8_t id = 0; id < MAX_MAPPED_PARAMS; ++id) + { + if (id != 0) + { + LedDisplaySeparator* separator = createWidget(Vec(0.0f, posY)); + separator->box.size = Vec(box.size.x, 1.0f); + separator->visible = false; + scroll->container->addChild(separator); + separators[id] = separator; + } + + HostParametersMapChoice* const choice = new HostParametersMapChoice(module, id); + choice->box.pos = Vec(0.0f, posY); + choice->box.size = Vec(box.size.x, 20.0f); + choice->visible = id == 0; + scroll->container->addChild(choice); + choices[id] = choice; + + posY += choice->box.size.y; + } + } + + void step() override + { + if (module != nullptr) + { + const uint8_t numMappedParmeters = module->numMappedParmeters; + + for (uint8_t id = 1; id < MAX_MAPPED_PARAMS; ++id) + { + separators[id]->visible = (id < numMappedParmeters); + choices[id]->visible = (id < numMappedParmeters); + } + } + + Widget::step(); + } +}; + +struct HostParametersMapWidget : ModuleWidgetWith11HP { + HostParametersMap* const module; + + HostParametersMapWidget(HostParametersMap* const m) + : module(m) + { + setModule(module); + setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/HostParamsMap.svg"))); + createAndAddScrews(); + + HostParametersMapDisplay* const display = createWidget(Vec(1.0f, 71.0f)); + display->box.size = Vec(box.size.x - 2.0f, box.size.y - 89.0f); + display->setModule(m); + addChild(display); + } + + void draw(const DrawArgs& args) override + { + drawBackground(args.vg); + ModuleWidgetWith11HP::draw(args); + } +}; +#else +struct HostParametersMapWidget : ModuleWidget { + HostParametersMapWidget(HostParametersMap* const module) { + setModule(module); + } +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +Model* modelHostParametersMap = createModel("HostParametersMap"); + +// -------------------------------------------------------------------------------------------------------------------- diff --git a/plugins/Cardinal/src/HostParameters.cpp b/plugins/Cardinal/src/HostParameters.cpp index ac03d82..5ae63cc 100644 --- a/plugins/Cardinal/src/HostParameters.cpp +++ b/plugins/Cardinal/src/HostParameters.cpp @@ -53,7 +53,6 @@ struct HostParameters : TerminalModule { { const uint32_t processCounter = pcontext->processCounter; - // only checked on input if (lastProcessCounter != processCounter) { bypassed = isBypassed(); diff --git a/plugins/Cardinal/src/plugin.hpp b/plugins/Cardinal/src/plugin.hpp index d87d648..204e822 100644 --- a/plugins/Cardinal/src/plugin.hpp +++ b/plugins/Cardinal/src/plugin.hpp @@ -43,6 +43,7 @@ extern Model* modelHostMIDICC; extern Model* modelHostMIDIGate; extern Model* modelHostMIDIMap; extern Model* modelHostParameters; +extern Model* modelHostParametersMap; extern Model* modelHostTime; extern Model* modelIldaeil; extern Model* modelMPV; diff --git a/plugins/Makefile b/plugins/Makefile index f960f95..a32b910 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -200,6 +200,7 @@ PLUGIN_FILES += Cardinal/src/HostMIDI-CC.cpp PLUGIN_FILES += Cardinal/src/HostMIDI-Gate.cpp PLUGIN_FILES += Cardinal/src/HostMIDI-Map.cpp PLUGIN_FILES += Cardinal/src/HostParameters.cpp +PLUGIN_FILES += Cardinal/src/HostParameters-Map.cpp PLUGIN_FILES += Cardinal/src/HostTime.cpp PLUGIN_FILES += Cardinal/src/TextEditor.cpp @@ -219,7 +220,6 @@ ifneq ($(HEADLESS),true) PLUGIN_FILES += Cardinal/src/ImGuiWidget.cpp PLUGIN_FILES += Cardinal/src/ImGuiTextEditor.cpp PLUGIN_FILES += Cardinal/src/SassyScope.cpp -# PLUGIN_FILES += Cardinal/src/sassy/sassy_scope.cpp PLUGIN_FILES += $(wildcard Cardinal/src/DearImGui/*.cpp) PLUGIN_FILES += $(wildcard Cardinal/src/DearImGuiColorTextEditor/*.cpp) endif diff --git a/plugins/plugins.cpp b/plugins/plugins.cpp index 6b38d8c..b27014f 100644 --- a/plugins/plugins.cpp +++ b/plugins/plugins.cpp @@ -895,6 +895,7 @@ static void initStatic__Cardinal() p->addModel(modelHostMIDIGate); p->addModel(modelHostMIDIMap); p->addModel(modelHostParameters); + p->addModel(modelHostParametersMap); p->addModel(modelHostTime); p->addModel(modelTextEditor); #ifndef STATIC_BUILD @@ -931,6 +932,7 @@ static void initStatic__Cardinal() modelHostMIDIGate, modelHostMIDIMap, modelHostParameters, + modelHostParametersMap, modelHostTime, }; }