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, | |||
| "modules": [ | |||
| { | |||
| "id": 2799203590388841, | |||
| "id": 8712245256622475, | |||
| "plugin": "Cardinal", | |||
| "model": "TextEditor", | |||
| "version": "2.0", | |||
| "params": [], | |||
| "leftModuleId": 4, | |||
| "leftModuleId": 1202678850202654, | |||
| "data": { | |||
| "filepath": "", | |||
| "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": [ | |||
| 16, | |||
| 58, | |||
| 0 | |||
| ] | |||
| }, | |||
| { | |||
| "id": 3, | |||
| "plugin": "Cardinal", | |||
| "model": "HostTime", | |||
| "id": 5726895899473528, | |||
| "plugin": "Fundamental", | |||
| "model": "ADSR", | |||
| "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": [ | |||
| 25, | |||
| 18, | |||
| 0 | |||
| ] | |||
| }, | |||
| { | |||
| "id": 4, | |||
| "plugin": "Cardinal", | |||
| "model": "HostParameters", | |||
| "id": 4828178296911509, | |||
| "plugin": "Fundamental", | |||
| "model": "VCA-1", | |||
| "version": "2.0", | |||
| "params": [], | |||
| "leftModuleId": 3, | |||
| "rightModuleId": 2799203590388841, | |||
| "params": [ | |||
| { | |||
| "value": 1.0, | |||
| "id": 0 | |||
| }, | |||
| { | |||
| "value": 1.0, | |||
| "id": 1 | |||
| } | |||
| ], | |||
| "leftModuleId": 5726895899473528, | |||
| "rightModuleId": 1, | |||
| "pos": [ | |||
| 33, | |||
| 27, | |||
| 0 | |||
| ] | |||
| }, | |||
| { | |||
| "id": 7249509538355161, | |||
| "plugin": "Cardinal", | |||
| "model": "HostCV", | |||
| "id": 8601159184541723, | |||
| "plugin": "Fundamental", | |||
| "model": "VCO", | |||
| "version": "2.0", | |||
| "params": [ | |||
| { | |||
| @@ -80,7 +103,7 @@ | |||
| "id": 0 | |||
| }, | |||
| { | |||
| "value": 0.0, | |||
| "value": 1.0, | |||
| "id": 1 | |||
| }, | |||
| { | |||
| @@ -90,30 +113,171 @@ | |||
| { | |||
| "value": 0.0, | |||
| "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": [ | |||
| 8, | |||
| 9, | |||
| 0 | |||
| ] | |||
| }, | |||
| { | |||
| "id": 3606136179759592, | |||
| "id": 1, | |||
| "plugin": "Cardinal", | |||
| "model": "HostAudio2", | |||
| "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": [], | |||
| "rightModuleId": 7249509538355161, | |||
| "rightModuleId": 8601159184541723, | |||
| "data": { | |||
| "dcFilter": false | |||
| "pwRange": 0.0, | |||
| "smooth": false, | |||
| "channels": 1, | |||
| "polyMode": 0, | |||
| "lastPitch": 8192, | |||
| "lastMod": 0, | |||
| "inputChannel": 0, | |||
| "outputChannel": 0 | |||
| }, | |||
| "pos": [ | |||
| 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; | |||
| } | |||
| 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 | |||
| } | |||
| @@ -52,6 +52,37 @@ extern Model* modelTextEditor; | |||
| 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. | |||
| */ | |||
| @@ -61,7 +92,7 @@ float d_findMaxNormalizedFloat128(const float floats[128]) | |||
| static constexpr const float kEmptyFloats[128] = {}; | |||
| if (std::memcmp(floats, kEmptyFloats, sizeof(float)*128) == 0) | |||
| return 0.0f; | |||
| return 0.f; | |||
| float tmp, maxf2 = std::abs(floats[0]); | |||
| @@ -76,8 +107,8 @@ float d_findMaxNormalizedFloat128(const float floats[128]) | |||
| maxf2 = tmp; | |||
| } | |||
| if (maxf2 > 1.0f) | |||
| maxf2 = 1.0f; | |||
| if (maxf2 > 1.f) | |||
| maxf2 = 1.f; | |||
| return maxf2; | |||
| } | |||
| @@ -311,9 +311,12 @@ endif | |||
| PLUGIN_FILES += $(filter-out Fundamental/src/plugin.cpp,$(wildcard Fundamental/src/*.cpp)) | |||
| PLUGIN_FILES += Fundamental/src/dr_wav.c | |||
| MINIPLUGIN_FILES += Fundamental/src/ADSR.cpp | |||
| MINIPLUGIN_FILES += Fundamental/src/LFO.cpp | |||
| MINIPLUGIN_FILES += Fundamental/src/Noise.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/VCMixer.cpp | |||
| MINIPLUGIN_FILES += Fundamental/src/VCO.cpp | |||
| @@ -209,13 +209,16 @@ static void initStatic__Fundamental() | |||
| const StaticPluginLoader spl(p, "Fundamental"); | |||
| if (spl.ok()) | |||
| { | |||
| p->addModel(modelADSR); | |||
| p->addModel(modelLFO); | |||
| p->addModel(modelNoise); | |||
| p->addModel(modelRandom); | |||
| p->addModel(modelScope); | |||
| p->addModel(modelVCA_1); | |||
| p->addModel(modelVCF); | |||
| p->addModel(modelVCMixer); | |||
| p->addModel(modelVCO); | |||
| spl.removeModule("8vert"); | |||
| spl.removeModule("ADSR"); | |||
| spl.removeModule("Delay"); | |||
| spl.removeModule("LFO2"); | |||
| spl.removeModule("Merge"); | |||
| @@ -226,14 +229,11 @@ static void initStatic__Fundamental() | |||
| spl.removeModule("Pulses"); | |||
| spl.removeModule("Quantizer"); | |||
| spl.removeModule("SEQ3"); | |||
| spl.removeModule("Scope"); | |||
| spl.removeModule("SequentialSwitch1"); | |||
| spl.removeModule("SequentialSwitch2"); | |||
| spl.removeModule("Split"); | |||
| spl.removeModule("Sum"); | |||
| spl.removeModule("VCA"); | |||
| spl.removeModule("VCA-1"); | |||
| spl.removeModule("VCO"); | |||
| spl.removeModule("VCO2"); | |||
| } | |||
| } | |||
| @@ -16,4 +16,4 @@ | |||
| */ | |||
| #define CARDINAL_COMMON_UI_ONLY | |||
| #include "CardinalCommon.cpp" | |||
| #include "../CardinalCommon.cpp" | |||
| @@ -39,8 +39,8 @@ | |||
| #define DISTRHO_UI_FILE_BROWSER 1 | |||
| #define DISTRHO_UI_USE_NANOVG 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_NUM_INPUTS CARDINAL_NUM_AUDIO_INPUTS | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS CARDINAL_NUM_AUDIO_OUTPUTS | |||
| @@ -52,7 +52,7 @@ | |||
| static const constexpr uint kCardinalStateBaseCount = 3; // patch, screenshot, comment | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| # include "extra/ScopedValueSetter.hpp" | |||
| # include "WindowParameters.hpp" | |||
| static const constexpr uint kCardinalStateCount = kCardinalStateBaseCount + 2; // moduleInfos, windowSize | |||
| @@ -163,7 +163,7 @@ class CardinalPlugin : public CardinalBasePlugin | |||
| struct { | |||
| String comment; | |||
| String screenshot; | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| String windowSize; | |||
| #endif | |||
| } fState; | |||
| @@ -172,7 +172,7 @@ class CardinalPlugin : public CardinalBasePlugin | |||
| bool fWasBypassed; | |||
| MidiEvent bypassMidiEvents[16]; | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| // real values, not VCV interpreted ones | |||
| float fWindowParameters[kWindowParameterCount]; | |||
| #endif | |||
| @@ -191,7 +191,7 @@ public: | |||
| fNextExpectedFrame(0), | |||
| fWasBypassed(false) | |||
| { | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| fWindowParameters[kWindowParameterShowTooltips] = 1.0f; | |||
| fWindowParameters[kWindowParameterCableOpacity] = 50.0f; | |||
| fWindowParameters[kWindowParameterCableTension] = 75.0f; | |||
| @@ -290,7 +290,7 @@ public: | |||
| context->patch->clear(); | |||
| // 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); | |||
| #endif | |||
| Engine_setAboutToClose(context->engine); | |||
| @@ -419,6 +419,10 @@ protected: | |||
| parameter.symbol += String(index + 1); | |||
| parameter.unit = "v"; | |||
| parameter.hints = kParameterIsAutomatable; | |||
| #if CARDINAL_VARIANT_MINI | |||
| // TODO is hidden | |||
| // parameter.hints |= kParameterIsAutomatable; | |||
| #endif | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 10.0f; | |||
| @@ -431,7 +435,7 @@ protected: | |||
| return; | |||
| } | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| switch (index - kModuleParameters - 1) | |||
| { | |||
| case kWindowParameterShowTooltips: | |||
| @@ -610,7 +614,11 @@ protected: | |||
| switch (index) | |||
| { | |||
| case 0: | |||
| #if CARDINAL_VARIANT_MINI | |||
| state.hints = kStateIsHostWritable; | |||
| #else | |||
| state.hints = kStateIsBase64Blob; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| state.hints |= kStateIsOnlyForDSP; | |||
| #endif | |||
| @@ -620,11 +628,16 @@ protected: | |||
| if (const long fileSize = std::ftell(f)) | |||
| { | |||
| 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) | |||
| { | |||
| fileContent[fileSize] = '\0'; | |||
| #if CARDINAL_VARIANT_MINI | |||
| state.defaultValue = fileContent; | |||
| #else | |||
| state.defaultValue = String::asBase64(fileContent, fileSize); | |||
| #endif | |||
| } | |||
| delete[] fileContent; | |||
| @@ -675,7 +688,7 @@ protected: | |||
| if (index == kModuleParameters) | |||
| return context->bypassed ? 1.0f : 0.0f; | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| // window related parameters | |||
| index -= kModuleParameters + 1; | |||
| @@ -702,7 +715,7 @@ protected: | |||
| return; | |||
| } | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| // window related parameters | |||
| index -= kModuleParameters + 1; | |||
| @@ -716,7 +729,7 @@ protected: | |||
| String getState(const char* const key) const override | |||
| { | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| if (std::strcmp(key, "moduleInfos") == 0) | |||
| { | |||
| json_t* const rootJ = json_object(); | |||
| @@ -784,9 +797,12 @@ protected: | |||
| context->patch->cleanAutosave(); | |||
| // context->history->setSaved(); | |||
| #if CARDINAL_VARIANT_MINI | |||
| #else | |||
| try { | |||
| data = rack::system::archiveDirectory(fAutosavePath, 1); | |||
| } DISTRHO_SAFE_EXCEPTION_RETURN("getState archiveDirectory", String()); | |||
| #endif | |||
| } | |||
| return String::asBase64(data.data(), data.size()); | |||
| @@ -797,10 +813,10 @@ protected: | |||
| #if CARDINAL_VARIANT_MINI | |||
| if (std::strcmp(key, "param") == 0) | |||
| { | |||
| int64_t moduleId = 0; | |||
| longlong moduleId = 0; | |||
| int paramId = 0; | |||
| 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); | |||
| DISTRHO_SAFE_ASSERT_RETURN(module != nullptr,); | |||
| @@ -810,7 +826,7 @@ protected: | |||
| } | |||
| #endif | |||
| #ifndef HEADLESS | |||
| #if CARDINAL_VARIANT_MINI || !defined(HEADLESS) | |||
| if (std::strcmp(key, "moduleInfos") == 0) | |||
| { | |||
| json_error_t error; | |||
| @@ -869,6 +885,16 @@ protected: | |||
| if (fAutosavePath.empty()) | |||
| 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)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,); | |||
| @@ -892,6 +918,7 @@ protected: | |||
| rack::system::unarchiveToDirectory(data, fAutosavePath); | |||
| } DISTRHO_SAFE_EXCEPTION_RETURN("setState unarchiveToDirectory",); | |||
| } | |||
| #endif | |||
| const ScopedContext sc(this); | |||
| @@ -139,7 +139,7 @@ void sendParamChangeToRemote(RemoteDetails* const remote, int64_t moduleId, int | |||
| { | |||
| #if CARDINAL_VARIANT_MINI | |||
| 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); | |||
| #elif defined(HAVE_LIBLO) | |||
| 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->patch->saveAutosave(); | |||
| 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,); | |||
| #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); | |||
| DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); | |||
| @@ -180,7 +186,7 @@ void sendFullPatchToRemote(RemoteDetails* const remote) | |||
| } | |||
| lo_address_free(addr); | |||
| #endif | |||
| #endif | |||
| } | |||
| void sendScreenshotToRemote(RemoteDetails*, const char* const screenshot) | |||
| @@ -298,7 +298,7 @@ class CardinalUI : public CardinalBaseUI, | |||
| rack::math::Vec lastMousePos; | |||
| WindowParameters windowParameters; | |||
| int rateLimitStep = 0; | |||
| #ifdef DISTRHO_OS_WASM | |||
| #if defined(DISTRHO_OS_WASM) && ! CARDINAL_VARIANT_MINI | |||
| int8_t counterForFirstIdlePoint = 0; | |||
| #endif | |||
| #ifdef DPF_RUNTIME_TESTING | |||
| @@ -345,7 +345,7 @@ public: | |||
| rack::contextSet(context); | |||
| #if CARDINAL_VARIANT_MINI | |||
| remoteUtils::connectToRemote(); | |||
| DISTRHO_SAFE_ASSERT(remoteUtils::connectToRemote()); | |||
| // create unique temporary path for this instance | |||
| try { | |||
| @@ -366,9 +366,17 @@ public: | |||
| } | |||
| } 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; | |||
| 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->sampleRate = sampleRate; | |||
| @@ -378,7 +386,7 @@ public: | |||
| context->history = new rack::history::State; | |||
| context->patch = new rack::patch::Manager; | |||
| 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->scene = new rack::app::Scene; | |||
| @@ -386,6 +394,7 @@ public: | |||
| context->window = new rack::window::Window; | |||
| context->patch->loadTemplate(); | |||
| context->scene->rackScroll->reset(); | |||
| Engine_setRemoteDetails(context->engine, remoteDetails); | |||
| @@ -563,7 +572,7 @@ public: | |||
| } | |||
| #endif | |||
| #ifdef DISTRHO_OS_WASM | |||
| #if defined(DISTRHO_OS_WASM) && ! CARDINAL_VARIANT_MINI | |||
| if (counterForFirstIdlePoint >= 0 && ++counterForFirstIdlePoint == 30) | |||
| { | |||
| counterForFirstIdlePoint = -1; | |||
| @@ -606,7 +615,11 @@ public: | |||
| } | |||
| #if CARDINAL_VARIANT_MINI | |||
| context->engine->stepBlock(1); | |||
| { | |||
| const ScopedContext sc(this); | |||
| ++context->processCounter; | |||
| context->engine->stepBlock(1); | |||
| } | |||
| #endif | |||
| if (windowParameters.rateLimit != 0 && ++rateLimitStep % (windowParameters.rateLimit * 2)) | |||
| @@ -702,9 +715,23 @@ protected: | |||
| */ | |||
| 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; | |||
| } | |||
| switch (index - kModuleParameters - 1) | |||
| { | |||
| @@ -180,7 +180,7 @@ endif | |||
| # FIXME | |||
| ifeq ($(CARDINAL_VARIANT)$(CIBUILD)$(WASM),nativetruetrue) | |||
| ifneq ($(STATIC_BUILD),true) | |||
| ifneq ($(OLD_PATH),) | |||
| STATIC_CARLA_PLUGIN_LIBS = -lsndfile -lopus -lFLAC -lvorbisenc -lvorbis -logg -lm | |||
| endif | |||
| endif | |||
| @@ -380,6 +380,7 @@ LINK_FLAGS += -sLZ4=1 | |||
| ifeq ($(CARDINAL_VARIANT),mini) | |||
| LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources | |||
| # LINK_FLAGS += -sEXPORTED_RUNTIME_METHODS=FS,cwrap | |||
| else | |||
| LINK_FLAGS += --shell-file=../emscripten/shell.html | |||
| ifneq ($(STATIC_BUILD),true) | |||
| @@ -135,6 +135,7 @@ struct FileButton : MenuButton { | |||
| patchUtils::loadTemplateDialog(); | |||
| })); | |||
| #if ! CARDINAL_VARIANT_MINI | |||
| #ifndef DISTRHO_OS_WASM | |||
| menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() { | |||
| patchUtils::loadDialog(); | |||
| @@ -164,6 +165,7 @@ struct FileButton : MenuButton { | |||
| menu->addChild(createMenuItem("Save and download uncompressed", "", []() { | |||
| patchUtils::saveAsDialogUncompressed(); | |||
| })); | |||
| #endif | |||
| #endif | |||
| menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { | |||
| @@ -194,6 +196,7 @@ struct FileButton : MenuButton { | |||
| } | |||
| #endif | |||
| #if ! CARDINAL_VARIANT_MINI | |||
| #ifndef DISTRHO_OS_WASM | |||
| menu->addChild(new ui::MenuSeparator); | |||
| @@ -206,6 +209,7 @@ struct FileButton : MenuButton { | |||
| patchUtils::saveAsDialogUncompressed(); | |||
| })); | |||
| #endif | |||
| #endif | |||
| #if ! CARDINAL_VARIANT_MINI | |||
| if (!demoPatches.empty()) | |||
| @@ -761,9 +765,14 @@ struct MeterLabel : ui::Label { | |||
| // uiLastTime = time; | |||
| // } | |||
| #if CARDINAL_VARIANT_MINI | |||
| text = string::f("%.1f fps", 1.0 / frameDurationAvg); | |||
| #else | |||
| double meterAverage = APP->engine->getMeterAverage(); | |||
| double meterMax = APP->engine->getMeterMax(); | |||
| text = string::f("%.1f fps %.1f%% avg %.1f%% max", 1.0 / frameDurationAvg, meterAverage * 100, meterMax * 100); | |||
| #endif | |||
| Label::step(); | |||
| } | |||
| }; | |||
| @@ -795,9 +804,11 @@ struct MenuBar : widget::OpaqueWidget { | |||
| viewButton->text = "View"; | |||
| layout->addChild(viewButton); | |||
| #if ! CARDINAL_VARIANT_MINI | |||
| EngineButton* engineButton = new EngineButton; | |||
| engineButton->text = "Engine"; | |||
| layout->addChild(engineButton); | |||
| #endif | |||
| HelpButton* helpButton = new HelpButton; | |||
| helpButton->text = "Help"; | |||
| @@ -212,7 +212,11 @@ void Scene::step() { | |||
| if (remoteDetails->autoDeploy) { | |||
| const int actionIndex = APP->history->actionIndex; | |||
| 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); | |||
| if (/*std::abs(internal->historyActionIndex = actionIndex) > 1 ||*/ name != "move knob") { | |||
| printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str()); | |||