| @@ -74,6 +74,13 @@ protected: | |||
| virtual void d_uiIdle() {} | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| // ------------------------------------------------------------------- | |||
| // Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! | |||
| void* d_getPluginInstancePointer(); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| @@ -55,6 +55,10 @@ | |||
| # error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| # define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||
| #endif | |||
| /* Compatibility with non-clang compilers */ | |||
| #ifndef __has_feature | |||
| # define __has_feature(x) 0 | |||
| @@ -43,7 +43,7 @@ public: | |||
| UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin) | |||
| : fHost(host), | |||
| fPlugin(plugin), | |||
| fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback) | |||
| fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback, plugin->getInstancePointer()) | |||
| { | |||
| fUI.setTitle(host->uiName); | |||
| @@ -173,6 +173,11 @@ public: | |||
| return (fPlugin != nullptr) ? fPlugin->d_getUniqueId() : 0; | |||
| } | |||
| void* getInstancePointer() const noexcept | |||
| { | |||
| return fPlugin; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| @@ -19,6 +19,8 @@ | |||
| #include "lv2/atom.h" | |||
| #include "lv2/atom-util.h" | |||
| #include "lv2/buf-size.h" | |||
| #include "lv2/data-access.h" | |||
| #include "lv2/instance-access.h" | |||
| #include "lv2/midi.h" | |||
| #include "lv2/options.h" | |||
| #include "lv2/state.h" | |||
| @@ -556,6 +558,15 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| void* lv2_get_instance_pointer() | |||
| { | |||
| return fPlugin.getInstancePointer(); | |||
| } | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| PluginExporter fPlugin; | |||
| @@ -824,6 +835,15 @@ LV2_Worker_Status lv2_work(LV2_Handle instance, LV2_Worker_Respond_Function, LV2 | |||
| // ----------------------------------------------------------------------- | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| static void* lv2_get_instance_pointer(LV2_Handle instance) | |||
| { | |||
| return instancePtr->lv2_get_instance_pointer(); | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| static const void* lv2_extension_data(const char* uri) | |||
| { | |||
| static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; | |||
| @@ -848,6 +868,19 @@ static const void* lv2_extension_data(const char* uri) | |||
| return &worker; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| # define DISTRHO_DIRECT_ACCESS_URI "urn:distrho:direct-access" | |||
| struct LV2_DirectAccess_Interface { | |||
| void* (*get_instance_pointer)(LV2_Handle handle); | |||
| }; | |||
| static const LV2_DirectAccess_Interface directaccess = { lv2_get_instance_pointer }; | |||
| if (std::strcmp(uri, DISTRHO_DIRECT_ACCESS_URI) == 0) | |||
| return &directaccess; | |||
| #endif | |||
| return nullptr; | |||
| } | |||
| @@ -18,6 +18,8 @@ | |||
| #include "lv2/atom.h" | |||
| #include "lv2/buf-size.h" | |||
| #include "lv2/data-access.h" | |||
| #include "lv2/instance-access.h" | |||
| #include "lv2/midi.h" | |||
| #include "lv2/options.h" | |||
| #include "lv2/state.h" | |||
| @@ -86,16 +88,24 @@ void lv2_generate_ttl(const char* const basename) | |||
| # else | |||
| manifestString += " a ui:X11UI ;\n"; | |||
| # endif | |||
| # if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| manifestString += " ui:binary <" + pluginLabel + "_ui." DISTRHO_DLL_EXTENSION "> ;\n"; | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| # else | |||
| manifestString += " ui:binary <" + pluginLabel + "." DISTRHO_DLL_EXTENSION "> ;\n"; | |||
| #endif | |||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| manifestString += " lv2:extensionData ui:idleInterface ,\n"; | |||
| manifestString += " <" LV2_PROGRAMS__Interface "> ;\n"; | |||
| #else | |||
| # else | |||
| manifestString += " lv2:extensionData ui:idleInterface ;\n"; | |||
| #endif | |||
| # endif | |||
| manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; | |||
| manifestString += " ui:touch ;\n"; | |||
| manifestString += " lv2:requiredFeature ui:resize ,\n"; | |||
| # if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| manifestString += " <" LV2_DATA_ACCESS_URI "> ,\n"; | |||
| manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n"; | |||
| # endif | |||
| manifestString += " <" LV2_OPTIONS__options "> ,\n"; | |||
| manifestString += " <" LV2_URID__map "> .\n"; | |||
| #endif | |||
| @@ -119,7 +119,7 @@ public: | |||
| fEffect(effect), | |||
| fUiHelper(uiHelper), | |||
| fPlugin(plugin), | |||
| fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback) | |||
| fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback, plugin->getInstancePointer()) | |||
| { | |||
| } | |||
| @@ -84,6 +84,16 @@ void UI::d_uiResize(unsigned int width, unsigned int height) | |||
| pData->uiResizeCallback(width, height); | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| // ----------------------------------------------------------------------- | |||
| // Direct DSP access | |||
| void* UI::d_getPluginInstancePointer() | |||
| { | |||
| return pData->dspPtr; | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -16,6 +16,10 @@ | |||
| #include "DistrhoUIInternal.hpp" | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| # error DSSI UIs do not support direct access! | |||
| #endif | |||
| #include <lo/lo.h> | |||
| START_NAMESPACE_DISTRHO | |||
| @@ -45,6 +45,9 @@ struct UI::PrivateData { | |||
| // DSP | |||
| double sampleRate; | |||
| uint32_t parameterOffset; | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| void* dspPtr; | |||
| #endif | |||
| // Callbacks | |||
| editParamFunc editParamCallbackFunc; | |||
| @@ -57,6 +60,9 @@ struct UI::PrivateData { | |||
| PrivateData() noexcept | |||
| : sampleRate(d_lastUiSampleRate), | |||
| parameterOffset(0), | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| dspPtr(nullptr), | |||
| #endif | |||
| editParamCallbackFunc(nullptr), | |||
| setParamCallbackFunc(nullptr), | |||
| setStateCallbackFunc(nullptr), | |||
| @@ -120,7 +126,7 @@ class UIExporter | |||
| { | |||
| public: | |||
| UIExporter(void* const ptr, const intptr_t winId, | |||
| const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const uiResizeFunc uiResizeCall) | |||
| const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const uiResizeFunc uiResizeCall, void* const dspPtr = nullptr) | |||
| : glApp(), | |||
| glWindow(glApp, winId), | |||
| fUi(createUI()), | |||
| @@ -140,6 +146,13 @@ public: | |||
| glWindow.setSize(fUi->d_getWidth(), fUi->d_getHeight()); | |||
| glWindow.setResizable(false); | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| fData->dspPtr = dspPtr; | |||
| #else | |||
| return; // unused | |||
| (void)dspPtr; | |||
| #endif | |||
| } | |||
| ~UIExporter() | |||
| @@ -18,6 +18,8 @@ | |||
| #include "lv2/atom.h" | |||
| #include "lv2/atom-util.h" | |||
| #include "lv2/data-access.h" | |||
| #include "lv2/instance-access.h" | |||
| #include "lv2/options.h" | |||
| #include "lv2/ui.h" | |||
| #include "lv2/urid.h" | |||
| @@ -32,8 +34,8 @@ START_NAMESPACE_DISTRHO | |||
| class UiLv2 | |||
| { | |||
| public: | |||
| UiLv2(const intptr_t winId, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch, const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc) | |||
| : fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback), | |||
| UiLv2(const intptr_t winId, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch, const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc, void* const dspPtr) | |||
| : fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback, dspPtr), | |||
| fUridMap(uridMap), | |||
| fUiResize(uiResz), | |||
| fUiTouch(uiTouch), | |||
| @@ -202,6 +204,16 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
| const LV2UI_Resize* uiResize = nullptr; | |||
| const LV2UI_Touch* uiTouch = nullptr; | |||
| void* parentId = nullptr; | |||
| void* instance = nullptr; | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| # define DISTRHO_DIRECT_ACCESS_URI "urn:distrho:direct-access" | |||
| struct LV2_DirectAccess_Interface { | |||
| void* (*get_instance_pointer)(LV2_Handle handle); | |||
| }; | |||
| const LV2_Extension_Data_Feature* extData = nullptr; | |||
| #endif | |||
| for (int i=0; features[i] != nullptr; ++i) | |||
| { | |||
| @@ -213,6 +225,12 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
| uiResize = (const LV2UI_Resize*)features[i]->data; | |||
| else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0) | |||
| parentId = features[i]->data; | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| else if (std::strcmp(features[i]->URI, LV2_DATA_ACCESS_URI) == 0) | |||
| extData = (const LV2_Extension_Data_Feature*)features[i]->data; | |||
| else if (std::strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI) == 0) | |||
| instance = features[i]->data; | |||
| #endif | |||
| } | |||
| if (options == nullptr) | |||
| @@ -239,6 +257,24 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
| return nullptr; | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| if (extData == nullptr || instance == nullptr) | |||
| { | |||
| d_stderr("Data or instance access missing, cannot continue!"); | |||
| return nullptr; | |||
| } | |||
| if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_DIRECT_ACCESS_URI)) | |||
| { | |||
| instance = directAccess->get_instance_pointer(instance); | |||
| } | |||
| else | |||
| { | |||
| d_stderr("Failed to get direct access, cannot continue!"); | |||
| return nullptr; | |||
| } | |||
| #endif | |||
| *widget = parentId; | |||
| const intptr_t winId(*((intptr_t*)&parentId)); | |||
| @@ -259,7 +295,7 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||
| if (d_lastUiSampleRate == 0.0) | |||
| d_lastUiSampleRate = 44100.0; | |||
| return new UiLv2(winId, uridMap, uiResize, uiTouch, controller, writeFunction); | |||
| return new UiLv2(winId, uridMap, uiResize, uiTouch, controller, writeFunction, instance); | |||
| } | |||
| #define uiPtr ((UiLv2*)ui) | |||