@@ -7,7 +7,7 @@ THIS IS CURRENTLY A WORK IN PROGRESS RESEARCH PROJECT. | |||
It is not known yet how well this can work, mostly testing waters here. | |||
Currently the plugin will link against an internal [Carla](https://github.com/falkTX/Carla) for the plugin host part, embeding UIs if possible. | |||
Audio, MIDI and Time information works, but there is no latency, parameters or state handled right now. | |||
Audio, MIDI, Latency and Time information and State save/loading works, but there are no parameters right now. | |||
Also, only LV2 hosting is enabled at the moment. | |||
Ildaeil basically works as a mini-wrapper around Carla, leveraging it for all its host support. | |||
@@ -1 +1 @@ | |||
Subproject commit a310640e0fcb1aef53fe7d15771cccebdc9731c8 | |||
Subproject commit f93784ef1ad549a85f01dc4715920b9485303e0a |
@@ -2,5 +2,7 @@ | |||
../../dpf/distrho/ | |||
../../dpf-widgets/generic | |||
../../dpf-widgets/opengl | |||
/usr/include/carla | |||
/usr/include/carla/includes | |||
../../carla/source/backend | |||
../../carla/source/includes | |||
../../carla/source/modules | |||
../../carla/source/utils |
@@ -16,6 +16,9 @@ | |||
*/ | |||
#include "CarlaNativePlugin.h" | |||
#include "CarlaEngine.hpp" | |||
#include "water/streams/MemoryOutputStream.h" | |||
#include "water/xml/XmlDocument.h" | |||
#include "DistrhoPlugin.hpp" | |||
@@ -52,11 +55,13 @@ public: | |||
#endif | |||
mutable NativeTimeInfo fCarlaTimeInfo; | |||
mutable water::MemoryOutputStream fLastProjectState; | |||
uint32_t fLastLatencyValue; | |||
void* fUI; | |||
IldaeilPlugin() | |||
: Plugin(0, 0, 0), | |||
: Plugin(0, 0, 1), | |||
fCarlaPluginDescriptor(nullptr), | |||
fCarlaPluginHandle(nullptr), | |||
fCarlaHostHandle(nullptr), | |||
@@ -65,6 +70,7 @@ public: | |||
fMidiEventCount(0), | |||
fDummyBuffer(nullptr), | |||
#endif | |||
fLastLatencyValue(0), | |||
fUI(nullptr) | |||
{ | |||
fCarlaPluginDescriptor = carla_get_native_rack_plugin(); | |||
@@ -246,16 +252,72 @@ protected: | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* Init */ | |||
void initState(const uint32_t index, String& stateKey, String& defaultStateValue) override | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(index == 0,); | |||
stateKey = "project"; | |||
defaultStateValue = "" | |||
"<?xml version='1.0' encoding='UTF-8'?>\n" | |||
"<!DOCTYPE CARLA-PROJECT>\n" | |||
"<CARLA-PROJECT VERSION='" CARLA_VERSION_STRMIN "'>\n" | |||
"</CARLA-PROJECT>\n"; | |||
} | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* Internal data */ | |||
String getState(const char* const key) const override | |||
{ | |||
if (std::strcmp(key, "project") == 0) | |||
{ | |||
CarlaEngine* const engine = carla_get_engine_from_handle(fCarlaHostHandle); | |||
fLastProjectState.reset(); | |||
engine->saveProjectInternal(fLastProjectState); | |||
return String(static_cast<char*>(fLastProjectState.getDataAndRelease()), false); | |||
} | |||
return String(); | |||
} | |||
void setState(const char* const key, const char* const value) override | |||
{ | |||
if (std::strcmp(key, "project") == 0) | |||
{ | |||
CarlaEngine* const engine = carla_get_engine_from_handle(fCarlaHostHandle); | |||
water::XmlDocument xml(value); | |||
engine->loadProjectInternal(xml, true); | |||
} | |||
} | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* Process */ | |||
void checkLatencyChanged() | |||
{ | |||
if (fCarlaHostHandle == nullptr) | |||
return; | |||
uint32_t latency = 0; | |||
for (uint32_t i=0; i < carla_get_current_plugin_count(fCarlaHostHandle); ++i) | |||
latency += carla_get_plugin_latency(fCarlaHostHandle, i); | |||
if (fLastLatencyValue != latency) | |||
{ | |||
fLastLatencyValue = latency; | |||
setLatency(latency); | |||
} | |||
} | |||
void activate() override | |||
{ | |||
if (fCarlaPluginHandle != nullptr) | |||
fCarlaPluginDescriptor->activate(fCarlaPluginHandle); | |||
checkLatencyChanged(); | |||
} | |||
void deactivate() override | |||
@@ -305,6 +367,8 @@ protected: | |||
#else | |||
fCarlaPluginDescriptor->process(fCarlaPluginHandle, (float**)inputs, outputs, frames, nullptr, 0); | |||
#endif | |||
checkLatencyChanged(); | |||
} | |||
else | |||
{ | |||
@@ -59,7 +59,8 @@ class IldaeilUI : public UI, | |||
kDrawingLoading, | |||
kDrawingPluginList, | |||
kDrawingPluginCustomUI, | |||
kDrawingPluginGenericUI | |||
kDrawingPluginGenericUI, | |||
kDrawingPluginPendingFromInit | |||
} fDrawingState; | |||
struct PluginInfoCache { | |||
@@ -130,22 +131,16 @@ public: | |||
carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_UI_SCALE, getScaleFactor()*1000, nullptr); | |||
if (carla_get_current_plugin_count(handle) != 0) | |||
{ | |||
showPluginUI(handle); | |||
startThread(); | |||
return; | |||
} | |||
fDrawingState = kDrawingPluginPendingFromInit; | |||
} | |||
~IldaeilUI() override | |||
{ | |||
if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | |||
return; | |||
stopThread(-1); | |||
if (isThreadRunning()) | |||
stopThread(-1); | |||
// fPlugin->fUI = nullptr; | |||
hidePluginUI(fPlugin->fCarlaHostHandle); | |||
hidePluginUI(); | |||
delete[] fPlugins; | |||
} | |||
@@ -161,19 +156,23 @@ public: | |||
} | |||
else | |||
{ | |||
fDrawingState = kDrawingPluginGenericUI; | |||
// TODO query parameter information and store it | |||
const double scaleFactor = getScaleFactor(); | |||
setSize(kGenericWidth * scaleFactor, (kGenericHeight + kExtraHeight) * scaleFactor); | |||
fDrawingState = kDrawingPluginGenericUI; | |||
} | |||
repaint(); | |||
} | |||
void hidePluginUI(const CarlaHostHandle handle) | |||
void hidePluginUI() | |||
{ | |||
if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) | |||
return; | |||
if (fDrawingState == kDrawingPluginGenericUI || fDrawingState == kDrawingPluginCustomUI) | |||
carla_show_custom_ui(handle, 0, false); | |||
carla_show_custom_ui(fPlugin->fCarlaHostHandle, 0, false); | |||
fPluginHostWindow.hide(); | |||
} | |||
@@ -194,6 +193,11 @@ protected: | |||
repaint(); | |||
break; | |||
case kDrawingPluginPendingFromInit: | |||
showPluginUI(fPlugin->fCarlaHostHandle); | |||
startThread(); | |||
break; | |||
case kDrawingPluginCustomUI: | |||
fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); | |||
fPluginHostWindow.idle(); | |||
@@ -254,6 +258,9 @@ protected: | |||
switch (fDrawingState) | |||
{ | |||
case kDrawingInit: | |||
case kDrawingLoading: | |||
case kDrawingPluginPendingFromInit: | |||
drawLoading(); | |||
break; | |||
case kDrawingPluginList: | |||
drawPluginList(); | |||
@@ -261,9 +268,6 @@ protected: | |||
case kDrawingError: | |||
// TODO display error message | |||
break; | |||
case kDrawingLoading: | |||
drawLoading(); | |||
break; | |||
case kDrawingPluginGenericUI: | |||
drawGenericUI(); | |||
// fall-through | |||
@@ -282,7 +286,7 @@ protected: | |||
{ | |||
if (ImGui::Button("Pick Another...")) | |||
{ | |||
hidePluginUI(fPlugin->fCarlaHostHandle); | |||
hidePluginUI(); | |||
fDrawingState = kDrawingPluginList; | |||
const double scaleFactor = getScaleFactor(); | |||
@@ -362,7 +366,7 @@ protected: | |||
{ | |||
if (pluginIsRunning) | |||
{ | |||
hidePluginUI(handle); | |||
hidePluginUI(); | |||
carla_replace_plugin(handle, 0); | |||
} | |||
@@ -450,14 +454,16 @@ protected: | |||
/* -------------------------------------------------------------------------------------------------------- | |||
* DSP/Plugin Callbacks */ | |||
/** | |||
A parameter has changed on the plugin side. | |||
This is called by the host to inform the UI about parameter changes. | |||
*/ | |||
void parameterChanged(uint32_t, float) override | |||
{ | |||
} | |||
void stateChanged(const char* const key, const char* const) override | |||
{ | |||
if (std::strcmp(key, "project") == 0) | |||
hidePluginUI(); | |||
} | |||
// ------------------------------------------------------------------------------------------------------- | |||
private: | |||
@@ -67,6 +67,8 @@ BUILD_CXX_FLAGS += -I../../dpf-widgets/opengl | |||
BUILD_CXX_FLAGS += -DREAL_BUILD | |||
BUILD_CXX_FLAGS += -I../../carla/source/backend | |||
BUILD_CXX_FLAGS += -I../../carla/source/includes | |||
BUILD_CXX_FLAGS += -I../../carla/source/modules | |||
BUILD_CXX_FLAGS += -I../../carla/source/utils | |||
LINK_FLAGS += $(STATIC_CARLA_PLUGIN_LIBS) | |||
@@ -3,5 +3,7 @@ | |||
../../dpf/distrho/ | |||
../../dpf-widgets/generic | |||
../../dpf-widgets/opengl | |||
/usr/include/carla | |||
/usr/include/carla/includes | |||
../../carla/source/backend | |||
../../carla/source/includes | |||
../../carla/source/modules | |||
../../carla/source/utils |
@@ -27,6 +27,8 @@ | |||
#define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
#define DISTRHO_PLUGIN_WANT_LATENCY 1 | |||
#define DISTRHO_PLUGIN_WANT_STATE 1 | |||
#define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 0 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 | |||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
@@ -27,6 +27,8 @@ | |||
#define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 0 | |||
#define DISTRHO_PLUGIN_WANT_LATENCY 1 | |||
#define DISTRHO_PLUGIN_WANT_STATE 1 | |||
#define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1 | |||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
@@ -27,6 +27,8 @@ | |||
#define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
#define DISTRHO_PLUGIN_WANT_LATENCY 1 | |||
#define DISTRHO_PLUGIN_WANT_STATE 1 | |||
#define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 | |||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 | |||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||