diff --git a/data/lv2-bundles/files/audiofile.ttl b/data/lv2-bundles/files/audiofile.ttl index 265807b04..0779793c4 100644 --- a/data/lv2-bundles/files/audiofile.ttl +++ b/data/lv2-bundles/files/audiofile.ttl @@ -13,6 +13,7 @@ lv2:optionalFeature ; lv2:requiredFeature , + , , ; diff --git a/source/plugin/carla-lv2-export.cpp b/source/plugin/carla-lv2-export.cpp index 99fd65c32..a73a01d52 100644 --- a/source/plugin/carla-lv2-export.cpp +++ b/source/plugin/carla-lv2-export.cpp @@ -32,6 +32,7 @@ #include "lv2/units.h" #include "lv2/urid.h" #include "lv2/worker.h" +#include "lv2/inline-display.h" #include "lv2/lv2_external_ui.h" #include "lv2/lv2_programs.h" @@ -324,12 +325,18 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc, if (pluginDesc->hints & NATIVE_PLUGIN_IS_RTSAFE) text += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ;\n\n"; + if (pluginDesc->hints & NATIVE_PLUGIN_HAS_INLINE_DISPLAY) + text += " lv2:optionalFeature <" LV2_INLINEDISPLAY__queue_draw "> ;\n"; + // required text += " lv2:requiredFeature <" LV2_BUF_SIZE__boundedBlockLength "> ,\n"; if (pluginDesc->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) text += " <" LV2_BUF_SIZE__fixedBlockLength "> ,\n"; + if (pluginDesc->hints & NATIVE_PLUGIN_REQUESTS_IDLE) + text += " <" LV2_WORKER__schedule "> ,\n"; + text += " <" LV2_OPTIONS__options "> ,\n"; text += " <" LV2_URID__map "> ;\n"; text += "\n"; @@ -348,6 +355,9 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc, if (pluginDesc->hints & NATIVE_PLUGIN_HAS_UI) text += " lv2:extensionData <" LV2_WORKER__interface "> ;\n"; + if (pluginDesc->hints & NATIVE_PLUGIN_HAS_INLINE_DISPLAY) + text += " lv2:extensionData <" LV2_INLINEDISPLAY__interface "> ;\n"; + text += "\n"; // ------------------------------------------------------------------- diff --git a/source/plugin/carla-lv2.cpp b/source/plugin/carla-lv2.cpp index 8d1ce2212..88d34868e 100644 --- a/source/plugin/carla-lv2.cpp +++ b/source/plugin/carla-lv2.cpp @@ -600,6 +600,19 @@ public: return LV2_WORKER_SUCCESS; } + const LV2_Inline_Display_Image_Surface* lv2_idisp_render(const uint32_t width, const uint32_t height) + { + CARLA_SAFE_ASSERT_RETURN(fDescriptor->hints & NATIVE_PLUGIN_HAS_INLINE_DISPLAY, nullptr); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->render_inline_display, nullptr); + CARLA_SAFE_ASSERT_RETURN(width > 0, nullptr); + CARLA_SAFE_ASSERT_RETURN(height > 0, nullptr); + + const NativeInlineDisplayImageSurface* nsur = fDescriptor->render_inline_display(fHandle, width, height); + CARLA_SAFE_ASSERT_RETURN(nsur != nullptr, nullptr); + + return (const LV2_Inline_Display_Image_Surface*)(nsur); + } + // ---------------------------------------------------------------------------------------------------------------- void lv2ui_instantiate(LV2UI_Write_Function writeFunction, LV2UI_Controller controller, @@ -870,7 +883,12 @@ protected: return 0; case NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY: - break; + if (fInlineDisplay != nullptr && fInlineDisplay->queue_draw != nullptr) + { + fInlineDisplay->queue_draw(fInlineDisplay->handle); + return 1; + } + return 0; case NATIVE_HOST_OPCODE_GET_FILE_PATH: CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); @@ -1142,14 +1160,21 @@ static LV2_Worker_Status lv2_work_resp(LV2_Handle instance, uint32_t size, const return instancePtr->lv2_work_resp(size, body); } +static const LV2_Inline_Display_Image_Surface* lv2_idisp_render(LV2_Handle instance, uint32_t w, uint32_t h) +{ + // carla_debug("lv2_idisp_render(%p, %u, %u)", instance, w, h); + return instancePtr->lv2_idisp_render(w, h); +} + static const void* lv2_extension_data(const char* uri) { carla_debug("lv2_extension_data(\"%s\")", uri); - static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; - static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program }; - static const LV2_State_Interface state = { lv2_save, lv2_restore }; - static const LV2_Worker_Interface worker = { lv2_work, lv2_work_resp, nullptr }; + static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; + static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program }; + static const LV2_State_Interface state = { lv2_save, lv2_restore }; + static const LV2_Worker_Interface worker = { lv2_work, lv2_work_resp, nullptr }; + static const LV2_Inline_Display_Interface idisp = { lv2_idisp_render }; if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) return &options; @@ -1159,6 +1184,8 @@ static const void* lv2_extension_data(const char* uri) return &state; if (std::strcmp(uri, LV2_WORKER__interface) == 0) return &worker; + if (std::strcmp(uri, LV2_INLINEDISPLAY__interface) == 0) + return &idisp; return nullptr; } diff --git a/source/utils/CarlaLv2Utils.hpp b/source/utils/CarlaLv2Utils.hpp index e5c97a483..c9f8977bb 100644 --- a/source/utils/CarlaLv2Utils.hpp +++ b/source/utils/CarlaLv2Utils.hpp @@ -574,6 +574,7 @@ public: fUridMap(nullptr), fUridUnmap(nullptr), fWorker(nullptr), + fInlineDisplay(nullptr), fTimeInfo(), fLastPositionData(), fPorts(), @@ -595,6 +596,7 @@ public: const LV2_URID_Map* uridMap = nullptr; const LV2_URID_Unmap* uridUnmap = nullptr; const LV2_Worker_Schedule* worker = nullptr; + const LV2_Inline_Display* idisp = nullptr; for (int i=0; features[i] != nullptr; ++i) { @@ -608,6 +610,8 @@ public: uridUnmap = (const LV2_URID_Unmap*)features[i]->data; else if (std::strcmp(features[i]->URI, LV2_WORKER__schedule) == 0) worker = (const LV2_Worker_Schedule*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_INLINEDISPLAY__queue_draw) == 0) + idisp = (const LV2_Inline_Display*)features[i]->data; } if (options == nullptr || uridMap == nullptr) @@ -670,6 +674,7 @@ public: fFreePath = freePath; fUridUnmap = uridUnmap; fWorker = worker; + fInlineDisplay = idisp; clearTimeData(); } @@ -1187,6 +1192,7 @@ protected: const LV2_URID_Map* fUridMap; const LV2_URID_Unmap* fUridUnmap; const LV2_Worker_Schedule* fWorker; + const LV2_Inline_Display* fInlineDisplay; // Time info stuff TimeInfoStruct fTimeInfo;