From c469dbf76b13481f81aa987b9bb223f38c51da60 Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 20 Oct 2021 20:37:42 +0100 Subject: [PATCH] Initial work for host parameters module Signed-off-by: falkTX --- plugins/Cardinal/plugin.json | 22 ++- plugins/Cardinal/res/HostParameters.svg | 237 ++++++++++++++++++++++++ plugins/Cardinal/res/distrho.svg | 99 ++++++++++ plugins/Cardinal/src/HostParameters.cpp | 81 +++++++- plugins/plugins.cpp | 5 +- src/CardinalPlugin.cpp | 97 +++++----- src/CardinalUI.cpp | 4 +- src/PluginContext.hpp | 50 +++-- src/template.vcv | 23 ++- 9 files changed, 549 insertions(+), 69 deletions(-) create mode 100644 plugins/Cardinal/res/HostParameters.svg create mode 100644 plugins/Cardinal/res/distrho.svg diff --git a/plugins/Cardinal/plugin.json b/plugins/Cardinal/plugin.json index 80c8f6b..22f67f4 100644 --- a/plugins/Cardinal/plugin.json +++ b/plugins/Cardinal/plugin.json @@ -11,5 +11,25 @@ "manualUrl": "https://github.com/DISTRHO/Cardinal/wiki", "sourceUrl": "https://github.com/DISTRHO/Cardinal", "changelogUrl": "", - "modules": [] + "modules": + [ + { + "slug": "HostParameters", + "disabled": false, + "name": "Host Parameters", + "description": "Exposes host-controlled plugin parameters as module", + "tags": [ + "Utility" + ] + }, + { + "slug": "HostTime", + "disabled": false, + "name": "Host Time", + "description": "Exposes host-provided timing information as module", + "tags": [ + "Utility" + ] + } + ] } diff --git a/plugins/Cardinal/res/HostParameters.svg b/plugins/Cardinal/res/HostParameters.svg new file mode 100644 index 0000000..6d5ce0c --- /dev/null +++ b/plugins/Cardinal/res/HostParameters.svg @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/Cardinal/res/distrho.svg b/plugins/Cardinal/res/distrho.svg new file mode 100644 index 0000000..30b9d9b --- /dev/null +++ b/plugins/Cardinal/res/distrho.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Cardinal/src/HostParameters.cpp b/plugins/Cardinal/src/HostParameters.cpp index 75f2de6..c56cd5c 100644 --- a/plugins/Cardinal/src/HostParameters.cpp +++ b/plugins/Cardinal/src/HostParameters.cpp @@ -17,6 +17,26 @@ #include "plugin.hpp" +// ----------------------------------------------------------------------------------------------------------- +// from PluginContext.hpp + +namespace DISTRHO { + +static constexpr const uint kModuleParameters = 24; + +struct CardinalPluginContext : rack::Context { + uint32_t bufferSize; + double sampleRate; + float parameters[kModuleParameters]; + // more stuff follows, but we dont care.. +}; + +} + +using namespace DISTRHO; + +// ----------------------------------------------------------------------------------------------------------- + struct HostParameters : Module { enum ParamIds { NUM_PARAMS @@ -25,18 +45,55 @@ struct HostParameters : Module { NUM_INPUTS }; enum OutputIds { - NUM_OUTPUTS + NUM_OUTPUTS = 24 }; enum LightIds { NUM_LIGHTS }; - HostParameters() { + rack::dsp::SlewLimiter parameters[kModuleParameters]; + float sampleTime = 0.0f; + + HostParameters() + { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); + + CardinalPluginContext* const pcontext = reinterpret_cast(APP); + + if (pcontext == nullptr) + throw rack::Exception("Plugin context is null."); + + const float fsampleRate = static_cast(pcontext->sampleRate); + SampleRateChangeEvent e = { + fsampleRate, + 1.0f / fsampleRate + }; + onSampleRateChange(e); } - void process(const ProcessArgs&) override { - // TODO + void process(const ProcessArgs&) override + { + if (CardinalPluginContext* const pcontext = reinterpret_cast(APP)) + { + for (uint i=0; iparameters[i])); + } + } + + void onSampleRateChange(const SampleRateChangeEvent& e) override + { + if (CardinalPluginContext* const pcontext = reinterpret_cast(APP)) + { + const double fall = 1.0 / (double(pcontext->bufferSize) / e.sampleRate); + + for (uint i=0; iwindow->loadSvg(asset::plugin(pluginInstance, "res/HostParameters.svg"))); + + addChild(createWidget(Vec(RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + + const float startX = 10.0f; + const float startY = 170.0f; + const float padding = 30.0f; + + for (int i=0; i<24; ++i) + { + const float x = startX + int(i / 6) * padding; + const float y = startY + int(i % 6) * padding; + addOutput(createOutput(Vec(x, y), module, i)); + } } }; diff --git a/plugins/plugins.cpp b/plugins/plugins.cpp index df7bf86..925c744 100644 --- a/plugins/plugins.cpp +++ b/plugins/plugins.cpp @@ -769,9 +769,8 @@ static void initStatic__Cardinal() const StaticPluginLoader spl(p, "Cardinal"); if (spl.ok()) { - // TODO implement these - // p->addModel(modelHostParameters); - // p->addModel(modelHostTime); + p->addModel(modelHostParameters); + p->addModel(modelHostTime); } } diff --git a/src/CardinalPlugin.cpp b/src/CardinalPlugin.cpp index 99d3d6d..ff932cf 100644 --- a/src/CardinalPlugin.cpp +++ b/src/CardinalPlugin.cpp @@ -119,7 +119,6 @@ static const Initializer& getInitializerInstance() class CardinalPlugin : public CardinalBasePlugin { - CardinalPluginContext* const fContext; float* fAudioBufferIn; float* fAudioBufferOut; std::string fAutosavePath; @@ -129,15 +128,15 @@ class CardinalPlugin : public CardinalBasePlugin rack::audio::Device* fCurrentDevice; Mutex fDeviceMutex; - float fParameters[kModuleParameters + kWindowParameterCount]; + float fWindowParameters[kWindowParameterCount]; struct ScopedContext { const MutexLocker cml; ScopedContext(const CardinalPlugin* const plugin) - : cml(plugin->contextMutex) + : cml(plugin->context->mutex) { - rack::contextSet(plugin->fContext); + rack::contextSet(plugin->context); } ~ScopedContext() @@ -149,18 +148,15 @@ class CardinalPlugin : public CardinalBasePlugin public: CardinalPlugin() : CardinalBasePlugin(kModuleParameters + kWindowParameterCount, 0, 1), - fContext(new CardinalPluginContext(this)), fAudioBufferIn(nullptr), fAudioBufferOut(nullptr), fIsActive(false), fCurrentDevice(nullptr) { - std::memset(fParameters, 0, sizeof(fParameters)); - - fParameters[kModuleParameters + kWindowParameterCableOpacity] = 50.0f; - fParameters[kModuleParameters + kWindowParameterCableTension] = 50.0f; - fParameters[kModuleParameters + kWindowParameterRackBrightness] = 100.0f; - fParameters[kModuleParameters + kWindowParameterHaloBrightness] = 25.0f; + fWindowParameters[kWindowParameterCableOpacity] = 50.0f; + fWindowParameters[kWindowParameterCableTension] = 50.0f; + fWindowParameters[kWindowParameterRackBrightness] = 100.0f; + fWindowParameters[kWindowParameterHaloBrightness] = 25.0f; // create unique temporary path for this instance try { @@ -183,18 +179,18 @@ public: const ScopedContext sc(this); - fContext->engine = new rack::engine::Engine; - fContext->history = new rack::history::State; - fContext->patch = new rack::patch::Manager; - fContext->patch->autosavePath = fAutosavePath; - fContext->patch->templatePath = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR "template.vcv"; + context->engine = new rack::engine::Engine; + context->history = new rack::history::State; + context->patch = new rack::patch::Manager; + context->patch->autosavePath = fAutosavePath; + context->patch->templatePath = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR "template.vcv"; - fContext->event = new rack::widget::EventState; - fContext->scene = new rack::app::Scene; - fContext->event->rootWidget = fContext->scene; + context->event = new rack::widget::EventState; + context->scene = new rack::app::Scene; + context->event->rootWidget = context->scene; - fContext->patch->loadTemplate(); - fContext->engine->startFallbackThread(); + context->patch->loadTemplate(); + context->engine->startFallbackThread(); } ~CardinalPlugin() override @@ -202,13 +198,13 @@ public: { const ScopedContext sc(this); /* - delete fContext->scene; - fContext->scene = nullptr; + delete context->scene; + context->scene = nullptr; - delete fContext->event; - fContext->event = nullptr; + delete context->event; + context->event = nullptr; */ - delete fContext; + delete context; } if (! fAutosavePath.empty()) @@ -217,7 +213,7 @@ public: CardinalPluginContext* getRackContext() const noexcept { - return fContext; + return context; } protected: @@ -365,14 +361,34 @@ protected: /* -------------------------------------------------------------------------------------------------------- * Internal data */ - float getParameterValue(const uint32_t index) const override + float getParameterValue(uint32_t index) const override { - return fParameters[index]; + if (index < kModuleParameters) + return context->parameters[index]; + + index -= kModuleParameters; + + if (index < kWindowParameterCount) + return fWindowParameters[index]; + + return 0.0f; } - void setParameterValue(const uint32_t index, float value) override + void setParameterValue(uint32_t index, float value) override { - fParameters[index] = value; + if (index < kModuleParameters) + { + context->parameters[index] = value; + return; + } + + index -= kModuleParameters; + + if (index < kWindowParameterCount) + { + fWindowParameters[index] = value; + return; + } } String getState(const char* const key) const override @@ -387,9 +403,9 @@ protected: { const ScopedContext sc(this); - fContext->engine->prepareSave(); - fContext->patch->saveAutosave(); - fContext->patch->cleanAutosave(); + context->engine->prepareSave(); + context->patch->saveAutosave(); + context->patch->cleanAutosave(); data = rack::system::archiveDirectory(fAutosavePath, 1); } @@ -412,7 +428,7 @@ protected: rack::system::createDirectories(fAutosavePath); rack::system::unarchiveToDirectory(data, fAutosavePath); - fContext->patch->loadAutosave(); + context->patch->loadAutosave(); } /* -------------------------------------------------------------------------------------------------------- @@ -450,8 +466,8 @@ protected: void run(const float** const inputs, float** const outputs, const uint32_t frames) override { /* - fContext->engine->setFrame(getTimePosition().frame); - fContext->engine->stepBlock(frames); + context->engine->setFrame(getTimePosition().frame); + context->engine->stepBlock(frames); */ const MutexLocker cml(fDeviceMutex); @@ -482,13 +498,6 @@ protected: } } - /* - void sampleRateChanged(const double newSampleRate) override - { - fContext->engine->setSampleRate(newSampleRate); - } - */ - // ------------------------------------------------------------------------------------------------------- private: diff --git a/src/CardinalUI.cpp b/src/CardinalUI.cpp index c47da0d..76ddc40 100644 --- a/src/CardinalUI.cpp +++ b/src/CardinalUI.cpp @@ -63,7 +63,7 @@ class CardinalUI : public UI, ScopedContext(CardinalUI* const ui) : context(ui->fContext), - cml(context->plugin->contextMutex) + cml(context->mutex) { rack::contextSet(context); WindowParametersRestore(context->window); @@ -71,7 +71,7 @@ class CardinalUI : public UI, ScopedContext(CardinalUI* const ui, const int mods) : context(ui->fContext), - cml(context->plugin->contextMutex) + cml(context->mutex) { rack::contextSet(context); rack::window::WindowMods(context->window, mods); diff --git a/src/PluginContext.hpp b/src/PluginContext.hpp index 6b62074..bfbfae6 100644 --- a/src/PluginContext.hpp +++ b/src/PluginContext.hpp @@ -33,27 +33,51 @@ START_NAMESPACE_DISTRHO static constexpr const uint kModuleParameters = 24; +// ----------------------------------------------------------------------------------------------------------- + +struct CardinalPluginContext : rack::Context { + uint32_t bufferSize; + double sampleRate; + float parameters[kModuleParameters]; + + Mutex mutex; + Plugin* const plugin; + + CardinalPluginContext(Plugin* const p) + : bufferSize(p->getBufferSize()), + sampleRate(p->getSampleRate()), + plugin(p) + { + std::memset(parameters, 0, sizeof(parameters)); + } +}; + +// ----------------------------------------------------------------------------------------------------------- + class CardinalBasePlugin : public Plugin { public: + CardinalPluginContext* const context; + CardinalBasePlugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount) - : Plugin(parameterCount, programCount, stateCount) {} + : Plugin(parameterCount, programCount, stateCount), + context(new CardinalPluginContext(this)) {} ~CardinalBasePlugin() override {} virtual bool isActive() const noexcept = 0; virtual bool canAssignDevice() const noexcept = 0; virtual void assignDevice(rack::audio::Device* dev) noexcept = 0; virtual bool clearDevice(rack::audio::Device* dev) noexcept = 0; - // ensure context validity through UI and setState - Mutex contextMutex; -}; - -// ----------------------------------------------------------------------------------------------------------- - -struct CardinalPluginContext : rack::Context { - CardinalBasePlugin* const plugin; +protected: + void bufferSizeChanged(const uint32_t newBufferSize) override + { + context->bufferSize = newBufferSize; + } - CardinalPluginContext(CardinalBasePlugin* const p) - : plugin(p) {} + void sampleRateChanged(const double newSampleRate) override + { + context->sampleRate = newSampleRate; + // context->engine->setSampleRate(newSampleRate); + } }; // ----------------------------------------------------------------------------------------------------------- @@ -144,7 +168,7 @@ struct CardinalAudioDriver : rack::audio::Driver { CardinalPluginContext* const pluginContext = reinterpret_cast(port->context); DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr); - CardinalBasePlugin* const plugin = pluginContext->plugin; + CardinalBasePlugin* const plugin = reinterpret_cast(pluginContext->plugin); DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr); if (! plugin->canAssignDevice()) @@ -168,7 +192,7 @@ struct CardinalAudioDriver : rack::audio::Driver { CardinalPluginContext* const pluginContext = reinterpret_cast(port->context); DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,); - CardinalBasePlugin* const plugin = pluginContext->plugin; + CardinalBasePlugin* const plugin = reinterpret_cast(pluginContext->plugin); DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,); if (plugin->clearDevice(device)) diff --git a/src/template.vcv b/src/template.vcv index 6791d96..73b50de 100644 --- a/src/template.vcv +++ b/src/template.vcv @@ -1,5 +1,11 @@ { "version": "2.0", + "unsaved": true, + "zoom": 1.0, + "gridOffset": [ + -3.5333333015441895, + -0.078947365283966064 + ], "modules": [ { "id": 1, @@ -12,10 +18,11 @@ "id": 0 } ], + "rightModuleId": 4245168092954973, "data": { "audio": { "driver": 0, - "deviceName": "Plugin Device", + "deviceName": "Cardinal", "sampleRate": 48000.0, "blockSize": 512, "inputOffset": 0, @@ -27,8 +34,20 @@ 0, 0 ] + }, + { + "id": 4245168092954973, + "plugin": "Cardinal", + "model": "HostParameters", + "version": "2.0", + "params": [], + "leftModuleId": 1, + "pos": [ + 5, + 0 + ] } ], "cables": [], "masterModuleId": 1 -} +} \ No newline at end of file