| @@ -32,7 +32,8 @@ | |||||
| #include <osdialog.h> | #include <osdialog.h> | ||||
| #include "PluginContext.hpp" | #include "PluginContext.hpp" | ||||
| #include "extra/Mutex.hpp" | |||||
| #include "WindowParameters.hpp" | |||||
| #include "extra/Base64.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| namespace plugin { | namespace plugin { | ||||
| @@ -128,8 +129,13 @@ class CardinalPlugin : public CardinalBasePlugin | |||||
| rack::audio::Device* fCurrentDevice; | rack::audio::Device* fCurrentDevice; | ||||
| Mutex fDeviceMutex; | Mutex fDeviceMutex; | ||||
| float fParameters[kWindowParameterCount]; | |||||
| struct ScopedContext { | struct ScopedContext { | ||||
| ScopedContext(CardinalPlugin* const plugin) | |||||
| const MutexLocker cml; | |||||
| ScopedContext(const CardinalPlugin* const plugin) | |||||
| : cml(plugin->contextMutex) | |||||
| { | { | ||||
| rack::contextSet(plugin->fContext); | rack::contextSet(plugin->fContext); | ||||
| } | } | ||||
| @@ -142,13 +148,18 @@ class CardinalPlugin : public CardinalBasePlugin | |||||
| public: | public: | ||||
| CardinalPlugin() | CardinalPlugin() | ||||
| : CardinalBasePlugin(0, 0, 0), | |||||
| : CardinalBasePlugin(kWindowParameterCount, 0, 1), | |||||
| fContext(new CardinalPluginContext(this)), | fContext(new CardinalPluginContext(this)), | ||||
| fAudioBufferIn(nullptr), | fAudioBufferIn(nullptr), | ||||
| fAudioBufferOut(nullptr), | fAudioBufferOut(nullptr), | ||||
| fIsActive(false), | fIsActive(false), | ||||
| fCurrentDevice(nullptr) | fCurrentDevice(nullptr) | ||||
| { | { | ||||
| fParameters[kWindowParameterCableOpacity] = 50.0f; | |||||
| fParameters[kWindowParameterCableTension] = 50.0f; | |||||
| fParameters[kWindowParameterRackBrightness] = 100.0f; | |||||
| fParameters[kWindowParameterHaloBrightness] = 25.0f; | |||||
| // create unique temporary path for this instance | // create unique temporary path for this instance | ||||
| try { | try { | ||||
| char uidBuf[24]; | char uidBuf[24]; | ||||
| @@ -232,60 +243,38 @@ protected: | |||||
| /* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
| * Information */ | * Information */ | ||||
| /** | |||||
| Get the plugin label. | |||||
| A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers. | |||||
| */ | |||||
| const char* getLabel() const override | const char* getLabel() const override | ||||
| { | { | ||||
| return "Cardinal"; | return "Cardinal"; | ||||
| } | } | ||||
| /** | |||||
| Get an extensive comment/description about the plugin. | |||||
| */ | |||||
| const char* getDescription() const override | const char* getDescription() const override | ||||
| { | { | ||||
| return "..."; | |||||
| return "" | |||||
| "Cardinal is an open-source self-contained special plugin version of VCVRack, using DPF.\n" | |||||
| "It is NOT an official VCV project, and it is not affiliated with it in any way.\n"; | |||||
| } | } | ||||
| /** | |||||
| Get the plugin author/maker. | |||||
| */ | |||||
| const char* getMaker() const override | const char* getMaker() const override | ||||
| { | { | ||||
| return "DISTRHO"; | return "DISTRHO"; | ||||
| } | } | ||||
| /** | |||||
| Get the plugin homepage. | |||||
| */ | |||||
| const char* getHomePage() const override | const char* getHomePage() const override | ||||
| { | { | ||||
| return "https://github.com/DISTRHO/Cardinal"; | return "https://github.com/DISTRHO/Cardinal"; | ||||
| } | } | ||||
| /** | |||||
| Get the plugin license name (a single line of text). | |||||
| For commercial plugins this should return some short copyright information. | |||||
| */ | |||||
| const char* getLicense() const override | const char* getLicense() const override | ||||
| { | { | ||||
| return "ISC"; | |||||
| return "GPLv3+"; | |||||
| } | } | ||||
| /** | |||||
| Get the plugin version, in hexadecimal. | |||||
| */ | |||||
| uint32_t getVersion() const override | uint32_t getVersion() const override | ||||
| { | { | ||||
| return d_version(1, 0, 0); | |||||
| return d_version(2, 0, 0); | |||||
| } | } | ||||
| /** | |||||
| Get the plugin unique Id. | |||||
| This value is used by LADSPA, DSSI and VST plugin formats. | |||||
| */ | |||||
| int64_t getUniqueId() const override | int64_t getUniqueId() const override | ||||
| { | { | ||||
| return d_cconst('d', 'C', 'd', 'n'); | return d_cconst('d', 'C', 'd', 'n'); | ||||
| @@ -294,9 +283,110 @@ protected: | |||||
| /* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
| * Init */ | * Init */ | ||||
| void initParameter(const uint32_t index, Parameter& parameter) override | |||||
| { | |||||
| switch (index) | |||||
| { | |||||
| case kWindowParameterCableOpacity: | |||||
| parameter.name = "Cable Opacity"; | |||||
| parameter.symbol = "cableOpacity"; | |||||
| parameter.unit = "%"; | |||||
| parameter.hints = kParameterIsAutomable; | |||||
| parameter.ranges.def = 50.0f; | |||||
| parameter.ranges.min = 0.0f; | |||||
| parameter.ranges.max = 100.0f; | |||||
| break; | |||||
| case kWindowParameterCableTension: | |||||
| parameter.name = "Cable Tension"; | |||||
| parameter.symbol = "cableTension"; | |||||
| parameter.unit = "%"; | |||||
| parameter.hints = kParameterIsAutomable; | |||||
| parameter.ranges.def = 50.0f; | |||||
| parameter.ranges.min = 0.0f; | |||||
| parameter.ranges.max = 100.0f; | |||||
| break; | |||||
| case kWindowParameterRackBrightness: | |||||
| parameter.name = "Rack Brightness"; | |||||
| parameter.symbol = "rackBrightness"; | |||||
| parameter.unit = "%"; | |||||
| parameter.hints = kParameterIsAutomable; | |||||
| parameter.ranges.def = 100.0f; | |||||
| parameter.ranges.min = 0.0f; | |||||
| parameter.ranges.max = 100.0f; | |||||
| break; | |||||
| case kWindowParameterHaloBrightness: | |||||
| parameter.name = "Halo Brightness"; | |||||
| parameter.symbol = "haloBrightness"; | |||||
| parameter.unit = "%"; | |||||
| parameter.hints = kParameterIsAutomable; | |||||
| parameter.ranges.def = 25.0f; | |||||
| parameter.ranges.min = 0.0f; | |||||
| parameter.ranges.max = 100.0f; | |||||
| break; | |||||
| } | |||||
| } | |||||
| void initState(const uint32_t index, String& stateKey, String& defaultStateValue) override | |||||
| { | |||||
| DISTRHO_SAFE_ASSERT_RETURN(index == 0,); | |||||
| stateKey = "patch"; | |||||
| defaultStateValue = ""; | |||||
| } | |||||
| /* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
| * Internal data */ | * Internal data */ | ||||
| float getParameterValue(const uint32_t index) const override | |||||
| { | |||||
| return fParameters[index]; | |||||
| } | |||||
| void setParameterValue(const uint32_t index, float value) override | |||||
| { | |||||
| fParameters[index] = value; | |||||
| } | |||||
| String getState(const char* const key) const override | |||||
| { | |||||
| if (std::strcmp(key, "patch") != 0) | |||||
| return String(); | |||||
| if (fAutosavePath.empty()) | |||||
| return String(); | |||||
| std::vector<uint8_t> data; | |||||
| { | |||||
| const ScopedContext sc(this); | |||||
| fContext->engine->prepareSave(); | |||||
| fContext->patch->saveAutosave(); | |||||
| fContext->patch->cleanAutosave(); | |||||
| data = rack::system::archiveDirectory(fAutosavePath, 1); | |||||
| } | |||||
| return String::asBase64(data.data(), data.size()); | |||||
| } | |||||
| void setState(const char* const key, const char* const value) override | |||||
| { | |||||
| if (std::strcmp(key, "patch") != 0) | |||||
| return; | |||||
| if (fAutosavePath.empty()) | |||||
| return; | |||||
| const std::vector<uint8_t> data(d_getChunkFromBase64String(value)); | |||||
| const ScopedContext sc(this); | |||||
| rack::system::removeRecursively(fAutosavePath); | |||||
| rack::system::createDirectories(fAutosavePath); | |||||
| rack::system::unarchiveToDirectory(data, fAutosavePath); | |||||
| fContext->patch->loadAutosave(); | |||||
| } | |||||
| /* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
| * Process */ | * Process */ | ||||
| @@ -329,9 +419,6 @@ protected: | |||||
| fAudioBufferIn = fAudioBufferOut = nullptr; | fAudioBufferIn = fAudioBufferOut = nullptr; | ||||
| } | } | ||||
| /** | |||||
| Run/process function for plugins without MIDI input. | |||||
| */ | |||||
| void run(const float** const inputs, float** const outputs, const uint32_t frames) override | void run(const float** const inputs, float** const outputs, const uint32_t frames) override | ||||
| { | { | ||||
| /* | /* | ||||
| @@ -340,8 +427,9 @@ protected: | |||||
| */ | */ | ||||
| const MutexLocker cml(fDeviceMutex); | const MutexLocker cml(fDeviceMutex); | ||||
| // const MutexTryLocker cmtl(fPatchMutex); | |||||
| if (fCurrentDevice == nullptr) | |||||
| if (fCurrentDevice == nullptr /*|| cmtl.wasNotLocked()*/) | |||||
| { | { | ||||
| std::memset(outputs[0], 0, sizeof(float)*frames); | std::memset(outputs[0], 0, sizeof(float)*frames); | ||||
| std::memset(outputs[1], 0, sizeof(float)*frames); | std::memset(outputs[1], 0, sizeof(float)*frames); | ||||
| @@ -22,9 +22,13 @@ | |||||
| #include <ui/MenuItem.hpp> | #include <ui/MenuItem.hpp> | ||||
| #include <window/Window.hpp> | #include <window/Window.hpp> | ||||
| #include "PluginContext.hpp" | |||||
| #ifdef NDEBUG | |||||
| # undef DEBUG | |||||
| #endif | |||||
| #include "DistrhoUI.hpp" | #include "DistrhoUI.hpp" | ||||
| #include "PluginContext.hpp" | |||||
| #include "WindowParameters.hpp" | |||||
| #include "ResizeHandle.hpp" | #include "ResizeHandle.hpp" | ||||
| GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window) { return nullptr; } | GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window) { return nullptr; } | ||||
| @@ -45,20 +49,29 @@ START_NAMESPACE_DISTRHO | |||||
| CardinalPluginContext* getRackContextFromPlugin(void* ptr); | CardinalPluginContext* getRackContextFromPlugin(void* ptr); | ||||
| class CardinalUI : public UI | |||||
| class CardinalUI : public UI, | |||||
| public WindowParametersCallback | |||||
| { | { | ||||
| CardinalPluginContext* const fContext; | CardinalPluginContext* const fContext; | ||||
| rack::math::Vec fLastMousePos; | rack::math::Vec fLastMousePos; | ||||
| ResizeHandle fResizeHandle; | ResizeHandle fResizeHandle; | ||||
| WindowParameters fWindowParameters; | |||||
| struct ScopedContext { | struct ScopedContext { | ||||
| CardinalPluginContext* const context; | |||||
| const MutexLocker cml; | |||||
| ScopedContext(CardinalUI* const ui) | ScopedContext(CardinalUI* const ui) | ||||
| : context(ui->fContext), | |||||
| cml(context->plugin->contextMutex) | |||||
| { | { | ||||
| rack::contextSet(ui->fContext); | |||||
| rack::contextSet(context); | |||||
| WindowParametersRestore(context->window); | |||||
| } | } | ||||
| ~ScopedContext() | ~ScopedContext() | ||||
| { | { | ||||
| WindowParametersSave(context->window); | |||||
| rack::contextSet(nullptr); | rack::contextSet(nullptr); | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -72,58 +85,63 @@ public: | |||||
| if (isResizable()) | if (isResizable()) | ||||
| fResizeHandle.hide(); | fResizeHandle.hide(); | ||||
| const ScopedContext sc(this); | |||||
| fContext->window = new rack::window::Window; | |||||
| fContext->event = new rack::widget::EventState; | |||||
| fContext->scene = new rack::app::Scene; | |||||
| fContext->event->rootWidget = fContext->scene; | |||||
| { | |||||
| const ScopedContext sc(this); | |||||
| fContext->window = new rack::window::Window; | |||||
| rack::window::WindowInit(fContext->window, this); | |||||
| fContext->event = new rack::widget::EventState; | |||||
| fContext->scene = new rack::app::Scene; | |||||
| fContext->event->rootWidget = fContext->scene; | |||||
| // Hide non-wanted menu entries | |||||
| typedef rack::ui::Button rButton; | |||||
| // typedef rack::ui::MenuItem rMenuItem; | |||||
| typedef rack::widget::Widget rWidget; | |||||
| typedef std::list<rWidget*>::iterator rWidgetIterator; | |||||
| rack::window::WindowInit(fContext->window, this); | |||||
| rWidget* const layout = fContext->scene->menuBar->children.front(); | |||||
| // Hide non-wanted menu entries | |||||
| typedef rack::ui::Button rButton; | |||||
| // typedef rack::ui::MenuItem rMenuItem; | |||||
| typedef rack::widget::Widget rWidget; | |||||
| typedef std::list<rWidget*>::iterator rWidgetIterator; | |||||
| for (rWidgetIterator it = layout->children.begin(); it != layout->children.end(); ++it) | |||||
| { | |||||
| if (rButton* const button = reinterpret_cast<rButton*>(*it)) | |||||
| rWidget* const layout = fContext->scene->menuBar->children.front(); | |||||
| for (rWidgetIterator it = layout->children.begin(); it != layout->children.end(); ++it) | |||||
| { | { | ||||
| /* FIXME this doesnt work | |||||
| if (button->text == "Engine") | |||||
| if (rButton* const button = reinterpret_cast<rButton*>(*it)) | |||||
| { | { | ||||
| for (rWidgetIterator it2 = button->children.begin(); it2 != button->children.end(); ++it2) | |||||
| /* FIXME this doesnt work | |||||
| if (button->text == "Engine") | |||||
| { | { | ||||
| if (rMenuItem* const item = reinterpret_cast<rMenuItem*>(*it2)) | |||||
| for (rWidgetIterator it2 = button->children.begin(); it2 != button->children.end(); ++it2) | |||||
| { | { | ||||
| if (item->text == "Sample rate") | |||||
| if (rMenuItem* const item = reinterpret_cast<rMenuItem*>(*it2)) | |||||
| { | { | ||||
| button->children.erase(it2); | |||||
| delete button; | |||||
| break; | |||||
| if (item->text == "Sample rate") | |||||
| { | |||||
| button->children.erase(it2); | |||||
| delete button; | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| */ | |||||
| if (button->text == "Library") | |||||
| { | |||||
| layout->children.erase(it); | |||||
| delete button; | |||||
| break; | |||||
| */ | |||||
| if (button->text == "Library") | |||||
| { | |||||
| layout->children.erase(it); | |||||
| delete button; | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| // we need to reload current patch for things to show on screen :( | |||||
| // FIXME always save | |||||
| if (! fContext->patch->hasAutosave()) | |||||
| fContext->patch->saveAutosave(); | |||||
| fContext->patch->loadAutosave(); | |||||
| } | } | ||||
| // we need to reload current patch for things to show on screen :( | |||||
| // FIXME always save | |||||
| if (! fContext->patch->hasAutosave()) | |||||
| fContext->patch->saveAutosave(); | |||||
| fContext->patch->loadAutosave(); | |||||
| WindowParametersSetCallback(fContext->window, this); | |||||
| } | } | ||||
| ~CardinalUI() override | ~CardinalUI() override | ||||
| @@ -143,7 +161,6 @@ public: | |||||
| void onNanoDisplay() override | void onNanoDisplay() override | ||||
| { | { | ||||
| const ScopedContext sc(this); | const ScopedContext sc(this); | ||||
| fContext->window->step(); | fContext->window->step(); | ||||
| } | } | ||||
| @@ -152,6 +169,35 @@ public: | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void WindowParametersChanged(const WindowParameterList param, const float value) override | |||||
| { | |||||
| float mult; | |||||
| switch (param) | |||||
| { | |||||
| case kWindowParameterCableOpacity: | |||||
| mult = 100.0f; | |||||
| fWindowParameters.cableOpacity = value; | |||||
| break; | |||||
| case kWindowParameterCableTension: | |||||
| mult = 100.0f; | |||||
| fWindowParameters.cableTension = value; | |||||
| break; | |||||
| case kWindowParameterRackBrightness: | |||||
| mult = 100.0f; | |||||
| fWindowParameters.rackBrightness = value; | |||||
| break; | |||||
| case kWindowParameterHaloBrightness: | |||||
| mult = 100.0f; | |||||
| fWindowParameters.haloBrightness = value; | |||||
| break; | |||||
| default: | |||||
| return; | |||||
| } | |||||
| setParameterValue((uint)param, value * mult); | |||||
| } | |||||
| protected: | protected: | ||||
| /* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
| * DSP/Plugin Callbacks */ | * DSP/Plugin Callbacks */ | ||||
| @@ -160,7 +206,30 @@ protected: | |||||
| A parameter has changed on the plugin side. | A parameter has changed on the plugin side. | ||||
| This is called by the host to inform the UI about parameter changes. | This is called by the host to inform the UI about parameter changes. | ||||
| */ | */ | ||||
| void parameterChanged(uint32_t index, float value) override | |||||
| void parameterChanged(const uint32_t index, const float value) override | |||||
| { | |||||
| switch (index) | |||||
| { | |||||
| case kWindowParameterCableOpacity: | |||||
| fWindowParameters.cableOpacity = value / 100.0f; | |||||
| break; | |||||
| case kWindowParameterCableTension: | |||||
| fWindowParameters.cableTension = value / 100.0f; | |||||
| break; | |||||
| case kWindowParameterRackBrightness: | |||||
| fWindowParameters.rackBrightness = value / 100.0f; | |||||
| break; | |||||
| case kWindowParameterHaloBrightness: | |||||
| fWindowParameters.haloBrightness = value / 100.0f; | |||||
| break; | |||||
| default: | |||||
| return; | |||||
| } | |||||
| WindowParametersSetValues(fContext->window, fWindowParameters); | |||||
| } | |||||
| void stateChanged(const char* key, const char* value) override | |||||
| { | { | ||||
| } | } | ||||
| @@ -25,6 +25,8 @@ | |||||
| #define DISTRHO_PLUGIN_HAS_UI 1 | #define DISTRHO_PLUGIN_HAS_UI 1 | ||||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | #define DISTRHO_PLUGIN_NUM_INPUTS 2 | ||||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | ||||
| #define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||||
| #define DISTRHO_PLUGIN_WANT_STATE 1 | |||||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | ||||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | ||||
| // #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | // #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | ||||
| @@ -25,6 +25,7 @@ | |||||
| #endif | #endif | ||||
| #include "DistrhoPlugin.hpp" | #include "DistrhoPlugin.hpp" | ||||
| #include "extra/Mutex.hpp" | |||||
| START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
| @@ -39,6 +40,9 @@ public: | |||||
| virtual bool canAssignDevice() const noexcept = 0; | virtual bool canAssignDevice() const noexcept = 0; | ||||
| virtual void assignDevice(rack::audio::Device* dev) noexcept = 0; | virtual void assignDevice(rack::audio::Device* dev) noexcept = 0; | ||||
| virtual bool clearDevice(rack::audio::Device* dev) noexcept = 0; | virtual bool clearDevice(rack::audio::Device* dev) noexcept = 0; | ||||
| // ensure context validity through UI and setState | |||||
| Mutex contextMutex; | |||||
| }; | }; | ||||
| // ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
| @@ -110,7 +114,7 @@ struct CardinalAudioDriver : rack::audio::Driver { | |||||
| std::vector<int> getDeviceIds() override | std::vector<int> getDeviceIds() override | ||||
| { | { | ||||
| return std::vector<int>({ 0 }); | |||||
| return std::vector<int>({ 1 }); | |||||
| } | } | ||||
| std::string getDeviceName(int) override | std::string getDeviceName(int) override | ||||
| @@ -19,6 +19,7 @@ | |||||
| #endif | #endif | ||||
| #include "DistrhoUI.hpp" | #include "DistrhoUI.hpp" | ||||
| #include "WindowParameters.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| namespace window { | namespace window { | ||||
| @@ -67,13 +68,19 @@ std::shared_ptr<Image> Image::load(const std::string& filename) { | |||||
| } | } | ||||
| struct WindowParams { | |||||
| float rackBrightness = 1.0f; | |||||
| }; | |||||
| struct Window::Internal { | struct Window::Internal { | ||||
| int mods = 0; | |||||
| DISTRHO_NAMESPACE::UI* ui = nullptr; | DISTRHO_NAMESPACE::UI* ui = nullptr; | ||||
| math::Vec size = minWindowSize; | |||||
| DISTRHO_NAMESPACE::WindowParameters params; | |||||
| DISTRHO_NAMESPACE::WindowParametersCallback* callback = nullptr; | |||||
| math::Vec size = minWindowSize; | |||||
| std::string lastWindowTitle; | std::string lastWindowTitle; | ||||
| int mods = 0; | |||||
| int frame = 0; | int frame = 0; | ||||
| int frameSwapInterval = 1; | int frameSwapInterval = 1; | ||||
| double monitorRefreshRate = 60.0; // FIXME | double monitorRefreshRate = 60.0; // FIXME | ||||
| @@ -107,6 +114,9 @@ void WindowInit(Window* const window, DISTRHO_NAMESPACE::UI* const ui) | |||||
| window->uiFont = window->loadFont(asset::system("res/fonts/DejaVuSans.ttf")); | window->uiFont = window->loadFont(asset::system("res/fonts/DejaVuSans.ttf")); | ||||
| bndSetFont(window->uiFont->handle); | bndSetFont(window->uiFont->handle); | ||||
| // Init settings | |||||
| WindowParametersRestore(window); | |||||
| if (APP->scene) { | if (APP->scene) { | ||||
| widget::Widget::ContextCreateEvent e; | widget::Widget::ContextCreateEvent e; | ||||
| APP->scene->onContextCreate(e); | APP->scene->onContextCreate(e); | ||||
| @@ -321,3 +331,59 @@ bool& Window::fbDirtyOnSubpixelChange() { | |||||
| } // namespace window | } // namespace window | ||||
| } // namespace rack | } // namespace rack | ||||
| START_NAMESPACE_DISTRHO | |||||
| void WindowParametersSave(rack::window::Window* const window) | |||||
| { | |||||
| if (d_isNotEqual(window->internal->params.cableOpacity, rack::settings::cableOpacity)) | |||||
| { | |||||
| window->internal->params.cableOpacity = rack::settings::cableOpacity; | |||||
| if (window->internal->callback != nullptr) | |||||
| window->internal->callback->WindowParametersChanged(kWindowParameterCableOpacity, | |||||
| rack::settings::cableOpacity); | |||||
| } | |||||
| if (d_isNotEqual(window->internal->params.cableTension, rack::settings::cableTension)) | |||||
| { | |||||
| window->internal->params.cableTension = rack::settings::cableTension; | |||||
| if (window->internal->callback != nullptr) | |||||
| window->internal->callback->WindowParametersChanged(kWindowParameterCableTension, | |||||
| rack::settings::cableTension); | |||||
| } | |||||
| if (d_isNotEqual(window->internal->params.rackBrightness, rack::settings::rackBrightness)) | |||||
| { | |||||
| window->internal->params.rackBrightness = rack::settings::rackBrightness; | |||||
| if (window->internal->callback != nullptr) | |||||
| window->internal->callback->WindowParametersChanged(kWindowParameterRackBrightness, | |||||
| rack::settings::rackBrightness); | |||||
| } | |||||
| if (d_isNotEqual(window->internal->params.haloBrightness, rack::settings::haloBrightness)) | |||||
| { | |||||
| window->internal->params.haloBrightness = rack::settings::haloBrightness; | |||||
| if (window->internal->callback != nullptr) | |||||
| window->internal->callback->WindowParametersChanged(kWindowParameterHaloBrightness, | |||||
| rack::settings::haloBrightness); | |||||
| } | |||||
| } | |||||
| void WindowParametersRestore(rack::window::Window* const window) | |||||
| { | |||||
| rack::settings::cableOpacity = window->internal->params.cableOpacity; | |||||
| rack::settings::cableTension = window->internal->params.cableTension; | |||||
| rack::settings::rackBrightness = window->internal->params.rackBrightness; | |||||
| rack::settings::haloBrightness = window->internal->params.haloBrightness; | |||||
| } | |||||
| void WindowParametersSetCallback(rack::window::Window* const window, WindowParametersCallback* const callback) | |||||
| { | |||||
| window->internal->callback = callback; | |||||
| } | |||||
| void WindowParametersSetValues(rack::window::Window* const window, const WindowParameters& params) | |||||
| { | |||||
| window->internal->params = params; | |||||
| } | |||||
| END_NAMESPACE_DISTRHO | |||||
| @@ -0,0 +1,60 @@ | |||||
| /* | |||||
| * DISTRHO Cardinal Plugin | |||||
| * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * This program is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU General Public License as | |||||
| * published by the Free Software Foundation; either version 3 of | |||||
| * the License, or any later version. | |||||
| * | |||||
| * This program is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| * GNU General Public License for more details. | |||||
| * | |||||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||||
| */ | |||||
| #pragma once | |||||
| #include "DistrhoUtils.hpp" | |||||
| namespace rack { | |||||
| namespace window { | |||||
| struct Window; | |||||
| } | |||||
| } | |||||
| START_NAMESPACE_DISTRHO | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| enum WindowParameterList { | |||||
| kWindowParameterCableOpacity, | |||||
| kWindowParameterCableTension, | |||||
| kWindowParameterRackBrightness, | |||||
| kWindowParameterHaloBrightness, | |||||
| kWindowParameterCount, | |||||
| }; | |||||
| struct WindowParameters { | |||||
| float cableOpacity = 0.5f; | |||||
| float cableTension = 0.5f; | |||||
| float rackBrightness = 1.0f; | |||||
| float haloBrightness = 0.25f; | |||||
| // KnobMode knobMode = KNOB_MODE_LINEAR; | |||||
| }; | |||||
| struct WindowParametersCallback { | |||||
| virtual ~WindowParametersCallback() {} | |||||
| virtual void WindowParametersChanged(WindowParameterList param, float value) = 0; | |||||
| }; | |||||
| void WindowParametersSave(rack::window::Window* window); | |||||
| void WindowParametersRestore(rack::window::Window* window); | |||||
| void WindowParametersSetCallback(rack::window::Window* window, WindowParametersCallback* callback); | |||||
| void WindowParametersSetValues(rack::window::Window* window, const WindowParameters& params); | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| END_NAMESPACE_DISTRHO | |||||