| @@ -74,6 +74,13 @@ protected: | |||||
| virtual void d_uiIdle() {} | 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: | private: | ||||
| @@ -55,6 +55,10 @@ | |||||
| # error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | # error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | ||||
| #endif | #endif | ||||
| #ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| # define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||||
| #endif | |||||
| /* Compatibility with non-clang compilers */ | /* Compatibility with non-clang compilers */ | ||||
| #ifndef __has_feature | #ifndef __has_feature | ||||
| # define __has_feature(x) 0 | # define __has_feature(x) 0 | ||||
| @@ -43,7 +43,7 @@ public: | |||||
| UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin) | UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin) | ||||
| : fHost(host), | : fHost(host), | ||||
| fPlugin(plugin), | fPlugin(plugin), | ||||
| fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback) | |||||
| fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback, plugin->getInstancePointer()) | |||||
| { | { | ||||
| fUI.setTitle(host->uiName); | fUI.setTitle(host->uiName); | ||||
| @@ -173,6 +173,11 @@ public: | |||||
| return (fPlugin != nullptr) ? fPlugin->d_getUniqueId() : 0; | return (fPlugin != nullptr) ? fPlugin->d_getUniqueId() : 0; | ||||
| } | } | ||||
| void* getInstancePointer() const noexcept | |||||
| { | |||||
| return fPlugin; | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| #if DISTRHO_PLUGIN_WANT_LATENCY | #if DISTRHO_PLUGIN_WANT_LATENCY | ||||
| @@ -19,6 +19,8 @@ | |||||
| #include "lv2/atom.h" | #include "lv2/atom.h" | ||||
| #include "lv2/atom-util.h" | #include "lv2/atom-util.h" | ||||
| #include "lv2/buf-size.h" | #include "lv2/buf-size.h" | ||||
| #include "lv2/data-access.h" | |||||
| #include "lv2/instance-access.h" | |||||
| #include "lv2/midi.h" | #include "lv2/midi.h" | ||||
| #include "lv2/options.h" | #include "lv2/options.h" | ||||
| #include "lv2/state.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: | private: | ||||
| PluginExporter fPlugin; | 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 void* lv2_extension_data(const char* uri) | ||||
| { | { | ||||
| static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; | 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; | return &worker; | ||||
| #endif | #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; | return nullptr; | ||||
| } | } | ||||
| @@ -18,6 +18,8 @@ | |||||
| #include "lv2/atom.h" | #include "lv2/atom.h" | ||||
| #include "lv2/buf-size.h" | #include "lv2/buf-size.h" | ||||
| #include "lv2/data-access.h" | |||||
| #include "lv2/instance-access.h" | |||||
| #include "lv2/midi.h" | #include "lv2/midi.h" | ||||
| #include "lv2/options.h" | #include "lv2/options.h" | ||||
| #include "lv2/state.h" | #include "lv2/state.h" | ||||
| @@ -86,16 +88,24 @@ void lv2_generate_ttl(const char* const basename) | |||||
| # else | # else | ||||
| manifestString += " a ui:X11UI ;\n"; | manifestString += " a ui:X11UI ;\n"; | ||||
| # endif | # endif | ||||
| # if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| manifestString += " ui:binary <" + pluginLabel + "_ui." DISTRHO_DLL_EXTENSION "> ;\n"; | 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:extensionData ui:idleInterface ,\n"; | ||||
| manifestString += " <" LV2_PROGRAMS__Interface "> ;\n"; | manifestString += " <" LV2_PROGRAMS__Interface "> ;\n"; | ||||
| #else | |||||
| # else | |||||
| manifestString += " lv2:extensionData ui:idleInterface ;\n"; | manifestString += " lv2:extensionData ui:idleInterface ;\n"; | ||||
| #endif | |||||
| # endif | |||||
| manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; | manifestString += " lv2:optionalFeature ui:noUserResize ,\n"; | ||||
| manifestString += " ui:touch ;\n"; | manifestString += " ui:touch ;\n"; | ||||
| manifestString += " lv2:requiredFeature ui:resize ,\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_OPTIONS__options "> ,\n"; | ||||
| manifestString += " <" LV2_URID__map "> .\n"; | manifestString += " <" LV2_URID__map "> .\n"; | ||||
| #endif | #endif | ||||
| @@ -119,7 +119,7 @@ public: | |||||
| fEffect(effect), | fEffect(effect), | ||||
| fUiHelper(uiHelper), | fUiHelper(uiHelper), | ||||
| fPlugin(plugin), | 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); | pData->uiResizeCallback(width, height); | ||||
| } | } | ||||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| // ----------------------------------------------------------------------- | |||||
| // Direct DSP access | |||||
| void* UI::d_getPluginInstancePointer() | |||||
| { | |||||
| return pData->dspPtr; | |||||
| } | |||||
| #endif | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| END_NAMESPACE_DISTRHO | END_NAMESPACE_DISTRHO | ||||
| @@ -16,6 +16,10 @@ | |||||
| #include "DistrhoUIInternal.hpp" | #include "DistrhoUIInternal.hpp" | ||||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| # error DSSI UIs do not support direct access! | |||||
| #endif | |||||
| #include <lo/lo.h> | #include <lo/lo.h> | ||||
| START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
| @@ -45,6 +45,9 @@ struct UI::PrivateData { | |||||
| // DSP | // DSP | ||||
| double sampleRate; | double sampleRate; | ||||
| uint32_t parameterOffset; | uint32_t parameterOffset; | ||||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| void* dspPtr; | |||||
| #endif | |||||
| // Callbacks | // Callbacks | ||||
| editParamFunc editParamCallbackFunc; | editParamFunc editParamCallbackFunc; | ||||
| @@ -57,6 +60,9 @@ struct UI::PrivateData { | |||||
| PrivateData() noexcept | PrivateData() noexcept | ||||
| : sampleRate(d_lastUiSampleRate), | : sampleRate(d_lastUiSampleRate), | ||||
| parameterOffset(0), | parameterOffset(0), | ||||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| dspPtr(nullptr), | |||||
| #endif | |||||
| editParamCallbackFunc(nullptr), | editParamCallbackFunc(nullptr), | ||||
| setParamCallbackFunc(nullptr), | setParamCallbackFunc(nullptr), | ||||
| setStateCallbackFunc(nullptr), | setStateCallbackFunc(nullptr), | ||||
| @@ -120,7 +126,7 @@ class UIExporter | |||||
| { | { | ||||
| public: | public: | ||||
| UIExporter(void* const ptr, const intptr_t winId, | 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(), | : glApp(), | ||||
| glWindow(glApp, winId), | glWindow(glApp, winId), | ||||
| fUi(createUI()), | fUi(createUI()), | ||||
| @@ -140,6 +146,13 @@ public: | |||||
| glWindow.setSize(fUi->d_getWidth(), fUi->d_getHeight()); | glWindow.setSize(fUi->d_getWidth(), fUi->d_getHeight()); | ||||
| glWindow.setResizable(false); | glWindow.setResizable(false); | ||||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||||
| fData->dspPtr = dspPtr; | |||||
| #else | |||||
| return; // unused | |||||
| (void)dspPtr; | |||||
| #endif | |||||
| } | } | ||||
| ~UIExporter() | ~UIExporter() | ||||
| @@ -18,6 +18,8 @@ | |||||
| #include "lv2/atom.h" | #include "lv2/atom.h" | ||||
| #include "lv2/atom-util.h" | #include "lv2/atom-util.h" | ||||
| #include "lv2/data-access.h" | |||||
| #include "lv2/instance-access.h" | |||||
| #include "lv2/options.h" | #include "lv2/options.h" | ||||
| #include "lv2/ui.h" | #include "lv2/ui.h" | ||||
| #include "lv2/urid.h" | #include "lv2/urid.h" | ||||
| @@ -32,8 +34,8 @@ START_NAMESPACE_DISTRHO | |||||
| class UiLv2 | class UiLv2 | ||||
| { | { | ||||
| public: | 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), | fUridMap(uridMap), | ||||
| fUiResize(uiResz), | fUiResize(uiResz), | ||||
| fUiTouch(uiTouch), | fUiTouch(uiTouch), | ||||
| @@ -202,6 +204,16 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
| const LV2UI_Resize* uiResize = nullptr; | const LV2UI_Resize* uiResize = nullptr; | ||||
| const LV2UI_Touch* uiTouch = nullptr; | const LV2UI_Touch* uiTouch = nullptr; | ||||
| void* parentId = 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) | 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; | uiResize = (const LV2UI_Resize*)features[i]->data; | ||||
| else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0) | else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0) | ||||
| parentId = features[i]->data; | 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) | if (options == nullptr) | ||||
| @@ -239,6 +257,24 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
| return nullptr; | 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; | *widget = parentId; | ||||
| const intptr_t winId(*((intptr_t*)&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) | if (d_lastUiSampleRate == 0.0) | ||||
| d_lastUiSampleRate = 44100.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) | #define uiPtr ((UiLv2*)ui) | ||||