Signed-off-by: falkTX <falktx@falktx.com>tags/23.02
@@ -1 +1 @@ | |||||
Subproject commit 8eb504d3eb6b4f9984503bedfbd3c02b7cb63d2b | |||||
Subproject commit 207e0ae8720faa4db6f34192d83a0ee3b85b832a |
@@ -1,78 +1,101 @@ | |||||
{ | { | ||||
"version": "2.1", | |||||
"version": "2.1.1", | |||||
"zoom": 1.0, | "zoom": 1.0, | ||||
"modules": [ | "modules": [ | ||||
{ | { | ||||
"id": 2799203590388841, | |||||
"id": 8712245256622475, | |||||
"plugin": "Cardinal", | "plugin": "Cardinal", | ||||
"model": "TextEditor", | "model": "TextEditor", | ||||
"version": "2.0", | "version": "2.0", | ||||
"params": [], | "params": [], | ||||
"leftModuleId": 4, | |||||
"leftModuleId": 1202678850202654, | |||||
"data": { | "data": { | ||||
"filepath": "", | "filepath": "", | ||||
"lang": "None", | "lang": "None", | ||||
"etext": "Welcome to Cardinal!\n\nThis is the mini variant\nIt has 2 audio ports, 5 CV ports, plus MIDI\n\nThe most relevant modules for host\nintegration are in this default patch\n\nHave fun!\n\n", | |||||
"width": 23 | |||||
}, | |||||
"pos": [ | |||||
42, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"id": 2, | |||||
"plugin": "Cardinal", | |||||
"model": "HostMIDI", | |||||
"version": "2.0", | |||||
"params": [], | |||||
"leftModuleId": 7249509538355161, | |||||
"rightModuleId": 3, | |||||
"data": { | |||||
"pwRange": 0.0, | |||||
"smooth": false, | |||||
"channels": 1, | |||||
"polyMode": 0, | |||||
"lastPitch": 8192, | |||||
"lastMod": 0, | |||||
"inputChannel": 0, | |||||
"outputChannel": 0 | |||||
"etext": "Welcome to Cardinal!\n\nThis is the mini variant\nIt has 2 audio ports, 5 CV ports, plus MIDI\n\nThe most relevant modules for host\nintegration are in this default patch\n\nA basic VCO + ADSR + VCA is\nthe default patch\n\nHave fun!\n\n", | |||||
"width": 19 | |||||
}, | }, | ||||
"pos": [ | "pos": [ | ||||
16, | |||||
58, | |||||
0 | 0 | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": 3, | |||||
"plugin": "Cardinal", | |||||
"model": "HostTime", | |||||
"id": 5726895899473528, | |||||
"plugin": "Fundamental", | |||||
"model": "ADSR", | |||||
"version": "2.0", | "version": "2.0", | ||||
"params": [], | |||||
"leftModuleId": 2, | |||||
"rightModuleId": 4, | |||||
"params": [ | |||||
{ | |||||
"value": 0.5, | |||||
"id": 0 | |||||
}, | |||||
{ | |||||
"value": 0.5, | |||||
"id": 1 | |||||
}, | |||||
{ | |||||
"value": 0.5, | |||||
"id": 2 | |||||
}, | |||||
{ | |||||
"value": 0.5, | |||||
"id": 3 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 4 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 5 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 6 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 7 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 8 | |||||
} | |||||
], | |||||
"leftModuleId": 8601159184541723, | |||||
"rightModuleId": 4828178296911509, | |||||
"pos": [ | "pos": [ | ||||
25, | |||||
18, | |||||
0 | 0 | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": 4, | |||||
"plugin": "Cardinal", | |||||
"model": "HostParameters", | |||||
"id": 4828178296911509, | |||||
"plugin": "Fundamental", | |||||
"model": "VCA-1", | |||||
"version": "2.0", | "version": "2.0", | ||||
"params": [], | |||||
"leftModuleId": 3, | |||||
"rightModuleId": 2799203590388841, | |||||
"params": [ | |||||
{ | |||||
"value": 1.0, | |||||
"id": 0 | |||||
}, | |||||
{ | |||||
"value": 1.0, | |||||
"id": 1 | |||||
} | |||||
], | |||||
"leftModuleId": 5726895899473528, | |||||
"rightModuleId": 1, | |||||
"pos": [ | "pos": [ | ||||
33, | |||||
27, | |||||
0 | 0 | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": 7249509538355161, | |||||
"plugin": "Cardinal", | |||||
"model": "HostCV", | |||||
"id": 8601159184541723, | |||||
"plugin": "Fundamental", | |||||
"model": "VCO", | |||||
"version": "2.0", | "version": "2.0", | ||||
"params": [ | "params": [ | ||||
{ | { | ||||
@@ -80,7 +103,7 @@ | |||||
"id": 0 | "id": 0 | ||||
}, | }, | ||||
{ | { | ||||
"value": 0.0, | |||||
"value": 1.0, | |||||
"id": 1 | "id": 1 | ||||
}, | }, | ||||
{ | { | ||||
@@ -90,30 +113,171 @@ | |||||
{ | { | ||||
"value": 0.0, | "value": 0.0, | ||||
"id": 3 | "id": 3 | ||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 4 | |||||
}, | |||||
{ | |||||
"value": 0.5, | |||||
"id": 5 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 6 | |||||
}, | |||||
{ | |||||
"value": 0.0, | |||||
"id": 7 | |||||
} | } | ||||
], | ], | ||||
"leftModuleId": 3606136179759592, | |||||
"rightModuleId": 2, | |||||
"leftModuleId": 2, | |||||
"rightModuleId": 5726895899473528, | |||||
"pos": [ | "pos": [ | ||||
8, | |||||
9, | |||||
0 | 0 | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": 3606136179759592, | |||||
"id": 1, | |||||
"plugin": "Cardinal", | "plugin": "Cardinal", | ||||
"model": "HostAudio2", | "model": "HostAudio2", | ||||
"version": "2.0", | "version": "2.0", | ||||
"params": [ | |||||
{ | |||||
"value": 0.79432821273803711, | |||||
"id": 0 | |||||
} | |||||
], | |||||
"leftModuleId": 4828178296911509, | |||||
"rightModuleId": 4, | |||||
"data": { | |||||
"dcFilter": true | |||||
}, | |||||
"pos": [ | |||||
30, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"id": 2, | |||||
"plugin": "Cardinal", | |||||
"model": "HostMIDI", | |||||
"version": "2.0", | |||||
"params": [], | "params": [], | ||||
"rightModuleId": 7249509538355161, | |||||
"rightModuleId": 8601159184541723, | |||||
"data": { | "data": { | ||||
"dcFilter": false | |||||
"pwRange": 0.0, | |||||
"smooth": false, | |||||
"channels": 1, | |||||
"polyMode": 0, | |||||
"lastPitch": 8192, | |||||
"lastMod": 0, | |||||
"inputChannel": 0, | |||||
"outputChannel": 0 | |||||
}, | }, | ||||
"pos": [ | "pos": [ | ||||
0, | 0, | ||||
0 | 0 | ||||
] | ] | ||||
}, | |||||
{ | |||||
"id": 4, | |||||
"plugin": "Cardinal", | |||||
"model": "HostParameters", | |||||
"version": "2.0", | |||||
"params": [], | |||||
"leftModuleId": 1, | |||||
"rightModuleId": 1202678850202654, | |||||
"data": { | |||||
"smooth": true | |||||
}, | |||||
"pos": [ | |||||
38, | |||||
0 | |||||
] | |||||
}, | |||||
{ | |||||
"id": 1202678850202654, | |||||
"plugin": "Cardinal", | |||||
"model": "HostParametersMap", | |||||
"version": "2.0", | |||||
"params": [], | |||||
"leftModuleId": 4, | |||||
"rightModuleId": 8712245256622475, | |||||
"data": { | |||||
"maps": [ | |||||
{ | |||||
"hostParamId": 255, | |||||
"inverted": false, | |||||
"smooth": true, | |||||
"moduleId": -1, | |||||
"paramId": 0 | |||||
} | |||||
] | |||||
}, | |||||
"pos": [ | |||||
47, | |||||
0 | |||||
] | |||||
} | } | ||||
], | ], | ||||
"cables": [] | |||||
"cables": [ | |||||
{ | |||||
"id": 5155876120487880, | |||||
"outputModuleId": 2, | |||||
"outputId": 1, | |||||
"inputModuleId": 5726895899473528, | |||||
"inputId": 4, | |||||
"color": "#ff9352" | |||||
}, | |||||
{ | |||||
"id": 781753834216137, | |||||
"outputModuleId": 2, | |||||
"outputId": 6, | |||||
"inputModuleId": 5726895899473528, | |||||
"inputId": 5, | |||||
"color": "#ffd452" | |||||
}, | |||||
{ | |||||
"id": 3464471860196875, | |||||
"outputModuleId": 5726895899473528, | |||||
"outputId": 0, | |||||
"inputModuleId": 4828178296911509, | |||||
"inputId": 0, | |||||
"color": "#e8ff52" | |||||
}, | |||||
{ | |||||
"id": 739552540616113, | |||||
"outputModuleId": 4828178296911509, | |||||
"outputId": 0, | |||||
"inputModuleId": 1, | |||||
"inputId": 0, | |||||
"color": "#52beff" | |||||
}, | |||||
{ | |||||
"id": 6701970185765111, | |||||
"outputModuleId": 2, | |||||
"outputId": 0, | |||||
"inputModuleId": 8601159184541723, | |||||
"inputId": 0, | |||||
"color": "#ff5252" | |||||
}, | |||||
{ | |||||
"id": 6959800657121782, | |||||
"outputModuleId": 2, | |||||
"outputId": 2, | |||||
"inputModuleId": 8601159184541723, | |||||
"inputId": 1, | |||||
"color": "#52ff7d" | |||||
}, | |||||
{ | |||||
"id": 1598271319373837, | |||||
"outputModuleId": 8601159184541723, | |||||
"outputId": 0, | |||||
"inputModuleId": 4828178296911509, | |||||
"inputId": 1, | |||||
"color": "#a8ff52" | |||||
} | |||||
] | |||||
} | } |
@@ -222,25 +222,51 @@ struct HostAudio2 : HostAudio<2> { | |||||
valueR = 0.0f; | valueR = 0.0f; | ||||
} | } | ||||
const uint32_t j = internalDataFrame++; | |||||
internalDataBufferL[j] = valueL; | |||||
internalDataBufferR[j] = valueR; | |||||
if (pcontext->variant == kCardinalVariantMini) | |||||
{ | |||||
const uint32_t j = internalDataFrame++; | |||||
internalDataBufferL[j] = valueL; | |||||
internalDataBufferR[j] = valueR; | |||||
if (internalDataFrame == 4) | |||||
{ | |||||
internalDataFrame = 0; | |||||
if (resetMeters) | |||||
gainMeterL = gainMeterR = 0.0f; | |||||
if (internalDataFrame == 128) | |||||
gainMeterL = std::max(gainMeterL, d_findMaxNormalizedFloat<4>(internalDataBufferL)); | |||||
if (in2connected) | |||||
gainMeterR = std::max(gainMeterR, d_findMaxNormalizedFloat<4>(internalDataBufferR)); | |||||
else | |||||
gainMeterR = gainMeterL; | |||||
resetMeters = false; | |||||
} | |||||
} | |||||
else | |||||
{ | { | ||||
internalDataFrame = 0; | |||||
const uint32_t j = internalDataFrame++; | |||||
internalDataBufferL[j] = valueL; | |||||
internalDataBufferR[j] = valueR; | |||||
if (resetMeters) | |||||
gainMeterL = gainMeterR = 0.0f; | |||||
if (internalDataFrame == 128) | |||||
{ | |||||
internalDataFrame = 0; | |||||
if (resetMeters) | |||||
gainMeterL = gainMeterR = 0.0f; | |||||
gainMeterL = std::max(gainMeterL, d_findMaxNormalizedFloat128(internalDataBufferL)); | |||||
gainMeterL = std::max(gainMeterL, d_findMaxNormalizedFloat128(internalDataBufferL)); | |||||
if (in2connected) | |||||
gainMeterR = std::max(gainMeterR, d_findMaxNormalizedFloat128(internalDataBufferR)); | |||||
else | |||||
gainMeterR = gainMeterL; | |||||
if (in2connected) | |||||
gainMeterR = std::max(gainMeterR, d_findMaxNormalizedFloat128(internalDataBufferR)); | |||||
else | |||||
gainMeterR = gainMeterL; | |||||
resetMeters = false; | |||||
resetMeters = false; | |||||
} | |||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
@@ -52,6 +52,37 @@ extern Model* modelTextEditor; | |||||
extern std::vector<Model*> hostTerminalModels; | extern std::vector<Model*> hostTerminalModels; | ||||
/* | |||||
* Find the highest absolute and normalized value within a float array. | |||||
*/ | |||||
template<std::size_t size> | |||||
static inline | |||||
float d_findMaxNormalizedFloat(const float floats[size]) | |||||
{ | |||||
static constexpr const float kEmptyFloats[size] = {}; | |||||
if (std::memcmp(floats, kEmptyFloats, sizeof(float)*size) == 0) | |||||
return 0.f; | |||||
float tmp, maxf2 = std::abs(floats[0]); | |||||
for (std::size_t i=1; i<size; ++i) | |||||
{ | |||||
if (!std::isfinite(floats[i])) | |||||
__builtin_unreachable(); | |||||
tmp = std::abs(floats[i]); | |||||
if (tmp > maxf2) | |||||
maxf2 = tmp; | |||||
} | |||||
if (maxf2 > 1.f) | |||||
maxf2 = 1.f; | |||||
return maxf2; | |||||
} | |||||
/* | /* | ||||
* Find the highest absolute and normalized value within a float array. | * Find the highest absolute and normalized value within a float array. | ||||
*/ | */ | ||||
@@ -61,7 +92,7 @@ float d_findMaxNormalizedFloat128(const float floats[128]) | |||||
static constexpr const float kEmptyFloats[128] = {}; | static constexpr const float kEmptyFloats[128] = {}; | ||||
if (std::memcmp(floats, kEmptyFloats, sizeof(float)*128) == 0) | if (std::memcmp(floats, kEmptyFloats, sizeof(float)*128) == 0) | ||||
return 0.0f; | |||||
return 0.f; | |||||
float tmp, maxf2 = std::abs(floats[0]); | float tmp, maxf2 = std::abs(floats[0]); | ||||
@@ -76,8 +107,8 @@ float d_findMaxNormalizedFloat128(const float floats[128]) | |||||
maxf2 = tmp; | maxf2 = tmp; | ||||
} | } | ||||
if (maxf2 > 1.0f) | |||||
maxf2 = 1.0f; | |||||
if (maxf2 > 1.f) | |||||
maxf2 = 1.f; | |||||
return maxf2; | return maxf2; | ||||
} | } |
@@ -311,9 +311,12 @@ endif | |||||
PLUGIN_FILES += $(filter-out Fundamental/src/plugin.cpp,$(wildcard Fundamental/src/*.cpp)) | PLUGIN_FILES += $(filter-out Fundamental/src/plugin.cpp,$(wildcard Fundamental/src/*.cpp)) | ||||
PLUGIN_FILES += Fundamental/src/dr_wav.c | PLUGIN_FILES += Fundamental/src/dr_wav.c | ||||
MINIPLUGIN_FILES += Fundamental/src/ADSR.cpp | |||||
MINIPLUGIN_FILES += Fundamental/src/LFO.cpp | MINIPLUGIN_FILES += Fundamental/src/LFO.cpp | ||||
MINIPLUGIN_FILES += Fundamental/src/Noise.cpp | MINIPLUGIN_FILES += Fundamental/src/Noise.cpp | ||||
MINIPLUGIN_FILES += Fundamental/src/Random.cpp | MINIPLUGIN_FILES += Fundamental/src/Random.cpp | ||||
MINIPLUGIN_FILES += Fundamental/src/Scope.cpp | |||||
MINIPLUGIN_FILES += Fundamental/src/VCA-1.cpp | |||||
MINIPLUGIN_FILES += Fundamental/src/VCF.cpp | MINIPLUGIN_FILES += Fundamental/src/VCF.cpp | ||||
MINIPLUGIN_FILES += Fundamental/src/VCMixer.cpp | MINIPLUGIN_FILES += Fundamental/src/VCMixer.cpp | ||||
MINIPLUGIN_FILES += Fundamental/src/VCO.cpp | MINIPLUGIN_FILES += Fundamental/src/VCO.cpp | ||||
@@ -209,13 +209,16 @@ static void initStatic__Fundamental() | |||||
const StaticPluginLoader spl(p, "Fundamental"); | const StaticPluginLoader spl(p, "Fundamental"); | ||||
if (spl.ok()) | if (spl.ok()) | ||||
{ | { | ||||
p->addModel(modelADSR); | |||||
p->addModel(modelLFO); | p->addModel(modelLFO); | ||||
p->addModel(modelNoise); | p->addModel(modelNoise); | ||||
p->addModel(modelRandom); | p->addModel(modelRandom); | ||||
p->addModel(modelScope); | |||||
p->addModel(modelVCA_1); | |||||
p->addModel(modelVCF); | p->addModel(modelVCF); | ||||
p->addModel(modelVCMixer); | p->addModel(modelVCMixer); | ||||
p->addModel(modelVCO); | |||||
spl.removeModule("8vert"); | spl.removeModule("8vert"); | ||||
spl.removeModule("ADSR"); | |||||
spl.removeModule("Delay"); | spl.removeModule("Delay"); | ||||
spl.removeModule("LFO2"); | spl.removeModule("LFO2"); | ||||
spl.removeModule("Merge"); | spl.removeModule("Merge"); | ||||
@@ -226,14 +229,11 @@ static void initStatic__Fundamental() | |||||
spl.removeModule("Pulses"); | spl.removeModule("Pulses"); | ||||
spl.removeModule("Quantizer"); | spl.removeModule("Quantizer"); | ||||
spl.removeModule("SEQ3"); | spl.removeModule("SEQ3"); | ||||
spl.removeModule("Scope"); | |||||
spl.removeModule("SequentialSwitch1"); | spl.removeModule("SequentialSwitch1"); | ||||
spl.removeModule("SequentialSwitch2"); | spl.removeModule("SequentialSwitch2"); | ||||
spl.removeModule("Split"); | spl.removeModule("Split"); | ||||
spl.removeModule("Sum"); | spl.removeModule("Sum"); | ||||
spl.removeModule("VCA"); | spl.removeModule("VCA"); | ||||
spl.removeModule("VCA-1"); | |||||
spl.removeModule("VCO"); | |||||
spl.removeModule("VCO2"); | spl.removeModule("VCO2"); | ||||
} | } | ||||
} | } | ||||
@@ -16,4 +16,4 @@ | |||||
*/ | */ | ||||
#define CARDINAL_COMMON_UI_ONLY | #define CARDINAL_COMMON_UI_ONLY | ||||
#include "CardinalCommon.cpp" | |||||
#include "../CardinalCommon.cpp" |
@@ -39,8 +39,8 @@ | |||||
#define DISTRHO_UI_FILE_BROWSER 1 | #define DISTRHO_UI_FILE_BROWSER 1 | ||||
#define DISTRHO_UI_USE_NANOVG 1 | #define DISTRHO_UI_USE_NANOVG 1 | ||||
#define DISTRHO_UI_USER_RESIZABLE 1 | #define DISTRHO_UI_USER_RESIZABLE 1 | ||||
#define DISTRHO_UI_DEFAULT_WIDTH 1228 | |||||
#define DISTRHO_UI_DEFAULT_HEIGHT 666 | |||||
#define DISTRHO_UI_DEFAULT_WIDTH 1000 | |||||
#define DISTRHO_UI_DEFAULT_HEIGHT 600 | |||||
#define DISTRHO_PLUGIN_IS_SYNTH 0 | #define DISTRHO_PLUGIN_IS_SYNTH 0 | ||||
#define DISTRHO_PLUGIN_NUM_INPUTS CARDINAL_NUM_AUDIO_INPUTS | #define DISTRHO_PLUGIN_NUM_INPUTS CARDINAL_NUM_AUDIO_INPUTS | ||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS CARDINAL_NUM_AUDIO_OUTPUTS | #define DISTRHO_PLUGIN_NUM_OUTPUTS CARDINAL_NUM_AUDIO_OUTPUTS | ||||
@@ -52,7 +52,7 @@ | |||||
static const constexpr uint kCardinalStateBaseCount = 3; // patch, screenshot, comment | static const constexpr uint kCardinalStateBaseCount = 3; // patch, screenshot, comment | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
# include "extra/ScopedValueSetter.hpp" | # include "extra/ScopedValueSetter.hpp" | ||||
# include "WindowParameters.hpp" | # include "WindowParameters.hpp" | ||||
static const constexpr uint kCardinalStateCount = kCardinalStateBaseCount + 2; // moduleInfos, windowSize | static const constexpr uint kCardinalStateCount = kCardinalStateBaseCount + 2; // moduleInfos, windowSize | ||||
@@ -163,7 +163,7 @@ class CardinalPlugin : public CardinalBasePlugin | |||||
struct { | struct { | ||||
String comment; | String comment; | ||||
String screenshot; | String screenshot; | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
String windowSize; | String windowSize; | ||||
#endif | #endif | ||||
} fState; | } fState; | ||||
@@ -172,7 +172,7 @@ class CardinalPlugin : public CardinalBasePlugin | |||||
bool fWasBypassed; | bool fWasBypassed; | ||||
MidiEvent bypassMidiEvents[16]; | MidiEvent bypassMidiEvents[16]; | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
// real values, not VCV interpreted ones | // real values, not VCV interpreted ones | ||||
float fWindowParameters[kWindowParameterCount]; | float fWindowParameters[kWindowParameterCount]; | ||||
#endif | #endif | ||||
@@ -191,7 +191,7 @@ public: | |||||
fNextExpectedFrame(0), | fNextExpectedFrame(0), | ||||
fWasBypassed(false) | fWasBypassed(false) | ||||
{ | { | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
fWindowParameters[kWindowParameterShowTooltips] = 1.0f; | fWindowParameters[kWindowParameterShowTooltips] = 1.0f; | ||||
fWindowParameters[kWindowParameterCableOpacity] = 50.0f; | fWindowParameters[kWindowParameterCableOpacity] = 50.0f; | ||||
fWindowParameters[kWindowParameterCableTension] = 75.0f; | fWindowParameters[kWindowParameterCableTension] = 75.0f; | ||||
@@ -290,7 +290,7 @@ public: | |||||
context->patch->clear(); | context->patch->clear(); | ||||
// do a little dance to prevent context scene deletion from saving to temp dir | // do a little dance to prevent context scene deletion from saving to temp dir | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
const ScopedValueSetter<bool> svs(rack::settings::headless, true); | const ScopedValueSetter<bool> svs(rack::settings::headless, true); | ||||
#endif | #endif | ||||
Engine_setAboutToClose(context->engine); | Engine_setAboutToClose(context->engine); | ||||
@@ -419,6 +419,10 @@ protected: | |||||
parameter.symbol += String(index + 1); | parameter.symbol += String(index + 1); | ||||
parameter.unit = "v"; | parameter.unit = "v"; | ||||
parameter.hints = kParameterIsAutomatable; | parameter.hints = kParameterIsAutomatable; | ||||
#if CARDINAL_VARIANT_MINI | |||||
// TODO is hidden | |||||
// parameter.hints |= kParameterIsAutomatable; | |||||
#endif | |||||
parameter.ranges.def = 0.0f; | parameter.ranges.def = 0.0f; | ||||
parameter.ranges.min = 0.0f; | parameter.ranges.min = 0.0f; | ||||
parameter.ranges.max = 10.0f; | parameter.ranges.max = 10.0f; | ||||
@@ -431,7 +435,7 @@ protected: | |||||
return; | return; | ||||
} | } | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
switch (index - kModuleParameters - 1) | switch (index - kModuleParameters - 1) | ||||
{ | { | ||||
case kWindowParameterShowTooltips: | case kWindowParameterShowTooltips: | ||||
@@ -610,7 +614,11 @@ protected: | |||||
switch (index) | switch (index) | ||||
{ | { | ||||
case 0: | case 0: | ||||
#if CARDINAL_VARIANT_MINI | |||||
state.hints = kStateIsHostWritable; | |||||
#else | |||||
state.hints = kStateIsBase64Blob; | state.hints = kStateIsBase64Blob; | ||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
state.hints |= kStateIsOnlyForDSP; | state.hints |= kStateIsOnlyForDSP; | ||||
#endif | #endif | ||||
@@ -620,11 +628,16 @@ protected: | |||||
if (const long fileSize = std::ftell(f)) | if (const long fileSize = std::ftell(f)) | ||||
{ | { | ||||
std::fseek(f, 0, SEEK_SET); | std::fseek(f, 0, SEEK_SET); | ||||
char* const fileContent = new char[fileSize]; | |||||
char* const fileContent = new char[fileSize+1]; | |||||
if (std::fread(fileContent, fileSize, 1, f) == 1) | if (std::fread(fileContent, fileSize, 1, f) == 1) | ||||
{ | { | ||||
fileContent[fileSize] = '\0'; | |||||
#if CARDINAL_VARIANT_MINI | |||||
state.defaultValue = fileContent; | |||||
#else | |||||
state.defaultValue = String::asBase64(fileContent, fileSize); | state.defaultValue = String::asBase64(fileContent, fileSize); | ||||
#endif | |||||
} | } | ||||
delete[] fileContent; | delete[] fileContent; | ||||
@@ -675,7 +688,7 @@ protected: | |||||
if (index == kModuleParameters) | if (index == kModuleParameters) | ||||
return context->bypassed ? 1.0f : 0.0f; | return context->bypassed ? 1.0f : 0.0f; | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
// window related parameters | // window related parameters | ||||
index -= kModuleParameters + 1; | index -= kModuleParameters + 1; | ||||
@@ -702,7 +715,7 @@ protected: | |||||
return; | return; | ||||
} | } | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
// window related parameters | // window related parameters | ||||
index -= kModuleParameters + 1; | index -= kModuleParameters + 1; | ||||
@@ -716,7 +729,7 @@ protected: | |||||
String getState(const char* const key) const override | String getState(const char* const key) const override | ||||
{ | { | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
if (std::strcmp(key, "moduleInfos") == 0) | if (std::strcmp(key, "moduleInfos") == 0) | ||||
{ | { | ||||
json_t* const rootJ = json_object(); | json_t* const rootJ = json_object(); | ||||
@@ -784,9 +797,12 @@ protected: | |||||
context->patch->cleanAutosave(); | context->patch->cleanAutosave(); | ||||
// context->history->setSaved(); | // context->history->setSaved(); | ||||
#if CARDINAL_VARIANT_MINI | |||||
#else | |||||
try { | try { | ||||
data = rack::system::archiveDirectory(fAutosavePath, 1); | data = rack::system::archiveDirectory(fAutosavePath, 1); | ||||
} DISTRHO_SAFE_EXCEPTION_RETURN("getState archiveDirectory", String()); | } DISTRHO_SAFE_EXCEPTION_RETURN("getState archiveDirectory", String()); | ||||
#endif | |||||
} | } | ||||
return String::asBase64(data.data(), data.size()); | return String::asBase64(data.data(), data.size()); | ||||
@@ -797,10 +813,10 @@ protected: | |||||
#if CARDINAL_VARIANT_MINI | #if CARDINAL_VARIANT_MINI | ||||
if (std::strcmp(key, "param") == 0) | if (std::strcmp(key, "param") == 0) | ||||
{ | { | ||||
int64_t moduleId = 0; | |||||
longlong moduleId = 0; | |||||
int paramId = 0; | int paramId = 0; | ||||
float paramValue = 0.f; | float paramValue = 0.f; | ||||
std::sscanf(value, "%lu:%d:%f", &moduleId, ¶mId, ¶mValue); | |||||
std::sscanf(value, "%lld:%d:%f", &moduleId, ¶mId, ¶mValue); | |||||
rack::engine::Module* const module = context->engine->getModule(moduleId); | rack::engine::Module* const module = context->engine->getModule(moduleId); | ||||
DISTRHO_SAFE_ASSERT_RETURN(module != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(module != nullptr,); | ||||
@@ -810,7 +826,7 @@ protected: | |||||
} | } | ||||
#endif | #endif | ||||
#ifndef HEADLESS | |||||
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||||
if (std::strcmp(key, "moduleInfos") == 0) | if (std::strcmp(key, "moduleInfos") == 0) | ||||
{ | { | ||||
json_error_t error; | json_error_t error; | ||||
@@ -869,6 +885,16 @@ protected: | |||||
if (fAutosavePath.empty()) | if (fAutosavePath.empty()) | ||||
return; | return; | ||||
#if CARDINAL_VARIANT_MINI | |||||
FILE* const f = std::fopen(rack::system::join(fAutosavePath, "patch.json").c_str(), "w"); | |||||
DISTRHO_SAFE_ASSERT_RETURN(f != nullptr,); | |||||
rack::system::removeRecursively(fAutosavePath); | |||||
rack::system::createDirectories(fAutosavePath); | |||||
std::fwrite(value, std::strlen(value)+1, 1, f); | |||||
std::fclose(f); | |||||
#else | |||||
const std::vector<uint8_t> data(d_getChunkFromBase64String(value)); | const std::vector<uint8_t> data(d_getChunkFromBase64String(value)); | ||||
DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,); | DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,); | ||||
@@ -892,6 +918,7 @@ protected: | |||||
rack::system::unarchiveToDirectory(data, fAutosavePath); | rack::system::unarchiveToDirectory(data, fAutosavePath); | ||||
} DISTRHO_SAFE_EXCEPTION_RETURN("setState unarchiveToDirectory",); | } DISTRHO_SAFE_EXCEPTION_RETURN("setState unarchiveToDirectory",); | ||||
} | } | ||||
#endif | |||||
const ScopedContext sc(this); | const ScopedContext sc(this); | ||||
@@ -139,7 +139,7 @@ void sendParamChangeToRemote(RemoteDetails* const remote, int64_t moduleId, int | |||||
{ | { | ||||
#if CARDINAL_VARIANT_MINI | #if CARDINAL_VARIANT_MINI | ||||
char paramBuf[512] = {}; | char paramBuf[512] = {}; | ||||
std::snprintf(paramBuf, sizeof(paramBuf), "%lu:%d:%f", moduleId, paramId, value); | |||||
std::snprintf(paramBuf, sizeof(paramBuf), "%llu:%d:%f", (ulonglong)moduleId, paramId, value); | |||||
static_cast<CardinalBaseUI*>(remote->handle)->setState("param", paramBuf); | static_cast<CardinalBaseUI*>(remote->handle)->setState("param", paramBuf); | ||||
#elif defined(HAVE_LIBLO) | #elif defined(HAVE_LIBLO) | ||||
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT); | const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT); | ||||
@@ -159,17 +159,23 @@ void sendFullPatchToRemote(RemoteDetails* const remote) | |||||
context->engine->prepareSave(); | context->engine->prepareSave(); | ||||
context->patch->saveAutosave(); | context->patch->saveAutosave(); | ||||
context->patch->cleanAutosave(); | context->patch->cleanAutosave(); | ||||
std::vector<uint8_t> data(rack::system::archiveDirectory(context->patch->autosavePath, 1)); | |||||
std::vector<uint8_t> data; | |||||
using namespace rack::system; | |||||
#if CARDINAL_VARIANT_MINI | |||||
try { | |||||
data = readFile(join(context->patch->autosavePath, "patch.json")); | |||||
} DISTRHO_SAFE_EXCEPTION_RETURN("sendFullPatchToRemote",); | |||||
static_cast<CardinalBaseUI*>(remote->handle)->setState("patch", reinterpret_cast<const char*>(data.data())); | |||||
#elif defined(HAVE_LIBLO) | |||||
try { | |||||
data = archiveDirectory(context->patch->autosavePath, 1); | |||||
} DISTRHO_SAFE_EXCEPTION_RETURN("sendFullPatchToRemote",); | |||||
DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,); | DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,); | ||||
#if CARDINAL_VARIANT_MINI | |||||
if (char* const patch = String::asBase64(data.data(), data.size()).getAndReleaseBuffer()) | |||||
{ | |||||
static_cast<CardinalBaseUI*>(remote->handle)->setState("patch", patch); | |||||
std::free(patch); | |||||
} | |||||
#elif defined(HAVE_LIBLO) | |||||
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT); | const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT); | ||||
DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); | ||||
@@ -180,7 +186,7 @@ void sendFullPatchToRemote(RemoteDetails* const remote) | |||||
} | } | ||||
lo_address_free(addr); | lo_address_free(addr); | ||||
#endif | |||||
#endif | |||||
} | } | ||||
void sendScreenshotToRemote(RemoteDetails*, const char* const screenshot) | void sendScreenshotToRemote(RemoteDetails*, const char* const screenshot) | ||||
@@ -298,7 +298,7 @@ class CardinalUI : public CardinalBaseUI, | |||||
rack::math::Vec lastMousePos; | rack::math::Vec lastMousePos; | ||||
WindowParameters windowParameters; | WindowParameters windowParameters; | ||||
int rateLimitStep = 0; | int rateLimitStep = 0; | ||||
#ifdef DISTRHO_OS_WASM | |||||
#if defined(DISTRHO_OS_WASM) && ! CARDINAL_VARIANT_MINI | |||||
int8_t counterForFirstIdlePoint = 0; | int8_t counterForFirstIdlePoint = 0; | ||||
#endif | #endif | ||||
#ifdef DPF_RUNTIME_TESTING | #ifdef DPF_RUNTIME_TESTING | ||||
@@ -345,7 +345,7 @@ public: | |||||
rack::contextSet(context); | rack::contextSet(context); | ||||
#if CARDINAL_VARIANT_MINI | #if CARDINAL_VARIANT_MINI | ||||
remoteUtils::connectToRemote(); | |||||
DISTRHO_SAFE_ASSERT(remoteUtils::connectToRemote()); | |||||
// create unique temporary path for this instance | // create unique temporary path for this instance | ||||
try { | try { | ||||
@@ -366,9 +366,17 @@ public: | |||||
} | } | ||||
} DISTRHO_SAFE_EXCEPTION("create unique temporary path"); | } DISTRHO_SAFE_EXCEPTION("create unique temporary path"); | ||||
const float sampleRate = getSampleRate(); | |||||
const float sampleRate = 60; // fake audio running at 60 fps | |||||
rack::settings::sampleRate = sampleRate; | rack::settings::sampleRate = sampleRate; | ||||
context->dataIns = new const float*[DISTRHO_PLUGIN_NUM_INPUTS]; | |||||
context->dataOuts = new float*[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||||
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS;++i) | |||||
*const_cast<float**>(&context->dataIns[i]) = new float[1]; | |||||
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS;++i) | |||||
context->dataOuts[i] = new float[1]; | |||||
context->bufferSize = 1; | context->bufferSize = 1; | ||||
context->sampleRate = sampleRate; | context->sampleRate = sampleRate; | ||||
@@ -378,7 +386,7 @@ public: | |||||
context->history = new rack::history::State; | context->history = new rack::history::State; | ||||
context->patch = new rack::patch::Manager; | context->patch = new rack::patch::Manager; | ||||
context->patch->autosavePath = fAutosavePath; | context->patch->autosavePath = fAutosavePath; | ||||
context->patch->templatePath = context->patch->factoryTemplatePath = fInitializer->templatePath; | |||||
context->patch->templatePath = context->patch->factoryTemplatePath = fInitializer->factoryTemplatePath; | |||||
context->event = new rack::widget::EventState; | context->event = new rack::widget::EventState; | ||||
context->scene = new rack::app::Scene; | context->scene = new rack::app::Scene; | ||||
@@ -386,6 +394,7 @@ public: | |||||
context->window = new rack::window::Window; | context->window = new rack::window::Window; | ||||
context->patch->loadTemplate(); | |||||
context->scene->rackScroll->reset(); | context->scene->rackScroll->reset(); | ||||
Engine_setRemoteDetails(context->engine, remoteDetails); | Engine_setRemoteDetails(context->engine, remoteDetails); | ||||
@@ -563,7 +572,7 @@ public: | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef DISTRHO_OS_WASM | |||||
#if defined(DISTRHO_OS_WASM) && ! CARDINAL_VARIANT_MINI | |||||
if (counterForFirstIdlePoint >= 0 && ++counterForFirstIdlePoint == 30) | if (counterForFirstIdlePoint >= 0 && ++counterForFirstIdlePoint == 30) | ||||
{ | { | ||||
counterForFirstIdlePoint = -1; | counterForFirstIdlePoint = -1; | ||||
@@ -606,7 +615,11 @@ public: | |||||
} | } | ||||
#if CARDINAL_VARIANT_MINI | #if CARDINAL_VARIANT_MINI | ||||
context->engine->stepBlock(1); | |||||
{ | |||||
const ScopedContext sc(this); | |||||
++context->processCounter; | |||||
context->engine->stepBlock(1); | |||||
} | |||||
#endif | #endif | ||||
if (windowParameters.rateLimit != 0 && ++rateLimitStep % (windowParameters.rateLimit * 2)) | if (windowParameters.rateLimit != 0 && ++rateLimitStep % (windowParameters.rateLimit * 2)) | ||||
@@ -702,9 +715,23 @@ protected: | |||||
*/ | */ | ||||
void parameterChanged(const uint32_t index, const float value) override | void parameterChanged(const uint32_t index, const float value) override | ||||
{ | { | ||||
// host mapped parameters + bypass | |||||
if (index <= kModuleParameters) | |||||
// host mapped parameters | |||||
if (index < kModuleParameters) | |||||
{ | |||||
#if CARDINAL_VARIANT_MINI | |||||
context->parameters[index] = value; | |||||
#endif | |||||
return; | |||||
} | |||||
// bypass | |||||
if (index == kModuleParameters) | |||||
{ | |||||
#if CARDINAL_VARIANT_MINI | |||||
context->bypassed = value > 0.5f; | |||||
#endif | |||||
return; | return; | ||||
} | |||||
switch (index - kModuleParameters - 1) | switch (index - kModuleParameters - 1) | ||||
{ | { | ||||
@@ -180,7 +180,7 @@ endif | |||||
# FIXME | # FIXME | ||||
ifeq ($(CARDINAL_VARIANT)$(CIBUILD)$(WASM),nativetruetrue) | ifeq ($(CARDINAL_VARIANT)$(CIBUILD)$(WASM),nativetruetrue) | ||||
ifneq ($(STATIC_BUILD),true) | |||||
ifneq ($(OLD_PATH),) | |||||
STATIC_CARLA_PLUGIN_LIBS = -lsndfile -lopus -lFLAC -lvorbisenc -lvorbis -logg -lm | STATIC_CARLA_PLUGIN_LIBS = -lsndfile -lopus -lFLAC -lvorbisenc -lvorbis -logg -lm | ||||
endif | endif | ||||
endif | endif | ||||
@@ -380,6 +380,7 @@ LINK_FLAGS += -sLZ4=1 | |||||
ifeq ($(CARDINAL_VARIANT),mini) | ifeq ($(CARDINAL_VARIANT),mini) | ||||
LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources | LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources | ||||
# LINK_FLAGS += -sEXPORTED_RUNTIME_METHODS=FS,cwrap | |||||
else | else | ||||
LINK_FLAGS += --shell-file=../emscripten/shell.html | LINK_FLAGS += --shell-file=../emscripten/shell.html | ||||
ifneq ($(STATIC_BUILD),true) | ifneq ($(STATIC_BUILD),true) | ||||
@@ -135,6 +135,7 @@ struct FileButton : MenuButton { | |||||
patchUtils::loadTemplateDialog(); | patchUtils::loadTemplateDialog(); | ||||
})); | })); | ||||
#if ! CARDINAL_VARIANT_MINI | |||||
#ifndef DISTRHO_OS_WASM | #ifndef DISTRHO_OS_WASM | ||||
menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() { | menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() { | ||||
patchUtils::loadDialog(); | patchUtils::loadDialog(); | ||||
@@ -164,6 +165,7 @@ struct FileButton : MenuButton { | |||||
menu->addChild(createMenuItem("Save and download uncompressed", "", []() { | menu->addChild(createMenuItem("Save and download uncompressed", "", []() { | ||||
patchUtils::saveAsDialogUncompressed(); | patchUtils::saveAsDialogUncompressed(); | ||||
})); | })); | ||||
#endif | |||||
#endif | #endif | ||||
menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { | menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { | ||||
@@ -194,6 +196,7 @@ struct FileButton : MenuButton { | |||||
} | } | ||||
#endif | #endif | ||||
#if ! CARDINAL_VARIANT_MINI | |||||
#ifndef DISTRHO_OS_WASM | #ifndef DISTRHO_OS_WASM | ||||
menu->addChild(new ui::MenuSeparator); | menu->addChild(new ui::MenuSeparator); | ||||
@@ -206,6 +209,7 @@ struct FileButton : MenuButton { | |||||
patchUtils::saveAsDialogUncompressed(); | patchUtils::saveAsDialogUncompressed(); | ||||
})); | })); | ||||
#endif | #endif | ||||
#endif | |||||
#if ! CARDINAL_VARIANT_MINI | #if ! CARDINAL_VARIANT_MINI | ||||
if (!demoPatches.empty()) | if (!demoPatches.empty()) | ||||
@@ -761,9 +765,14 @@ struct MeterLabel : ui::Label { | |||||
// uiLastTime = time; | // uiLastTime = time; | ||||
// } | // } | ||||
#if CARDINAL_VARIANT_MINI | |||||
text = string::f("%.1f fps", 1.0 / frameDurationAvg); | |||||
#else | |||||
double meterAverage = APP->engine->getMeterAverage(); | double meterAverage = APP->engine->getMeterAverage(); | ||||
double meterMax = APP->engine->getMeterMax(); | double meterMax = APP->engine->getMeterMax(); | ||||
text = string::f("%.1f fps %.1f%% avg %.1f%% max", 1.0 / frameDurationAvg, meterAverage * 100, meterMax * 100); | text = string::f("%.1f fps %.1f%% avg %.1f%% max", 1.0 / frameDurationAvg, meterAverage * 100, meterMax * 100); | ||||
#endif | |||||
Label::step(); | Label::step(); | ||||
} | } | ||||
}; | }; | ||||
@@ -795,9 +804,11 @@ struct MenuBar : widget::OpaqueWidget { | |||||
viewButton->text = "View"; | viewButton->text = "View"; | ||||
layout->addChild(viewButton); | layout->addChild(viewButton); | ||||
#if ! CARDINAL_VARIANT_MINI | |||||
EngineButton* engineButton = new EngineButton; | EngineButton* engineButton = new EngineButton; | ||||
engineButton->text = "Engine"; | engineButton->text = "Engine"; | ||||
layout->addChild(engineButton); | layout->addChild(engineButton); | ||||
#endif | |||||
HelpButton* helpButton = new HelpButton; | HelpButton* helpButton = new HelpButton; | ||||
helpButton->text = "Help"; | helpButton->text = "Help"; | ||||
@@ -212,7 +212,11 @@ void Scene::step() { | |||||
if (remoteDetails->autoDeploy) { | if (remoteDetails->autoDeploy) { | ||||
const int actionIndex = APP->history->actionIndex; | const int actionIndex = APP->history->actionIndex; | ||||
const double time = system::getTime(); | const double time = system::getTime(); | ||||
if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) { | |||||
if (internal->historyActionIndex == -1) { | |||||
internal->historyActionIndex = actionIndex; | |||||
internal->lastSceneChangeTime = time; | |||||
} else if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) { | |||||
const std::string& name(APP->history->actions[actionIndex - 1]->name); | const std::string& name(APP->history->actions[actionIndex - 1]->name); | ||||
if (/*std::abs(internal->historyActionIndex = actionIndex) > 1 ||*/ name != "move knob") { | if (/*std::abs(internal->historyActionIndex = actionIndex) > 1 ||*/ name != "move knob") { | ||||
printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str()); | printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str()); | ||||