From 98e0a5d7acc4d49b92d2a7b03e6efec7162f3b08 Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 11 Oct 2023 11:55:11 +0200 Subject: [PATCH] Implement LV2 ControlInputPort change request feature Signed-off-by: falkTX --- source/backend/plugin/CarlaPluginLV2.cpp | 37 ++++++++ .../lv2/control-input-port-change-request.h | 84 +++++++++++++++++++ source/utils/CarlaLv2Utils.hpp | 4 + 3 files changed, 125 insertions(+) create mode 100644 source/includes/lv2/control-input-port-change-request.h diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 07016d675..5c56ca516 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -188,6 +188,7 @@ enum CarlaLv2Features { kFeatureIdWorker, kFeatureIdInlineDisplay, kFeatureIdMidnam, + kFeatureIdCtrlInPortChangeReq, kFeatureCountPlugin, // UI features kFeatureIdUiDataAccess = kFeatureCountPlugin, @@ -835,6 +836,9 @@ public: if (fFeatures[kFeatureIdMidnam] != nullptr && fFeatures[kFeatureIdMidnam]->data != nullptr) delete (LV2_Midnam*)fFeatures[kFeatureIdMidnam]->data; + if (fFeatures[kFeatureIdCtrlInPortChangeReq] != nullptr && fFeatures[kFeatureIdCtrlInPortChangeReq]->data != nullptr) + delete (LV2_ControlInputPort_Change_Request*)fFeatures[kFeatureIdCtrlInPortChangeReq]->data; + for (uint32_t i=0; i < kFeatureCountAll; ++i) { if (fFeatures[i] != nullptr) @@ -6150,6 +6154,20 @@ public: // ------------------------------------------------------------------- + LV2_ControlInputPort_Change_Status handleCtrlInPortChangeReq(const uint32_t index, const float value) + { + CARLA_SAFE_ASSERT_RETURN(index < fRdfDescriptor->PortCount, LV2_CONTROL_INPUT_PORT_CHANGE_ERR_INVALID_INDEX); + CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN); + + const float fixedValue = pData->param.getFixedValue(index, value); + fParamBuffers[index] = fixedValue; + + CarlaPlugin::setParameterValueRT(index, fixedValue, 0, true); + return LV2_CONTROL_INPUT_PORT_CHANGE_SUCCESS; + } + + // ------------------------------------------------------------------- + void handleExternalUIClosed() { CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EXTERNAL,); @@ -6791,6 +6809,10 @@ public: midnam->handle = this; midnam->update = carla_lv2_midnam_update; + LV2_ControlInputPort_Change_Request* const portChangeReq = new LV2_ControlInputPort_Change_Request; + portChangeReq->handle = this; + portChangeReq->request_change = carla_lv2_ctrl_in_port_change_req; + // --------------------------------------------------------------- // initialize features (part 2) @@ -6868,6 +6890,9 @@ public: fFeatures[kFeatureIdMidnam]->URI = LV2_MIDNAM__update; fFeatures[kFeatureIdMidnam]->data = midnam; + fFeatures[kFeatureIdCtrlInPortChangeReq]->URI = LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI; + fFeatures[kFeatureIdCtrlInPortChangeReq]->data = portChangeReq; + // --------------------------------------------------------------- // initialize features (part 3) @@ -8176,6 +8201,18 @@ private: ((CarlaPluginLV2*)handle)->handleMidnamUpdate(); } + // ------------------------------------------------------------------- + // ControlInputPort change request Feature + + static LV2_ControlInputPort_Change_Status carla_lv2_ctrl_in_port_change_req( + LV2_ControlInputPort_Change_Request_Handle handle, uint32_t index, float value) + { + CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN); + carla_stdout("carla_lv2_ctrl_in_port_change_req(%p, %u, %f)", handle, index, value); + + return ((CarlaPluginLV2*)handle)->handleCtrlInPortChangeReq(index, value); + } + // ------------------------------------------------------------------- // External UI Feature diff --git a/source/includes/lv2/control-input-port-change-request.h b/source/includes/lv2/control-input-port-change-request.h new file mode 100644 index 000000000..e38dad45d --- /dev/null +++ b/source/includes/lv2/control-input-port-change-request.h @@ -0,0 +1,84 @@ +/* + LV2 ControlInputPort change request extension + Copyright 2020 Filipe Coelho + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file control-input-port-change-request.h + C header for the LV2 ControlInputPort change request extension . +*/ + +#ifndef LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H +#define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H + +#include "lv2.h" + +#define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI "http://kx.studio/ns/lv2ext/control-input-port-change-request" +#define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_PREFIX LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI "#" + +#include + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +/** A status code for LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI functions. */ +typedef enum { + LV2_CONTROL_INPUT_PORT_CHANGE_SUCCESS = 0, /**< Completed successfully. */ + LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_CONTROL_INPUT_PORT_CHANGE_ERR_INVALID_INDEX = 2 /**< Failed due to invalid port index. */ +} LV2_ControlInputPort_Change_Status; + +/** + * Opaque handle for LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI feature. + */ +typedef void* LV2_ControlInputPort_Change_Request_Handle; + +/** + * On instantiation, host must supply LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI feature. + * LV2_Feature::data must be pointer to LV2_ControlInputPort_Change_Request. +*/ +typedef struct _LV2_ControlInputPort_Change_Request { + /** + * Opaque host data. + */ + LV2_ControlInputPort_Change_Request_Handle handle; + + /** + * request_change() + * + * Ask the host to change a plugin's control input port value. + * Parameter handle MUST be the 'handle' member of this struct. + * Parameter index is port index to change. + * Parameter value is the requested value to change the control port input to. + * + * Returns status of the request. + * The host may decline this request, if e.g. it is currently automating this port. + * + * The plugin MUST call this function during run(). + */ + LV2_ControlInputPort_Change_Status (*request_change)(LV2_ControlInputPort_Change_Request_Handle handle, + uint32_t index, + float value); + +} LV2_ControlInputPort_Change_Request; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H */ diff --git a/source/utils/CarlaLv2Utils.hpp b/source/utils/CarlaLv2Utils.hpp index 7c706fa8a..2443e4e93 100644 --- a/source/utils/CarlaLv2Utils.hpp +++ b/source/utils/CarlaLv2Utils.hpp @@ -72,6 +72,8 @@ #include "lv2/lv2_programs.h" #include "lv2/lv2_rtmempool.h" +#include "lv2/control-input-port-change-request.h" + #include "lilv/lilvmm.hpp" #include "sratom/sratom.h" #include "lilv/config/lilv_config.h" @@ -3184,6 +3186,8 @@ bool is_lv2_feature_supported(const LV2_URI uri) noexcept return true; if (std::strcmp(uri, LV2_BUF_SIZE__powerOf2BlockLength) == 0) return true; + if (std::strcmp(uri, LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI) == 0) + return true; if (std::strcmp(uri, LV2_CORE__hardRTCapable) == 0) return true; if (std::strcmp(uri, LV2_CORE__inPlaceBroken) == 0)