Finish createModel override, fix Ildaeil race condition on load
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
749cafde2d
commit
c4426fd125
5 changed files with 78 additions and 45 deletions
|
@ -32,67 +32,88 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "DistrhoUtils.hpp"
|
||||||
|
|
||||||
namespace rack {
|
namespace rack {
|
||||||
|
|
||||||
struct CardinalPluginModelHelper {
|
struct CardinalPluginModelHelper : plugin::Model {
|
||||||
virtual ~CardinalPluginModelHelper() {}
|
virtual app::ModuleWidget* createModuleWidgetFromEngineLoad(engine::Module* m) = 0;
|
||||||
virtual void createCachedModuleWidget(rack::engine::Module* m) = 0;
|
virtual void removeCachedModuleWidget(engine::Module* m) = 0;
|
||||||
virtual void clearCachedModuleWidget(rack::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;
|
TModule* tm = nullptr;
|
||||||
if (m) {
|
if (m)
|
||||||
assert(m->model == this);
|
{
|
||||||
|
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);
|
app::ModuleWidget* const tmw = new TModuleWidget(tm);
|
||||||
mw->setModel(this);
|
tmw->setModel(this);
|
||||||
return mw;
|
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;
|
DISTRHO_SAFE_ASSERT_RETURN(m != nullptr, nullptr);
|
||||||
assert(m->model == this); if (m->model != this) return;
|
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);
|
DISTRHO_SAFE_ASSERT_RETURN(tm != nullptr, nullptr);
|
||||||
mw->setModel(this);
|
|
||||||
widgets[m] = mw;
|
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;
|
DISTRHO_SAFE_ASSERT_RETURN(m != nullptr,);
|
||||||
assert(m->model == this); if (m->model != this) return;
|
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>();
|
CardinalPluginModel<TModule, TModuleWidget>* const o = new CardinalPluginModel<TModule, TModuleWidget>();
|
||||||
o->slug = slug;
|
o->slug = slug;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define createModel createModelOldVCV
|
#define createModel createModelOldVCV
|
||||||
#include_next "helpers.hpp"
|
#include_next "helpers.hpp"
|
||||||
|
#undef createModel
|
||||||
|
|
|
@ -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),
|
module(m)
|
||||||
fPluginLoadMutex(m->fPluginLoadMutex)
|
|
||||||
{
|
{
|
||||||
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));
|
addInput(createInput<PJ301MPort>(Vec(3, 54 + 135), module, IldaeilModule::PITCH_INPUT));
|
||||||
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 165), module, IldaeilModule::GATE_INPUT));
|
addInput(createInput<PJ301MPort>(Vec(3, 54 + 165), module, IldaeilModule::GATE_INPUT));
|
||||||
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 195), module, IldaeilModule::VEL_INPUT));
|
addInput(createInput<PJ301MPort>(Vec(3, 54 + 195), module, IldaeilModule::VEL_INPUT));
|
||||||
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 225), module, IldaeilModule::AFT_INPUT));
|
addInput(createInput<PJ301MPort>(Vec(3, 54 + 225), module, IldaeilModule::AFT_INPUT));
|
||||||
addOutput(createInput<PJ301MPort>(Vec(3, 54 + 255), module, IldaeilModule::PW_INPUT));
|
addInput(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 + 285), module, IldaeilModule::MW_INPUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(IldaeilModuleWidget)
|
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(IldaeilModuleWidget)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue