Browse Source

Finish createModel override, fix Ildaeil race condition on load

Signed-off-by: falkTX <falktx@falktx.com>
tags/22.02
falkTX 3 years ago
parent
commit
c4426fd125
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
5 changed files with 78 additions and 45 deletions
  1. +47
    -26
      include/helpers.hpp
  2. +12
    -13
      plugins/Cardinal/src/Ildaeil.cpp
  3. +7
    -1
      plugins/Makefile
  4. +4
    -0
      src/Makefile
  5. +8
    -5
      src/override/Engine.cpp

+ 47
- 26
include/helpers.hpp View File

@@ -32,67 +32,88 @@


#include <unordered_map> #include <unordered_map>


#include "DistrhoUtils.hpp"

namespace rack { namespace rack {


struct CardinalPluginModelHelper {
virtual ~CardinalPluginModelHelper() {}
virtual void createCachedModuleWidget(rack::engine::Module* m) = 0;
virtual void clearCachedModuleWidget(rack::engine::Module* m) = 0;
struct CardinalPluginModelHelper : plugin::Model {
virtual app::ModuleWidget* createModuleWidgetFromEngineLoad(engine::Module* m) = 0;
virtual void removeCachedModuleWidget(engine::Module* m) = 0;
}; };


template <class TModule, class TModuleWidget> template <class TModule, class TModuleWidget>
struct CardinalPluginModel : plugin::Model, CardinalPluginModelHelper
struct CardinalPluginModel : CardinalPluginModelHelper
{ {
std::unordered_map<rack::engine::Module*, app::ModuleWidget*> widgets;
std::unordered_map<engine::Module*, TModuleWidget*> widgets;
std::unordered_map<engine::Module*, bool> widgetNeedsDeletion;


rack::engine::Module* createModule() override
engine::Module* createModule() override
{ {
engine::Module* const m = new TModule; engine::Module* const m = new TModule;
m->model = this; m->model = this;
return m; return m;
} }


app::ModuleWidget* createModuleWidget(rack::engine::Module* const m) override
app::ModuleWidget* createModuleWidget(engine::Module* const m) override
{ {
TModule* tm = NULL;
if (m) {
assert(m->model == this);
TModule* tm = nullptr;
if (m)
{
DISTRHO_SAFE_ASSERT_RETURN(m->model == this, nullptr);
if (widgets.find(m) != widgets.end()) if (widgets.find(m) != widgets.end())
{
widgetNeedsDeletion[m] = false;
return widgets[m]; return widgets[m];
}
tm = dynamic_cast<TModule*>(m); tm = dynamic_cast<TModule*>(m);
} }
app::ModuleWidget* mw = new TModuleWidget(tm);
mw->setModel(this);
return mw;
app::ModuleWidget* const tmw = new TModuleWidget(tm);
tmw->setModel(this);
return tmw;
} }


void createCachedModuleWidget(rack::engine::Module* const m) override
app::ModuleWidget* createModuleWidgetFromEngineLoad(engine::Module* const m) override
{ {
assert(m != nullptr); if (m == nullptr) return;
assert(m->model == this); if (m->model != this) return;
DISTRHO_SAFE_ASSERT_RETURN(m != nullptr, nullptr);
DISTRHO_SAFE_ASSERT_RETURN(m->model == this, nullptr);

TModule* const tm = dynamic_cast<TModule*>(m); TModule* const tm = dynamic_cast<TModule*>(m);
TModuleWidget* const mw = new TModuleWidget(tm);
mw->setModel(this);
widgets[m] = mw;
DISTRHO_SAFE_ASSERT_RETURN(tm != nullptr, nullptr);

TModuleWidget* const tmw = new TModuleWidget(tm);
tmw->setModel(this);

widgets[m] = tmw;
widgetNeedsDeletion[m] = true;
return tmw;
} }


void clearCachedModuleWidget(rack::engine::Module* const m) override
void removeCachedModuleWidget(engine::Module* const m) override
{ {
assert(m != nullptr); if (m == nullptr) return;
assert(m->model == this); if (m->model != this) return;
DISTRHO_SAFE_ASSERT_RETURN(m != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(m->model == this,);

if (widgets.find(m) == widgets.end())
return;

if (widgetNeedsDeletion[m])
delete widgets[m];

widgets.erase(m); widgets.erase(m);
widgetNeedsDeletion.erase(m);
} }
}; };


template <class TModule, class TModuleWidget> template <class TModule, class TModuleWidget>
CardinalPluginModel<TModule, TModuleWidget>* createModel(std::string slug) CardinalPluginModel<TModule, TModuleWidget>* createModel(std::string slug)
{ {
CardinalPluginModel<TModule, TModuleWidget>* const o = new CardinalPluginModel<TModule, TModuleWidget>();
o->slug = slug;
return o;
CardinalPluginModel<TModule, TModuleWidget>* const o = new CardinalPluginModel<TModule, TModuleWidget>();
o->slug = slug;
return o;
} }


} }


#define createModel createModelOldVCV #define createModel createModelOldVCV
#include_next "helpers.hpp" #include_next "helpers.hpp"
#undef createModel

+ 12
- 13
plugins/Cardinal/src/Ildaeil.cpp View File

@@ -208,6 +208,8 @@ static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpc


// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


static Mutex sPluginInfoLoadMutex;

struct IldaeilModule : Module { struct IldaeilModule : Module {
enum ParamIds { enum ParamIds {
NUM_PARAMS NUM_PARAMS
@@ -243,7 +245,6 @@ struct IldaeilModule : Module {
mutable NativeTimeInfo fCarlaTimeInfo; mutable NativeTimeInfo fCarlaTimeInfo;


void* fUI = nullptr; void* fUI = nullptr;
Mutex fPluginLoadMutex;


float audioDataIn1[BUFFER_SIZE]; float audioDataIn1[BUFFER_SIZE];
float audioDataIn2[BUFFER_SIZE]; float audioDataIn2[BUFFER_SIZE];
@@ -417,7 +418,7 @@ struct IldaeilModule : Module {
CarlaEngine* const engine = carla_get_engine_from_handle(fCarlaHostHandle); CarlaEngine* const engine = carla_get_engine_from_handle(fCarlaHostHandle);


water::XmlDocument xml(projectState); water::XmlDocument xml(projectState);
const MutexLocker cml(fPluginLoadMutex);
const MutexLocker cml(sPluginInfoLoadMutex);
engine->loadProjectInternal(xml, true); engine->loadProjectInternal(xml, true);
} }


@@ -641,12 +642,10 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {


bool idleCallbackActive = false; bool idleCallbackActive = false;
IldaeilModule* const module; IldaeilModule* const module;
Mutex& fPluginLoadMutex;


IldaeilWidget(IldaeilModule* const m) IldaeilWidget(IldaeilModule* const m)
: ImGuiWidget(), : ImGuiWidget(),
module(m),
fPluginLoadMutex(m->fPluginLoadMutex)
module(m)
{ {
if (module->fCarlaHostHandle == nullptr) if (module->fCarlaHostHandle == nullptr)
{ {
@@ -836,7 +835,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {


carla_set_engine_option(handle, ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, fPluginWillRunInBridgeMode, nullptr); carla_set_engine_option(handle, ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, fPluginWillRunInBridgeMode, nullptr);


const MutexLocker cml(fPluginLoadMutex);
const MutexLocker cml(sPluginInfoLoadMutex);


if (carla_add_plugin(handle, BINARY_NATIVE, fPluginType, nullptr, nullptr, if (carla_add_plugin(handle, BINARY_NATIVE, fPluginType, nullptr, nullptr,
label, 0, 0x0, PLUGIN_OPTIONS_NULL)) label, 0, 0x0, PLUGIN_OPTIONS_NULL))
@@ -1018,7 +1017,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
if (path != nullptr) if (path != nullptr)
carla_set_engine_option(module->fCarlaHostHandle, ENGINE_OPTION_PLUGIN_PATH, pluginType, path); carla_set_engine_option(module->fCarlaHostHandle, ENGINE_OPTION_PLUGIN_PATH, pluginType, path);


const MutexLocker cml(fPluginLoadMutex);
const MutexLocker cml(sPluginInfoLoadMutex);


if (const uint count = carla_get_cached_plugin_count(pluginType, path)) if (const uint count = carla_get_cached_plugin_count(pluginType, path))
{ {
@@ -1432,12 +1431,12 @@ struct IldaeilModuleWidget : ModuleWidget {
addOutput(createOutput<PJ301MPort>(Vec(3, 54 + 60), module, IldaeilModule::OUTPUT1)); addOutput(createOutput<PJ301MPort>(Vec(3, 54 + 60), module, IldaeilModule::OUTPUT1));
addOutput(createOutput<PJ301MPort>(Vec(3, 54 + 90), module, IldaeilModule::OUTPUT2)); addOutput(createOutput<PJ301MPort>(Vec(3, 54 + 90), module, IldaeilModule::OUTPUT2));


addOutput(createInput<PJ301MPort>(Vec(3, 54 + 135), module, IldaeilModule::PITCH_INPUT));
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 165), module, IldaeilModule::GATE_INPUT));
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 195), module, IldaeilModule::VEL_INPUT));
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 225), module, IldaeilModule::AFT_INPUT));
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 255), module, IldaeilModule::PW_INPUT));
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 285), module, IldaeilModule::MW_INPUT));
addInput(createInput<PJ301MPort>(Vec(3, 54 + 135), module, IldaeilModule::PITCH_INPUT));
addInput(createInput<PJ301MPort>(Vec(3, 54 + 165), module, IldaeilModule::GATE_INPUT));
addInput(createInput<PJ301MPort>(Vec(3, 54 + 195), module, IldaeilModule::VEL_INPUT));
addInput(createInput<PJ301MPort>(Vec(3, 54 + 225), module, IldaeilModule::AFT_INPUT));
addInput(createInput<PJ301MPort>(Vec(3, 54 + 255), module, IldaeilModule::PW_INPUT));
addInput(createInput<PJ301MPort>(Vec(3, 54 + 285), module, IldaeilModule::MW_INPUT));
} }


DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(IldaeilModuleWidget) DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(IldaeilModuleWidget)


+ 7
- 1
plugins/Makefile View File

@@ -570,11 +570,14 @@ BASE_FLAGS += -I../src/Rack/dep/osdialog
BASE_FLAGS += -I../src/Rack/dep/oui-blendish BASE_FLAGS += -I../src/Rack/dep/oui-blendish
BASE_FLAGS += -I../src/Rack/dep/pffft BASE_FLAGS += -I../src/Rack/dep/pffft


ifeq ($(DEBUG),true)
BASE_FLAGS += -UDEBUG
endif

ifeq ($(HEADLESS),true) ifeq ($(HEADLESS),true)
BASE_FLAGS += -DHEADLESS BASE_FLAGS += -DHEADLESS
endif endif



ifeq ($(WASM),true) ifeq ($(WASM),true)
BASE_FLAGS += -DNANOVG_GLES2=1 BASE_FLAGS += -DNANOVG_GLES2=1
BASE_FLAGS += -msse -msse2 -msse3 -msimd128 BASE_FLAGS += -msse -msse2 -msse3 -msimd128
@@ -611,7 +614,10 @@ BASE_FLAGS += -Wno-unused-variable
# also from plugins # also from plugins


BASE_FLAGS += -Wno-deprecated-declarations BASE_FLAGS += -Wno-deprecated-declarations

ifeq ($(MACOS),true)
BASE_FLAGS += -Wno-unknown-warning-option BASE_FLAGS += -Wno-unknown-warning-option
endif


# -------------------------------------------------------------- # --------------------------------------------------------------
# Build targets # Build targets


+ 4
- 0
src/Makefile View File

@@ -50,6 +50,10 @@ BASE_FLAGS += -IRack/dep/osdialog
BASE_FLAGS += -IRack/dep/oui-blendish BASE_FLAGS += -IRack/dep/oui-blendish
BASE_FLAGS += -IRack/dep/pffft BASE_FLAGS += -IRack/dep/pffft


ifeq ($(DEBUG),true)
BASE_FLAGS += -UDEBUG
endif

ifeq ($(HEADLESS),true) ifeq ($(HEADLESS),true)
BASE_FLAGS += -DHEADLESS BASE_FLAGS += -DHEADLESS
endif endif


+ 8
- 5
src/override/Engine.cpp View File

@@ -558,6 +558,10 @@ void Engine::removeModule_NoLock(Module* module) {
// Check that the module actually exists // Check that the module actually exists
auto it = std::find(internal->modules.begin(), internal->modules.end(), module); auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
DISTRHO_SAFE_ASSERT_RETURN(it != internal->modules.end(),); DISTRHO_SAFE_ASSERT_RETURN(it != internal->modules.end(),);
// Remove from widgets cache
CardinalPluginModelHelper* const helper = dynamic_cast<CardinalPluginModelHelper*>(module->model);
DISTRHO_SAFE_ASSERT_RETURN(helper != nullptr,);
helper->removeCachedModuleWidget(module);
// Dispatch RemoveEvent // Dispatch RemoveEvent
Module::RemoveEvent eRemove; Module::RemoveEvent eRemove;
module->onRemove(eRemove); module->onRemove(eRemove);
@@ -586,9 +590,6 @@ void Engine::removeModule_NoLock(Module* module) {
m->rightExpander.module = NULL; m->rightExpander.module = NULL;
} }
} }
// Remove from widgets cache
if (auto* const helper = reinterpret_cast<CardinalPluginModelHelper*>(module->model))
helper->clearCachedModuleWidget(module);
// Remove module // Remove module
internal->modulesCache.erase(module->id); internal->modulesCache.erase(module->id);
internal->modules.erase(it); internal->modules.erase(it);
@@ -989,10 +990,11 @@ void Engine::fromJson(json_t* rootJ) {
DISTRHO_SAFE_ASSERT_CONTINUE(module != nullptr); DISTRHO_SAFE_ASSERT_CONTINUE(module != nullptr);


// Create the widget too, needed by a few modules // Create the widget too, needed by a few modules
auto* const helper = reinterpret_cast<CardinalPluginModelHelper*>(model);
CardinalPluginModelHelper* const helper = dynamic_cast<CardinalPluginModelHelper*>(model);
DISTRHO_SAFE_ASSERT_CONTINUE(helper != nullptr); DISTRHO_SAFE_ASSERT_CONTINUE(helper != nullptr);


helper->createCachedModuleWidget(module);
app::ModuleWidget* const moduleWidget = helper->createModuleWidgetFromEngineLoad(module);
DISTRHO_SAFE_ASSERT_CONTINUE(moduleWidget != nullptr);


try { try {
// This doesn't need a lock because the Module is not added to the Engine yet. // This doesn't need a lock because the Module is not added to the Engine yet.
@@ -1009,6 +1011,7 @@ void Engine::fromJson(json_t* rootJ) {
catch (Exception& e) { catch (Exception& e) {
WARN("Cannot load module: %s", e.what()); WARN("Cannot load module: %s", e.what());
// APP->patch->log(e.what()); // APP->patch->log(e.what());
helper->removeCachedModuleWidget(module);
delete module; delete module;
continue; continue;
} }


Loading…
Cancel
Save