From f2540a653269ccf866db9ce2ac919fdba71ac232 Mon Sep 17 00:00:00 2001 From: Kristian Amlie Date: Tue, 15 Jul 2025 12:41:39 +0200 Subject: [PATCH 1/4] Add support for parameter labels also when running as a plugin. Previously it was only available when running as a Jack application. Signed-off-by: Kristian Amlie --- source/backend/engine/CarlaEngineNative.cpp | 17 ++++++++++++ source/frontend/carla-plugin | 9 ++++++- source/frontend/carla_backend.py | 29 ++++++++++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp index 18987a7bf0..538b9b1bbf 100644 --- a/source/backend/engine/CarlaEngineNative.cpp +++ b/source/backend/engine/CarlaEngineNative.cpp @@ -589,6 +589,9 @@ class CarlaEngineNative : public CarlaEngine CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } + std::snprintf(tmpBuf, STR_MAX, "%i\n", plugin->getParameterScalePointCount(i)); + CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); + std::snprintf(tmpBuf, STR_MAX, "PARAMETER_RANGES_%i:%i\n", pluginId, i); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); @@ -606,6 +609,20 @@ class CarlaEngineNative : public CarlaEngine std::snprintf(tmpBuf, STR_MAX, "%.12g\n", static_cast(plugin->getParameterValue(i))); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); + + for (uint32_t p = 0; p < plugin->getParameterScalePointCount(i); p++) { + std::snprintf(tmpBuf, STR_MAX, "PARAMETER_SCALEPOINT_%i:%i:%i\n", pluginId, i, p); + CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); + + std::snprintf(tmpBuf, STR_MAX, "%.12g\n", plugin->getParameterScalePointValue(i, p)); + CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); + + if (plugin->getParameterScalePointLabel(i, p, tmpBuf)) { + CARLA_SAFE_ASSERT_RETURN(fUiServer.writeAndFixMessage(tmpBuf),); + } else { + CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); + } + } } fUiServer.syncMessages(); diff --git a/source/frontend/carla-plugin b/source/frontend/carla-plugin index a3850b9156..56c0aa17d9 100755 --- a/source/frontend/carla-plugin +++ b/source/frontend/carla-plugin @@ -280,6 +280,7 @@ class CarlaMiniW(ExternalUI, HostWindow): paramUnit = self.readlineblock() paramComment = self.readlineblock() paramGroupName = self.readlineblock() + scalePointCount = int(self.readlineblock()) paramInfo = { 'name': paramName, @@ -287,7 +288,7 @@ class CarlaMiniW(ExternalUI, HostWindow): 'unit': paramUnit, 'comment': paramComment, 'groupName': paramGroupName, - 'scalePointCount': 0, + 'scalePointCount': scalePointCount, } self.host._set_parameterInfo(pluginId, paramId, paramInfo) @@ -317,6 +318,12 @@ class CarlaMiniW(ExternalUI, HostWindow): } self.host._set_parameterRanges(pluginId, paramId, paramRanges) + elif msg.startswith("PARAMETER_SCALEPOINT_"): + pluginId, param, point = [int(i) for i in msg.replace("PARAMETER_SCALEPOINT_", "").split(":")] + value = float(self.readlineblock()) + label = self.readlineblock() + self.host._set_parameterScalePoint(pluginId, param, point, value, label) + elif msg.startswith("PROGRAM_COUNT_"): pluginId, count, current = [int(i) for i in msg.replace("PROGRAM_COUNT_", "").split(":")] self.host._set_programCount(pluginId, count) diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py index 49c41f2aef..88fdb5790c 100644 --- a/source/frontend/carla_backend.py +++ b/source/frontend/carla_backend.py @@ -3272,6 +3272,7 @@ def clear(self): self.parameterData = [] self.parameterRanges = [] self.parameterValues = [] + self.parameterScalePoints = [] self.programCount = 0 self.programCurrent = -1 self.programNames = [] @@ -3484,7 +3485,7 @@ def get_parameter_info(self, pluginId, parameterId): return self.fPluginsInfo.get(pluginId, self.fFallbackPluginInfo).parameterInfo[parameterId] def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId): - return PyCarlaScalePointInfo + return self.fPluginsInfo.get(pluginId, self.fFallbackPluginInfo).parameterScalePoints[parameterId][scalePointId] def get_parameter_data(self, pluginId, parameterId): return self.fPluginsInfo.get(pluginId, self.fFallbackPluginInfo).parameterData[parameterId] @@ -3765,6 +3766,7 @@ def _set_parameterCountInfo(self, pluginId, count, info): plugin.parameterData = [] plugin.parameterRanges = [] plugin.parameterValues = [] + plugin.parameterScalePoints = [] # add placeholders for _ in range(count): @@ -3772,6 +3774,26 @@ def _set_parameterCountInfo(self, pluginId, count, info): plugin.parameterData.append(PyParameterData.copy()) plugin.parameterRanges.append(PyParameterRanges.copy()) plugin.parameterValues.append(0.0) + plugin.parameterScalePoints.append([]) + + def _set_parameterScalePoint(self, pluginId, param, point, value, label): + plugin = self.fPluginsInfo.get(pluginId, None) + if plugin is None: + print("_set_parameterScalePointCount failed for", pluginId) + return + + if param < 0 or param >= plugin.parameterCount: + print("_set_parameterScalePointCount failed for parameter", param) + return + + if point < 0 or point >= plugin.parameterInfo[param]["scalePointCount"]: + print("_set_parameterScalePointCount failed for scale point", point) + return + + plugin.parameterScalePoints[param][point] = { + "value": value, + "label": label, + } def _set_programCount(self, pluginId, count): plugin = self.fPluginsInfo.get(pluginId, None) @@ -3810,6 +3832,11 @@ def _set_parameterInfo(self, pluginId, paramIndex, info): else: print("_set_parameterInfo failed for", pluginId, "and index", paramIndex) + # add placeholders + plugin.parameterScalePoints[paramIndex] = [] + for _ in range(info["scalePointCount"]): + plugin.parameterScalePoints[paramIndex].append({}) + def _set_parameterData(self, pluginId, paramIndex, data): plugin = self.fPluginsInfo.get(pluginId, None) if plugin is None: From dd1b7cbcdb229f6308de63580c0fbe020b00d3f4 Mon Sep 17 00:00:00 2001 From: Kristian Amlie Date: Sat, 14 Mar 2026 16:03:26 +0100 Subject: [PATCH 2/4] Fix: Don't insert scale points for invalid param indexes. Signed-off-by: Kristian Amlie --- source/frontend/carla_backend.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py index 88fdb5790c..77cdac79f4 100644 --- a/source/frontend/carla_backend.py +++ b/source/frontend/carla_backend.py @@ -3829,14 +3829,14 @@ def _set_parameterInfo(self, pluginId, paramIndex, info): return if paramIndex < plugin.parameterCount: plugin.parameterInfo[paramIndex] = info + + # add placeholders + plugin.parameterScalePoints[paramIndex] = [] + for _ in range(info["scalePointCount"]): + plugin.parameterScalePoints[paramIndex].append({}) else: print("_set_parameterInfo failed for", pluginId, "and index", paramIndex) - # add placeholders - plugin.parameterScalePoints[paramIndex] = [] - for _ in range(info["scalePointCount"]): - plugin.parameterScalePoints[paramIndex].append({}) - def _set_parameterData(self, pluginId, paramIndex, data): plugin = self.fPluginsInfo.get(pluginId, None) if plugin is None: From 21c7405b0b3e62a44544b14b88df485f419187b0 Mon Sep 17 00:00:00 2001 From: Kristian Amlie Date: Sat, 14 Mar 2026 17:15:31 +0100 Subject: [PATCH 3/4] Fix incorrect error message. Signed-off-by: Kristian Amlie --- source/frontend/carla_backend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py index 77cdac79f4..5102f96d93 100644 --- a/source/frontend/carla_backend.py +++ b/source/frontend/carla_backend.py @@ -3779,15 +3779,15 @@ def _set_parameterCountInfo(self, pluginId, count, info): def _set_parameterScalePoint(self, pluginId, param, point, value, label): plugin = self.fPluginsInfo.get(pluginId, None) if plugin is None: - print("_set_parameterScalePointCount failed for", pluginId) + print("_set_parameterScalePoint failed for", pluginId) return if param < 0 or param >= plugin.parameterCount: - print("_set_parameterScalePointCount failed for parameter", param) + print("_set_parameterScalePoint failed for parameter", param) return if point < 0 or point >= plugin.parameterInfo[param]["scalePointCount"]: - print("_set_parameterScalePointCount failed for scale point", point) + print("_set_parameterScalePoint failed for scale point", point) return plugin.parameterScalePoints[param][point] = { From bb8c5a5f569862c9920d645d2ad5c059978dddfd Mon Sep 17 00:00:00 2001 From: Kristian Amlie Date: Mon, 23 Mar 2026 11:47:44 +0100 Subject: [PATCH 4/4] Make scale point patch for LV2 compatible across versions. Use a dedicated `PARAMETER_SCALEPOINT_COUNT` statement in the protocol, so that old versions ignore it, instead of getting out of sync with the protocol and failing altogether. This helps for example to run an updated Carla and an older Carla-inside-Cardinal side by side. Signed-off-by: Kristian Amlie --- source/backend/engine/CarlaEngineNative.cpp | 2 ++ source/frontend/carla-plugin | 8 ++++++-- source/frontend/carla_backend.py | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp index 538b9b1bbf..70e31f1e46 100644 --- a/source/backend/engine/CarlaEngineNative.cpp +++ b/source/backend/engine/CarlaEngineNative.cpp @@ -589,6 +589,8 @@ class CarlaEngineNative : public CarlaEngine CARLA_SAFE_ASSERT_RETURN(fUiServer.writeEmptyMessage(),); } + std::snprintf(tmpBuf, STR_MAX, "PARAMETER_SCALEPOINT_COUNT_%i:%i\n", pluginId, i); + CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); std::snprintf(tmpBuf, STR_MAX, "%i\n", plugin->getParameterScalePointCount(i)); CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); diff --git a/source/frontend/carla-plugin b/source/frontend/carla-plugin index 56c0aa17d9..42e94d8fe3 100755 --- a/source/frontend/carla-plugin +++ b/source/frontend/carla-plugin @@ -280,7 +280,6 @@ class CarlaMiniW(ExternalUI, HostWindow): paramUnit = self.readlineblock() paramComment = self.readlineblock() paramGroupName = self.readlineblock() - scalePointCount = int(self.readlineblock()) paramInfo = { 'name': paramName, @@ -288,7 +287,7 @@ class CarlaMiniW(ExternalUI, HostWindow): 'unit': paramUnit, 'comment': paramComment, 'groupName': paramGroupName, - 'scalePointCount': scalePointCount, + 'scalePointCount': 0, } self.host._set_parameterInfo(pluginId, paramId, paramInfo) @@ -318,6 +317,11 @@ class CarlaMiniW(ExternalUI, HostWindow): } self.host._set_parameterRanges(pluginId, paramId, paramRanges) + elif msg.startswith("PARAMETER_SCALEPOINT_COUNT_"): + pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_SCALEPOINT_COUNT_", "").split(":")] + scalePointCount = int(self.readlineblock()) + self.host._set_parameterScalePointCount(pluginId, paramId, scalePointCount) + elif msg.startswith("PARAMETER_SCALEPOINT_"): pluginId, param, point = [int(i) for i in msg.replace("PARAMETER_SCALEPOINT_", "").split(":")] value = float(self.readlineblock()) diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py index 5102f96d93..b64f29bc45 100644 --- a/source/frontend/carla_backend.py +++ b/source/frontend/carla_backend.py @@ -3829,13 +3829,23 @@ def _set_parameterInfo(self, pluginId, paramIndex, info): return if paramIndex < plugin.parameterCount: plugin.parameterInfo[paramIndex] = info + else: + print("_set_parameterInfo failed for", pluginId, "and index", paramIndex) + + def _set_parameterScalePointCount(self, pluginId, paramIndex, count): + plugin = self.fPluginsInfo.get(pluginId, None) + if plugin is None: + print("_set_parameterScalePointCount failed for", pluginId) + return + if paramIndex < plugin.parameterCount and paramIndex < len(plugin.parameterInfo): + plugin.parameterInfo[paramIndex]["scalePointCount"] = count # add placeholders plugin.parameterScalePoints[paramIndex] = [] - for _ in range(info["scalePointCount"]): + for _ in range(count): plugin.parameterScalePoints[paramIndex].append({}) else: - print("_set_parameterInfo failed for", pluginId, "and index", paramIndex) + print("_set_parameterScalePointCount failed for", pluginId, "and index", paramIndex) def _set_parameterData(self, pluginId, paramIndex, data): plugin = self.fPluginsInfo.get(pluginId, None)