Ildaeil: Separate drawing and idle logic, fixing some crashes

This commit is contained in:
falkTX 2021-11-14 21:08:32 +00:00
parent 0fa7cbd349
commit ae3097809b
3 changed files with 126 additions and 101 deletions

View file

@ -165,6 +165,10 @@ struct IldaeilModule : Module {
if (const char* const path = std::getenv("LV2_PATH")) if (const char* const path = std::getenv("LV2_PATH"))
carla_set_engine_option(fCarlaHostHandle, ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2, path); carla_set_engine_option(fCarlaHostHandle, ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2, path);
#ifdef CARLA_OS_MAC
carla_set_engine_option(fCarlaHostHandle, ENGINE_OPTION_PREFER_UI_BRIDGES, 0, nullptr);
#endif
fCarlaPluginDescriptor->dispatcher(fCarlaPluginHandle, NATIVE_PLUGIN_OPCODE_HOST_USES_EMBED, fCarlaPluginDescriptor->dispatcher(fCarlaPluginHandle, NATIVE_PLUGIN_OPCODE_HOST_USES_EMBED,
0, 0, nullptr, 0.0f); 0, 0, nullptr, 0.0f);
@ -416,20 +420,31 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
}; };
enum { enum {
kDrawingInit,
kDrawingErrorInit,
kDrawingErrorDraw,
kDrawingLoading, kDrawingLoading,
kDrawingPluginError,
kDrawingPluginList, kDrawingPluginList,
kDrawingPluginGenericUI, kDrawingPluginGenericUI,
kDrawingPluginPendingFromInit kDrawingErrorInit,
} fDrawingState = kDrawingInit; kDrawingErrorDraw
} fDrawingState = kDrawingLoading;
enum {
kIdleInit,
kIdleInitPluginAlreadyLoaded,
kIdleLoadSelectedPlugin,
kIdleResetPlugin,
kIdleShowCustomUI,
kIdleHidePluginUI,
kIdleGiveIdleToUI,
kIdleNothing
} fIdleState = kIdleInit;
PluginType fPluginType = PLUGIN_LV2; PluginType fPluginType = PLUGIN_LV2;
uint fPluginCount = 0; uint fPluginCount = 0;
uint fPluginSelected = false; uint fPluginSelected = false;
bool fPluginScanningFinished = false; bool fPluginScanningFinished = false;
bool fPluginHasCustomUI = false; bool fPluginHasCustomUI = false;
bool fPluginRunning = false;
bool fPluginWillRunInBridgeMode = false; bool fPluginWillRunInBridgeMode = false;
PluginInfoCache* fPlugins = nullptr; PluginInfoCache* fPlugins = nullptr;
ScopedPointer<PluginGenericUI> fPluginGenericUI; ScopedPointer<PluginGenericUI> fPluginGenericUI;
@ -451,6 +466,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
{ {
fDrawingState = kDrawingErrorInit; fDrawingState = kDrawingErrorInit;
fPopupError = "Ildaeil backend failed to init properly, cannot continue."; fPopupError = "Ildaeil backend failed to init properly, cannot continue.";
fIdleState = kIdleNothing;
return; return;
} }
@ -464,7 +480,8 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
if (carla_get_current_plugin_count(handle) != 0) if (carla_get_current_plugin_count(handle) != 0)
{ {
const uint hints = carla_get_plugin_info(handle, 0)->hints; const uint hints = carla_get_plugin_info(handle, 0)->hints;
fDrawingState = kDrawingPluginPendingFromInit; fIdleState = kIdleInitPluginAlreadyLoaded;
fPluginRunning = true;
fPluginHasCustomUI = hints & PLUGIN_HAS_CUSTOM_UI; fPluginHasCustomUI = hints & PLUGIN_HAS_CUSTOM_UI;
} }
@ -477,6 +494,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
{ {
module->fUI = nullptr; module->fUI = nullptr;
carla_set_engine_option(module->fCarlaHostHandle, ENGINE_OPTION_FRONTEND_WIN_ID, 0, "0"); carla_set_engine_option(module->fCarlaHostHandle, ENGINE_OPTION_FRONTEND_WIN_ID, 0, "0");
carla_show_custom_ui(module->fCarlaHostHandle, 0, false);
module->pcontext->removeIdleCallback(this); module->pcontext->removeIdleCallback(this);
} }
@ -484,8 +502,6 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
if (isThreadRunning()) if (isThreadRunning())
stopThread(-1); stopThread(-1);
hidePluginUI();
fPluginGenericUI = nullptr; fPluginGenericUI = nullptr;
delete[] fPlugins; delete[] fPlugins;
@ -508,6 +524,8 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
break; break;
} }
} }
setDirty(true);
} }
void openFileFromDSP(const bool isDir, const char* const title, const char* const filter) void openFileFromDSP(const bool isDir, const char* const title, const char* const filter)
@ -519,7 +537,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
*/ */
} }
void showPluginUI(const CarlaHostHandle handle) void createOrUpdatePluginGenericUI(const CarlaHostHandle handle)
{ {
const CarlaPluginInfo* const info = carla_get_plugin_info(handle, 0); const CarlaPluginInfo* const info = carla_get_plugin_info(handle, 0);
@ -533,15 +551,6 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
setDirty(true); setDirty(true);
} }
void hidePluginUI()
{
if (module->fCarlaHostHandle == nullptr)
return;
if (fDrawingState == kDrawingPluginGenericUI)
carla_show_custom_ui(module->fCarlaHostHandle, 0, false);
}
void createPluginGenericUI(const CarlaHostHandle handle, const CarlaPluginInfo* const info) void createPluginGenericUI(const CarlaHostHandle handle, const CarlaPluginInfo* const info)
{ {
PluginGenericUI* const ui = new PluginGenericUI; PluginGenericUI* const ui = new PluginGenericUI;
@ -627,11 +636,11 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
} }
} }
bool loadPlugin(const CarlaHostHandle handle, const char* const label) void loadPlugin(const CarlaHostHandle handle, const char* const label)
{ {
if (carla_get_current_plugin_count(handle) != 0) if (fPluginRunning)
{ {
hidePluginUI(); carla_show_custom_ui(handle, 0, false);
carla_replace_plugin(handle, 0); carla_replace_plugin(handle, 0);
} }
@ -640,18 +649,18 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
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))
{ {
fPluginRunning = true;
fPluginGenericUI = nullptr; fPluginGenericUI = nullptr;
showPluginUI(handle); createOrUpdatePluginGenericUI(handle);
return true;
} }
else else
{ {
fPopupError = carla_get_last_error(handle); fPopupError = carla_get_last_error(handle);
d_stdout("got error: %s", fPopupError.buffer()); d_stdout("got error: %s", fPopupError.buffer());
ImGui::OpenPopup("Plugin Error"); fDrawingState = kDrawingPluginError;
} }
return false; setDirty(true);
} }
void onContextCreate(const ContextCreateEvent& e) override void onContextCreate(const ContextCreateEvent& e) override
@ -717,25 +726,78 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
void idleCallback() override void idleCallback() override
{ {
switch (fDrawingState) const CarlaHostHandle handle = module->fCarlaHostHandle;
DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr,);
switch (fIdleState)
{ {
case kDrawingInit: case kIdleInit:
fDrawingState = kDrawingLoading; fIdleState = kIdleNothing;
startThread(); startThread();
break; break;
case kDrawingPluginPendingFromInit: case kIdleInitPluginAlreadyLoaded:
showPluginUI(module->fCarlaHostHandle); fIdleState = kIdleNothing;
createOrUpdatePluginGenericUI(handle);
startThread(); startThread();
break; break;
case kDrawingPluginGenericUI: case kIdleLoadSelectedPlugin:
fIdleState = kIdleNothing;
loadSelectedPlugin(handle);
break;
case kIdleResetPlugin:
fIdleState = kIdleNothing;
loadPlugin(handle, carla_get_plugin_info(handle, 0)->label);
break;
case kIdleShowCustomUI:
fIdleState = kIdleGiveIdleToUI;
carla_show_custom_ui(handle, 0, true);
break;
case kIdleHidePluginUI:
fIdleState = kIdleNothing;
carla_show_custom_ui(handle, 0, false);
break;
case kIdleGiveIdleToUI:
module->fCarlaPluginDescriptor->ui_idle(module->fCarlaPluginHandle); module->fCarlaPluginDescriptor->ui_idle(module->fCarlaPluginHandle);
break; break;
case kIdleNothing:
break;
}
}
void loadSelectedPlugin(const CarlaHostHandle handle)
{
const PluginInfoCache& info(fPlugins[fPluginSelected]);
const char* label = nullptr;
switch (fPluginType)
{
case PLUGIN_INTERNAL:
// case PLUGIN_JSFX:
case PLUGIN_SFZ:
label = info.label;
break;
case PLUGIN_LV2: {
const char* const slash = std::strchr(info.label, DISTRHO_OS_SEP);
DISTRHO_SAFE_ASSERT_RETURN(slash != nullptr,);
label = slash+1;
break;
}
default: default:
break; break;
} }
DISTRHO_SAFE_ASSERT_RETURN(label != nullptr,);
d_stdout("Loading %s...", info.name);
loadPlugin(handle, label);
} }
/* /*
@ -748,9 +810,10 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
void run() override void run() override
{ {
const PluginType pluginType = fPluginType;
const char* path; const char* path;
switch (fPluginType) switch (pluginType)
{ {
case PLUGIN_LV2: case PLUGIN_LV2:
path = std::getenv("LV2_PATH"); path = std::getenv("LV2_PATH");
@ -761,9 +824,9 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
} }
if (path != nullptr) if (path != nullptr)
carla_set_engine_option(module->fCarlaHostHandle, ENGINE_OPTION_PLUGIN_PATH, fPluginType, path); carla_set_engine_option(module->fCarlaHostHandle, ENGINE_OPTION_PLUGIN_PATH, pluginType, path);
if (const uint count = carla_get_cached_plugin_count(fPluginType, nullptr)) if (const uint count = carla_get_cached_plugin_count(pluginType, path))
{ {
fPluginCount = 0; fPluginCount = 0;
fPlugins = new PluginInfoCache[count]; fPlugins = new PluginInfoCache[count];
@ -776,12 +839,14 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
for (uint i=0, j; i < count && ! shouldThreadExit(); ++i) for (uint i=0, j; i < count && ! shouldThreadExit(); ++i)
{ {
const CarlaCachedPluginInfo* const info = carla_get_cached_plugin_info(fPluginType, i); const CarlaCachedPluginInfo* const info = carla_get_cached_plugin_info(pluginType, i);
DISTRHO_SAFE_ASSERT_CONTINUE(info != nullptr); DISTRHO_SAFE_ASSERT_CONTINUE(info != nullptr);
if (! info->valid) if (! info->valid)
continue; continue;
if (info->audioIns != 2 || info->audioOuts != 2) if (info->audioIns != 0 && info->audioIns != 2)
continue;
if (info->audioOuts != 0 && info->audioOuts != 2)
continue; continue;
j = fPluginCount; j = fPluginCount;
@ -790,10 +855,10 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
++fPluginCount; ++fPluginCount;
} }
} }
else else if (fDrawingState == kDrawingLoading)
{ {
String error("There are no "); String error("There are no ");
error += getPluginTypeAsString(fPluginType); error += getPluginTypeAsString(pluginType);
error += " audio plugins on this system."; error += " audio plugins on this system.";
fPopupError = error; fPopupError = error;
fDrawingState = kDrawingErrorInit; fDrawingState = kDrawingErrorInit;
@ -807,14 +872,22 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
{ {
switch (fDrawingState) switch (fDrawingState)
{ {
case kDrawingInit:
case kDrawingLoading: case kDrawingLoading:
case kDrawingPluginPendingFromInit:
drawLoading(); drawLoading();
break; break;
case kDrawingPluginError:
ImGui::OpenPopup("Plugin Error");
// call ourselves again with the plugin list
fDrawingState = kDrawingPluginList;
drawImGui();
break;
case kDrawingPluginList: case kDrawingPluginList:
drawPluginList(); drawPluginList();
break; break;
case kDrawingPluginGenericUI:
drawTopBar();
drawGenericUI();
break;
case kDrawingErrorInit: case kDrawingErrorInit:
fDrawingState = kDrawingErrorDraw; fDrawingState = kDrawingErrorDraw;
drawError(true); drawError(true);
@ -822,10 +895,6 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
case kDrawingErrorDraw: case kDrawingErrorDraw:
drawError(false); drawError(false);
break; break;
case kDrawingPluginGenericUI:
drawTopBar();
drawGenericUI();
break;
} }
} }
@ -883,30 +952,23 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
if (ImGui::Begin("Current Plugin", nullptr, flags)) if (ImGui::Begin("Current Plugin", nullptr, flags))
{ {
const CarlaHostHandle handle = module->fCarlaHostHandle;
if (ImGui::Button("Pick Another...")) if (ImGui::Button("Pick Another..."))
{ {
hidePluginUI(); fIdleState = kIdleHidePluginUI;
fDrawingState = kDrawingPluginList; fDrawingState = kDrawingPluginList;
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Reset")) if (ImGui::Button("Reset"))
{ fIdleState = kIdleResetPlugin;
loadPlugin(handle, carla_get_plugin_info(handle, 0)->label);
}
if (fDrawingState == kDrawingPluginGenericUI && fPluginHasCustomUI) if (fDrawingState == kDrawingPluginGenericUI && fPluginHasCustomUI)
{ {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Show Custom GUI")) if (ImGui::Button("Show Custom GUI"))
{ fIdleState = kIdleShowCustomUI;
carla_show_custom_ui(handle, 0, true);
ImGui::End();
}
} }
} }
@ -994,9 +1056,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
setupMainWindowPos(); setupMainWindowPos();
if (ImGui::Begin("Plugin List", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize)) if (ImGui::Begin("Plugin List", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize))
{
ImGui::TextUnformatted("Loading...", nullptr); ImGui::TextUnformatted("Loading...", nullptr);
}
ImGui::End(); ImGui::End();
} }
@ -1005,8 +1065,6 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
{ {
setupMainWindowPos(); setupMainWindowPos();
const CarlaHostHandle handle = module->fCarlaHostHandle;
if (ImGui::Begin("Plugin List", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize)) if (ImGui::Begin("Plugin List", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize))
{ {
const int pflags = ImGuiWindowFlags_NoSavedSettings const int pflags = ImGuiWindowFlags_NoSavedSettings
@ -1025,9 +1083,7 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
ImGui::Separator(); ImGui::Separator();
if (ImGui::Button("Ok")) if (ImGui::Button("Ok"))
{
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
}
ImGui::SameLine(); ImGui::SameLine();
ImGui::Dummy(ImVec2(500, 1)); ImGui::Dummy(ImVec2(500, 1));
@ -1048,53 +1104,17 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread {
ImGui::BeginDisabled(!fPluginScanningFinished); ImGui::BeginDisabled(!fPluginScanningFinished);
if (ImGui::Button("Load Plugin")) if (ImGui::Button("Load Plugin"))
{ fIdleState = kIdleLoadSelectedPlugin;
do {
const PluginInfoCache& info(fPlugins[fPluginSelected]);
const char* label = nullptr;
switch (fPluginType)
{
case PLUGIN_INTERNAL:
// case PLUGIN_JSFX:
case PLUGIN_SFZ:
label = info.label;
break;
case PLUGIN_LV2: {
const char* const slash = std::strchr(info.label, DISTRHO_OS_SEP);
DISTRHO_SAFE_ASSERT_BREAK(slash != nullptr);
label = slash+1;
break;
}
default:
break;
}
DISTRHO_SAFE_ASSERT_BREAK(label != nullptr);
d_stdout("Loading %s...", info.name);
if (loadPlugin(handle, label))
{
ImGui::EndDisabled();
ImGui::End();
return;
}
} while (false);
}
ImGui::SameLine(); ImGui::SameLine();
ImGui::Checkbox("Run in bridge mode", &fPluginWillRunInBridgeMode); ImGui::Checkbox("Run in bridge mode", &fPluginWillRunInBridgeMode);
if (carla_get_current_plugin_count(handle) != 0) if (fPluginRunning)
{ {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Cancel")) if (ImGui::Button("Cancel"))
{ fDrawingState = kDrawingPluginGenericUI;
showPluginUI(handle);
}
} }
ImGui::EndDisabled(); ImGui::EndDisabled();

View file

@ -602,13 +602,16 @@ BUILD_C_FLAGS += -fno-finite-math-only
BUILD_CXX_FLAGS += -fno-finite-math-only BUILD_CXX_FLAGS += -fno-finite-math-only
# -------------------------------------------------------------- # --------------------------------------------------------------
# FIXME lots of warnings from VCV side # lots of warnings from VCV side
BASE_FLAGS += -Wno-unused-parameter BASE_FLAGS += -Wno-unused-parameter
BASE_FLAGS += -Wno-unused-variable BASE_FLAGS += -Wno-unused-variable
# also lots of plugins not updated to v2 yet # --------------------------------------------------------------
# also from plugins
BASE_FLAGS += -Wno-deprecated-declarations BASE_FLAGS += -Wno-deprecated-declarations
BASE_FLAGS += -Wno-unknown-warning-option
# -------------------------------------------------------------- # --------------------------------------------------------------
# Build targets # Build targets

View file

@ -251,6 +251,8 @@ public:
{ {
rack::contextSet(context); rack::contextSet(context);
context->nativeWindowId = 0;
rack::widget::Widget* const menuBar = context->scene->menuBar; rack::widget::Widget* const menuBar = context->scene->menuBar;
context->scene->menuBar = nullptr; context->scene->menuBar = nullptr;
context->scene->removeChild(menuBar); context->scene->removeChild(menuBar);