diff --git a/plugins/Cardinal/plugin.json b/plugins/Cardinal/plugin.json
index d05bce01..1ef3af9f 100644
--- a/plugins/Cardinal/plugin.json
+++ b/plugins/Cardinal/plugin.json
@@ -75,6 +75,15 @@
"tags": [
"Utility"
]
+ },
+ {
+ "slug": "CardinalExpIn8",
+ "disabled": false,
+ "name": "Cardinal Expander Inputs 8",
+ "description": "Expander to add 8 parameters CV inputs to Cardinal's plugin hosts",
+ "tags": [
+ "Expander"
+ ]
}
]
}
diff --git a/plugins/Cardinal/res/CardinalExpIn8.svg b/plugins/Cardinal/res/CardinalExpIn8.svg
new file mode 100644
index 00000000..a40ba990
--- /dev/null
+++ b/plugins/Cardinal/res/CardinalExpIn8.svg
@@ -0,0 +1,128 @@
+
+
+
+
diff --git a/plugins/Cardinal/src/CardinalExpIn8.cpp b/plugins/Cardinal/src/CardinalExpIn8.cpp
new file mode 100644
index 00000000..3b855ff2
--- /dev/null
+++ b/plugins/Cardinal/src/CardinalExpIn8.cpp
@@ -0,0 +1,88 @@
+//Expander module for Cardinal's plugin hosts
+//
+//Based on code from GateSeq64 and GateSeq64Expander by Marc Boulé
+//Adapted for Ildaeil by Simon-L
+
+#include "plugin.hpp"
+#include "expanders.hpp"
+
+static const unsigned int ildaeil_expanderRefreshStepSkips = 4;
+
+struct CardinalExpIn8 : CardinalExpander, Module {
+
+ void sendExpMessage() {
+ for (int i = 0; i < NUM_INPUTS; i++) {
+ float *messageToBase = (float*)rightExpander.module->leftExpander.producerMessage;
+ messageToBase[i] = (inputs[i].isConnected() ? inputs[i].getVoltage() : 0.0);
+ }
+ rightExpander.module->leftExpander.messageFlipRequested = true;
+ }
+
+ void processExpMessage() {}
+
+ enum InputIds {
+ PARAM1_INPUT,
+ PARAM2_INPUT,
+ PARAM3_INPUT,
+ PARAM4_INPUT,
+ PARAM5_INPUT,
+ PARAM6_INPUT,
+ PARAM7_INPUT,
+ PARAM8_INPUT,
+ NUM_INPUTS
+ };
+
+
+ CardinalExpIn8() {
+ config(0, NUM_INPUTS, 0, 0);
+
+ rightExpander.producerMessage = rightMessages[0];
+ rightExpander.consumerMessage = rightMessages[1];
+
+ configInput(PARAM1_INPUT, "Parameter 1");
+ configInput(PARAM2_INPUT, "Parameter 2");
+ configInput(PARAM3_INPUT, "Parameter 3");
+ configInput(PARAM4_INPUT, "Parameter 4");
+ configInput(PARAM5_INPUT, "Parameter 5");
+ configInput(PARAM6_INPUT, "Parameter 6");
+ configInput(PARAM7_INPUT, "Parameter 7");
+ configInput(PARAM8_INPUT, "Parameter 8");
+
+ }
+
+ void process(const ProcessArgs &args) override {
+ bool basePresent = (rightExpander.module && isCardinalExpandable(rightExpander.module));
+ if (basePresent) {
+ sendExpMessage();
+ }
+ }// process()
+};
+
+
+struct CardinalExpIn8Widget : ModuleWidget {
+ CardinalExpIn8Widget(CardinalExpIn8 *module) {
+ setModule(module);
+
+ setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CardinalExpIn8.svg")));
+ box.size = Vec(RACK_GRID_WIDTH * 2, RACK_GRID_HEIGHT);
+
+ // Screws
+ addChild(createWidget(Vec(0, 0)));
+ addChild(createWidget(Vec(0, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+ addChild(createWidget(Vec(RACK_GRID_WIDTH, 0)));
+ addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+ // Inputs
+ addInput(createInput(Vec(3, 54 + 75), module, CardinalExpIn8::PARAM1_INPUT));
+ addInput(createInput(Vec(3, 54 + 105), module, CardinalExpIn8::PARAM2_INPUT));
+ addInput(createInput(Vec(3, 54 + 135), module, CardinalExpIn8::PARAM3_INPUT));
+ addInput(createInput(Vec(3, 54 + 165), module, CardinalExpIn8::PARAM4_INPUT));
+ addInput(createInput(Vec(3, 54 + 195), module, CardinalExpIn8::PARAM5_INPUT));
+ addInput(createInput(Vec(3, 54 + 225), module, CardinalExpIn8::PARAM6_INPUT));
+ addInput(createInput(Vec(3, 54 + 255), module, CardinalExpIn8::PARAM7_INPUT));
+ addInput(createInput(Vec(3, 54 + 285), module, CardinalExpIn8::PARAM8_INPUT));
+ }
+
+};
+
+Model *modelCardinalExpIn8 = createModel("CardinalExpIn8");
diff --git a/plugins/Cardinal/src/Carla.cpp b/plugins/Cardinal/src/Carla.cpp
index 33b034b3..abd0c20a 100644
--- a/plugins/Cardinal/src/Carla.cpp
+++ b/plugins/Cardinal/src/Carla.cpp
@@ -16,6 +16,7 @@
*/
#include "plugincontext.hpp"
+#include "expanders.hpp"
#include "CarlaNativePlugin.h"
#include "CarlaBackendUtils.hpp"
@@ -54,7 +55,7 @@ static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpc
// --------------------------------------------------------------------------------------------------------------------
-struct CarlaModule : Module {
+struct CarlaModule : Module, CardinalExpander {
enum ParamIds {
BIPOLAR_INPUTS,
BIPOLAR_OUTPUTS,
@@ -123,6 +124,8 @@ struct CarlaModule : Module {
std::memset(dataOut, 0, sizeof(dataOut));
+ setupExpanding(this);
+
fCarlaPluginDescriptor = carla_get_native_patchbay_cv8_plugin();
DISTRHO_SAFE_ASSERT_RETURN(fCarlaPluginDescriptor != nullptr,);
@@ -259,11 +262,34 @@ struct CarlaModule : Module {
patchStorage = getPatchStorageDirectory();
}
+ void sendExpMessage() {}
+
+ void processExpMessage() {
+ // Unimplemented
+ float *messagesFromExpander = (float*)leftExpander.consumerMessage;
+ if (carla_get_current_plugin_count(fCarlaHostHandle)) {
+ const uint32_t pcount = carla_get_parameter_count(fCarlaHostHandle, 0);
+ for (uint i = 0; i < 8; i++) {
+ if (i < pcount && leftExpander.module->inputs[i].isConnected()) {
+ const ::ParameterRanges* const pranges = carla_get_parameter_ranges(fCarlaHostHandle, 0, i);
+ float scaled_param = (messagesFromExpander[i] + 10.0) * (pranges->max - pranges->min) / (20.0 + pranges->min);
+ carla_set_parameter_value(fCarlaHostHandle, 0, i, scaled_param);
+ fCarlaHostDescriptor.ui_parameter_changed(this, i, scaled_param);
+ }
+ }
+ }
+ }
+
void process(const ProcessArgs& args) override
{
if (fCarlaPluginHandle == nullptr)
return;
+ bool expanderPresent = (leftExpander.module && isCardinalExpander(leftExpander.module));
+ if (expanderPresent) {
+ processExpMessage();
+ }
+
const float inputOffset = params[BIPOLAR_INPUTS].getValue() > 0.1f ? -5.0f : 0.0f;
const float outputOffset = params[BIPOLAR_OUTPUTS].getValue() > 0.1f ? -5.0f : 0.0f;
diff --git a/plugins/Cardinal/src/Ildaeil.cpp b/plugins/Cardinal/src/Ildaeil.cpp
index b826ad21..e75c2050 100644
--- a/plugins/Cardinal/src/Ildaeil.cpp
+++ b/plugins/Cardinal/src/Ildaeil.cpp
@@ -26,6 +26,7 @@
*/
#include "plugincontext.hpp"
+#include "expanders.hpp"
#ifndef HEADLESS
# include "ImGuiWidget.hpp"
@@ -220,7 +221,7 @@ struct JuceInitializer {
};
#endif
-struct IldaeilModule : Module {
+struct IldaeilModule : CardinalExpander, Module {
enum ParamIds {
NUM_PARAMS
};
@@ -244,6 +245,23 @@ struct IldaeilModule : Module {
NUM_LIGHTS
};
+ void sendExpMessage() {}
+
+ void processExpMessage() {
+ float *messagesFromExpander = (float*)leftExpander.consumerMessage;
+ if (carla_get_current_plugin_count(fCarlaHostHandle)) {
+ const uint32_t pcount = carla_get_parameter_count(fCarlaHostHandle, 0);
+ for (uint i = 0; i < 8; i++) {
+ if (i < pcount && leftExpander.module->inputs[i].isConnected()) {
+ const ::ParameterRanges* const pranges = carla_get_parameter_ranges(fCarlaHostHandle, 0, i);
+ float scaled_param = (messagesFromExpander[i] + 10.0) * (pranges->max - pranges->min) / (20.0 + pranges->min);
+ carla_set_parameter_value(fCarlaHostHandle, 0, i, scaled_param);
+ fCarlaHostDescriptor.ui_parameter_changed(this, i, scaled_param);
+ }
+ }
+ }
+ }
+
#ifndef HEADLESS
SharedResourcePointer juceInitializer;
#endif
@@ -273,6 +291,7 @@ struct IldaeilModule : Module {
: pcontext(static_cast(APP))
{
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
+
for (uint i=0; i<2; ++i)
{
const char name[] = { 'A','u','d','i','o',' ','#',static_cast('0'+i+1),'\0' };
@@ -289,6 +308,8 @@ struct IldaeilModule : Module {
std::memset(audioDataOut1, 0, sizeof(audioDataOut1));
std::memset(audioDataOut2, 0, sizeof(audioDataOut2));
+ setupExpanding(this);
+
fCarlaPluginDescriptor = carla_get_native_rack_plugin();
DISTRHO_SAFE_ASSERT_RETURN(fCarlaPluginDescriptor != nullptr,);
@@ -432,6 +453,12 @@ struct IldaeilModule : Module {
if (fCarlaPluginHandle == nullptr)
return;
+ bool expanderPresent = (leftExpander.module && isCardinalExpander(leftExpander.module));
+ if (expanderPresent) {
+ // d_stdout("hm?");
+ processExpMessage();
+ }
+
const unsigned i = audioDataFill++;
audioDataIn1[i] = inputs[INPUT1].getVoltage() * 0.1f;
@@ -1369,9 +1396,16 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
}
else
{
+ bool expanderPresent = (module->leftExpander.module && module->isCardinalExpander(module->leftExpander.module));
+ const bool disabled = expanderPresent && (i < 8) && (module->leftExpander.module->inputs[i].isConnected());
+ if (disabled)
+ ImGui::BeginDisabled();
const bool ret = param.log
? ImGui::SliderFloat(param.name, &ui->values[i], param.min, param.max, param.format, 2.0f)
: ImGui::SliderFloat(param.name, &ui->values[i], param.min, param.max, param.format);
+ if (disabled)
+ ImGui::EndDisabled();
+
if (ret)
{
if (ImGui::IsItemActivated())
diff --git a/plugins/Cardinal/src/expanders.hpp b/plugins/Cardinal/src/expanders.hpp
new file mode 100644
index 00000000..063e408a
--- /dev/null
+++ b/plugins/Cardinal/src/expanders.hpp
@@ -0,0 +1,21 @@
+
+struct CardinalExpander
+{
+ CardinalExpander(){
+ };
+ virtual ~CardinalExpander(){};
+
+ bool isCardinalExpandable(Module *x) { return x->model == modelIldaeil || x->model == modelCarla; };
+ bool isCardinalExpander(Module *x) { return x->model == modelCardinalExpIn8; };
+
+ virtual void sendExpMessage() = 0;
+ virtual void processExpMessage() = 0;
+
+ float rightMessages[2][8] = {}; // messages from right-side
+ float leftMessages[2][8] = {};// messages from left-side
+
+ void setupExpanding(Module *module) {
+ module->leftExpander.producerMessage = leftMessages[0];
+ module->leftExpander.consumerMessage = leftMessages[1];
+ }
+};
\ No newline at end of file
diff --git a/plugins/Cardinal/src/plugin.hpp b/plugins/Cardinal/src/plugin.hpp
index 08044cbf..de7e8863 100644
--- a/plugins/Cardinal/src/plugin.hpp
+++ b/plugins/Cardinal/src/plugin.hpp
@@ -34,3 +34,4 @@ extern Model* modelHostCV;
extern Model* modelHostParameters;
extern Model* modelHostTime;
extern Model* modelIldaeil;
+extern Model* modelCardinalExpIn8;
diff --git a/plugins/Makefile b/plugins/Makefile
index 794e5969..97dcefd3 100644
--- a/plugins/Makefile
+++ b/plugins/Makefile
@@ -186,6 +186,7 @@ PLUGIN_FILES += Cardinal/src/HostCV.cpp
PLUGIN_FILES += Cardinal/src/HostParameters.cpp
PLUGIN_FILES += Cardinal/src/HostTime.cpp
PLUGIN_FILES += Cardinal/src/Ildaeil.cpp
+PLUGIN_FILES += Cardinal/src/CardinalExpIn8.cpp
ifneq ($(HEADLESS),true)
PLUGIN_FILES += Cardinal/src/ImGuiWidget.cpp
diff --git a/plugins/plugins.cpp b/plugins/plugins.cpp
index e588675b..0e438127 100644
--- a/plugins/plugins.cpp
+++ b/plugins/plugins.cpp
@@ -647,6 +647,7 @@ static void initStatic__Cardinal()
p->addModel(modelHostParameters);
p->addModel(modelHostTime);
p->addModel(modelIldaeil);
+ p->addModel(modelCardinalExpIn8);
}
}