diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h index df660ade5..272e11ade 100644 --- a/source/backend/CarlaBackend.h +++ b/source/backend/CarlaBackend.h @@ -1112,6 +1112,14 @@ typedef enum { */ ENGINE_CALLBACK_PARAMETER_CV_CONTROLLED_STATUS_CHANGED = 46, + /*! + * A parameter's mapped range has changed. + * @a pluginId Plugin Id + * @a value1 Parameter index + * @a valueStr New mapped range as "%f:%f" syntax + */ + ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 47, + } EngineCallbackOpcode; /* ------------------------------------------------------------------------------------------------------------ @@ -1570,6 +1578,16 @@ typedef struct { */ uint8_t midiChannel; + /*! + * Minimum value that this parameter maps to. + */ + float mappedMinimum; + + /*! + * Maximum value that this parameter maps to. + */ + float mappedMaximum; + } ParameterData; /*! diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h index 215a738c5..412da9855 100644 --- a/source/backend/CarlaHost.h +++ b/source/backend/CarlaHost.h @@ -965,6 +965,15 @@ CARLA_EXPORT void carla_set_parameter_midi_channel(uint pluginId, uint32_t param */ CARLA_EXPORT void carla_set_parameter_midi_cc(uint pluginId, uint32_t parameterId, int16_t cc); +/*! + * Change a plugin's parameter mapped range. + * @param pluginId Plugin + * @param parameterId Parameter index + * @param minimum New mapped minimum + * @param maximum New mapped maximum + */ +CARLA_EXPORT void carla_set_parameter_mapped_range(uint pluginId, uint32_t parameterId, float minimum, float maximum); + /*! * Change a plugin's parameter in drag/touch mode state. * Usually happens from a UI when the user is moving a parameter with a mouse or similar input. diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 6e8e24b60..a5885d7b6 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -608,6 +608,11 @@ public: */ virtual void setParameterMidiCC(uint32_t parameterId, int16_t cc, bool sendOsc, bool sendCallback) noexcept; + /*! + * Set parameter's @a parameterId mapped range to @a minimum and @a maximum. + */ + virtual void setParameterMappedRange(uint32_t parameterId, float minimum, float maximum, bool sendOsc, bool sendCallback) noexcept; + /*! * Add a custom data set. * If @a key already exists, its current value will be swapped with @a value. diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp index 1d9a86d24..e3cc6122a 100644 --- a/source/backend/CarlaStandalone.cpp +++ b/source/backend/CarlaStandalone.cpp @@ -2025,6 +2025,19 @@ void carla_set_parameter_midi_cc(uint pluginId, uint32_t parameterId, int16_t cc return plugin->setParameterMidiCC(parameterId, cc, true, false); } +void carla_set_parameter_mapped_range(uint pluginId, uint32_t parameterId, float minimum, float maximum) +{ + CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); + + CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); + CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); + + carla_debug("carla_set_parameter_mapped_range(%i, %i, %f, %f)", pluginId, parameterId, static_cast(minimum), static_cast(maximum)); + CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),); + + return plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false); +} + void carla_set_parameter_touch(uint pluginId, uint32_t parameterId, bool touch) { CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,); diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index 6a7f21fd6..fd44dbde1 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -175,7 +175,7 @@ public: CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientVersion, false); const uint32_t apiVersion = fShmNonRtClientControl.readUInt(); - CARLA_SAFE_ASSERT_RETURN(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION, false); + CARLA_SAFE_ASSERT_RETURN(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM, false); const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData)); @@ -212,7 +212,17 @@ public: { const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); - fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); + // kPluginBridgeNonRtServerVersion was added in API 7 + if (apiVersion >= 7) + { + fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerVersion); + fShmNonRtServerControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); + } + else + { + fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); + } + fShmNonRtServerControl.commitWrite(); } @@ -734,7 +744,8 @@ public: case kPluginBridgeNonRtClientVersion: { const uint apiVersion = fShmNonRtServerControl.readUInt(); - CARLA_SAFE_ASSERT_UINT2(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION, apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION); + CARLA_SAFE_ASSERT_UINT2(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM, + apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM); } break; case kPluginBridgeNonRtClientPing: { @@ -793,6 +804,16 @@ public: break; } + case kPluginBridgeNonRtClientSetParameterMappedRange: { + const uint32_t index = fShmNonRtClientControl.readUInt(); + const float minimum = fShmNonRtClientControl.readFloat(); + const float maximum = fShmNonRtClientControl.readFloat(); + + if (plugin != nullptr && plugin->isEnabled()) + plugin->setParameterMappedRange(index, minimum, maximum, false, false); + break; + } + case kPluginBridgeNonRtClientSetProgram: { const int32_t index(fShmNonRtClientControl.readInt()); diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index b26399beb..fd12f8fb9 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -45,7 +45,7 @@ CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------- // Fallback data -static const ParameterData kParameterDataNull = { PARAMETER_UNKNOWN, 0x0, PARAMETER_NULL, -1, -1, 0 }; +static const ParameterData kParameterDataNull = { PARAMETER_UNKNOWN, 0x0, PARAMETER_NULL, -1, -1, 0, 0.0f, 1.0f }; static const ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0.0001f, 0.1f }; static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; @@ -1757,6 +1757,32 @@ void CarlaPlugin::setParameterMidiCC(const uint32_t parameterId, const int16_t c #endif } +void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept +{ + if (pData->engineBridged) { + CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); + } else { + CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT + } + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); + + pData->param.data[parameterId].mappedMinimum = minimum; + pData->param.data[parameterId].mappedMaximum = maximum; + + char strBuf[STR_MAX+1]; + carla_zeroChars(strBuf, STR_MAX+1); + std::snprintf(strBuf, STR_MAX, "%f:%f", static_cast(minimum), static_cast(maximum)); + +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH + pData->engine->callback(sendCallback, sendOsc, + ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED, + pData->id, + static_cast(parameterId), + 0, 0, 0.0f, + strBuf); +#endif +} + void CarlaPlugin::setCustomData(const char* const type, const char* const key, const char* const value, const bool) { CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index aad996417..f97dbd19d 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -382,6 +382,7 @@ public: : CarlaPlugin(engine, id), fBinaryType(btype), fPluginType(ptype), + fBridgeVersion(6), // before kPluginBridgeNonRtServerVersion was a thing, API was at 6 fInitiated(false), fInitError(false), fSaved(true), @@ -766,6 +767,26 @@ public: CarlaPlugin::setParameterMidiCC(parameterId, cc, sendOsc, sendCallback); } + void setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept override + { + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); + CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); + + // kPluginBridgeNonRtClientSetParameterMappedRange was added in API 7 + if (fBridgeVersion >= 7) + { + const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); + + fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedRange); + fShmNonRtClientControl.writeUInt(parameterId); + fShmNonRtClientControl.writeFloat(minimum); + fShmNonRtClientControl.writeFloat(maximum); + fShmNonRtClientControl.commitWrite(); + } + + CarlaPlugin::setParameterMappedRange(parameterId, minimum, maximum, sendOsc, sendCallback); + } + void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); @@ -1922,6 +1943,10 @@ public: case kPluginBridgeNonRtServerPong: break; + case kPluginBridgeNonRtServerVersion: + fBridgeVersion = fShmNonRtServerControl.readUInt(); + break; + case kPluginBridgeNonRtServerPluginInfo1: { // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId const uint32_t category = fShmNonRtServerControl.readUInt(); @@ -2611,6 +2636,7 @@ public: private: const BinaryType fBinaryType; const PluginType fPluginType; + uint fBridgeVersion; bool fInitiated; bool fInitError; @@ -2855,7 +2881,7 @@ private: fShmNonRtServerControl.clearData(); fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion); - fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION); + fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeRtClientData))); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeNonRtClientData))); diff --git a/source/backend/plugin/CarlaPluginJack.cpp b/source/backend/plugin/CarlaPluginJack.cpp index 6efb04f82..ef65fb01a 100644 --- a/source/backend/plugin/CarlaPluginJack.cpp +++ b/source/backend/plugin/CarlaPluginJack.cpp @@ -1447,6 +1447,7 @@ public: case kPluginBridgeNonRtServerProgramName: case kPluginBridgeNonRtServerMidiProgramData: case kPluginBridgeNonRtServerSetCustomData: + case kPluginBridgeNonRtServerVersion: break; case kPluginBridgeNonRtServerSetChunkDataFile: @@ -1796,7 +1797,7 @@ private: // initial values fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion); - fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION); + fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeRtClientData))); fShmNonRtClientControl.writeUInt(static_cast(sizeof(BridgeNonRtClientData))); diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py index 79da63bb3..795e9b290 100644 --- a/source/frontend/carla_backend.py +++ b/source/frontend/carla_backend.py @@ -802,6 +802,12 @@ ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED = 45 # @a value2 New CV controlled status (boolean) ENGINE_CALLBACK_PARAMETER_CV_CONTROLLED_STATUS_CHANGED = 46 +# A parameter's mapped range has changed. +# @a pluginId Plugin Id +# @a value1 Parameter index +# @a valueStr New mapped range as "%f:%f" syntax +ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 47 + # ------------------------------------------------------------------------------------------------------------ # NSM Callback Opcode # NSM callback opcodes. @@ -1090,7 +1096,13 @@ class ParameterData(Structure): # Currently mapped MIDI channel. # Counts from 0 to 15. - ("midiChannel", c_uint8) + ("midiChannel", c_uint8), + + # Minimum value that this parameter maps to. + ("mappedMinimum", c_uint8), + + # Maximum value that this parameter maps to. + ("mappedMaximum", c_uint8) ] # Parameter ranges. @@ -1169,7 +1181,9 @@ PyParameterData = { 'index': PARAMETER_NULL, 'rindex': -1, 'midiCC': -1, - 'midiChannel': 0 + 'midiChannel': 0, + 'mappedMinimum': 0.0, + 'mappedMaximum': 1.0, } # @see ParameterRanges @@ -2060,6 +2074,15 @@ class CarlaHostMeta(object): def set_parameter_midi_cc(self, pluginId, parameterId, cc): raise NotImplementedError + # Change a plugin's parameter mapped range. + # @param pluginId Plugin + # @param parameterId Parameter index + # @param minimum New mapped minimum + # @param maximum New mapped maximum + @abstractmethod + def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum): + raise NotImplementedError + # Change a plugin's parameter in drag/touch mode state. # Usually happens from a UI when the user is moving a parameter with a mouse or similar input. # @param pluginId Plugin @@ -2450,6 +2473,9 @@ class CarlaHostNull(CarlaHostMeta): def set_parameter_midi_cc(self, pluginId, parameterId, cc): return + def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum): + return + def set_parameter_touch(self, pluginId, parameterId, touch): return @@ -2765,6 +2791,9 @@ class CarlaHostDLL(CarlaHostMeta): self.lib.carla_set_parameter_midi_cc.argtypes = [c_uint, c_uint32, c_int16] self.lib.carla_set_parameter_midi_cc.restype = None + self.lib.carla_set_parameter_mapped_range.argtypes = [c_uint, c_uint32, c_float, c_float] + self.lib.carla_set_parameter_mapped_range.restype = None + self.lib.carla_set_parameter_touch.argtypes = [c_uint, c_uint32, c_bool] self.lib.carla_set_parameter_touch.restype = None @@ -3087,6 +3116,9 @@ class CarlaHostDLL(CarlaHostMeta): def set_parameter_midi_cc(self, pluginId, parameterId, cc): self.lib.carla_set_parameter_midi_cc(pluginId, parameterId, cc) + def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum): + self.lib.carla_set_parameter_mapped_range(pluginId, parameterId, minimum, maximum) + def set_parameter_touch(self, pluginId, parameterId, touch): self.lib.carla_set_parameter_touch(pluginId, parameterId, touch) @@ -3756,6 +3788,17 @@ class CarlaHostPlugin(CarlaHostMeta): else: print("_set_parameterMidiCC failed for", pluginId, "and index", paramIndex) + def _set_parameterMappedRange(self, pluginId, paramIndex, minimum, maximum): + plugin = self.fPluginsInfo.get(pluginId, None) + if plugin is None: + print("_set_parameterMappedRange failed for", pluginId) + return + if paramIndex < plugin.parameterCount: + plugin.parameterData[paramIndex]['mappedMinimum'] = minimum + plugin.parameterData[paramIndex]['mappedMaximum'] = maximum + else: + print("_set_parameterMappedRange failed for", pluginId, "and index", paramIndex) + def _set_currentProgram(self, pluginId, pIndex): plugin = self.fPluginsInfo.get(pluginId, None) if plugin is None: @@ -3840,6 +3883,10 @@ class CarlaHostPlugin(CarlaHostMeta): elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED: self._set_parameterMidiChannel(pluginId, value1, value2) + elif action == ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED: + minimum, maximum = (float(i) for i in valueStr.split(":")) + self._set_parameterMappedRange(pluginId, value1, minimum, maximum) + elif action == ENGINE_CALLBACK_PROGRAM_CHANGED: self._set_currentProgram(pluginId, value1) diff --git a/source/libjack/libjack.cpp b/source/libjack/libjack.cpp index 1184cdd8c..8e82d1c0b 100644 --- a/source/libjack/libjack.cpp +++ b/source/libjack/libjack.cpp @@ -399,7 +399,7 @@ bool CarlaJackAppClient::initSharedMemmory() CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientVersion, false); const uint32_t apiVersion = fShmNonRtClientControl.readUInt(); - CARLA_SAFE_ASSERT_RETURN(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION, false); + CARLA_SAFE_ASSERT_RETURN(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT, false); const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt(); CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData)); @@ -1022,7 +1022,8 @@ bool CarlaJackAppClient::handleNonRtData() case kPluginBridgeNonRtClientVersion: { const uint apiVersion = fShmNonRtServerControl.readUInt(); - CARLA_SAFE_ASSERT_UINT2(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION, apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION); + CARLA_SAFE_ASSERT_UINT2(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT, + apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT); } break; case kPluginBridgeNonRtClientPing: { @@ -1051,6 +1052,7 @@ bool CarlaJackAppClient::handleNonRtData() case kPluginBridgeNonRtClientSetParameterValue: case kPluginBridgeNonRtClientSetParameterMidiChannel: case kPluginBridgeNonRtClientSetParameterMidiCC: + case kPluginBridgeNonRtClientSetParameterMappedRange: case kPluginBridgeNonRtClientSetProgram: case kPluginBridgeNonRtClientSetMidiProgram: case kPluginBridgeNonRtClientSetCustomData: diff --git a/source/utils/CarlaBackendUtils.hpp b/source/utils/CarlaBackendUtils.hpp index 81bb949a6..2971be15c 100644 --- a/source/utils/CarlaBackendUtils.hpp +++ b/source/utils/CarlaBackendUtils.hpp @@ -315,6 +315,8 @@ const char* EngineCallbackOpcode2Str(const EngineCallbackOpcode opcode) noexcept return "ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED"; case ENGINE_CALLBACK_PARAMETER_CV_CONTROLLED_STATUS_CHANGED: return "ENGINE_CALLBACK_PARAMETER_CV_CONTROLLED_STATUS_CHANGED"; + case ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED: + return "ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED"; } carla_stderr("CarlaBackend::EngineCallbackOpcode2Str(%i) - invalid opcode", opcode); diff --git a/source/utils/CarlaBridgeDefines.hpp b/source/utils/CarlaBridgeDefines.hpp index 774366f10..3fb4ab391 100644 --- a/source/utils/CarlaBridgeDefines.hpp +++ b/source/utils/CarlaBridgeDefines.hpp @@ -20,7 +20,11 @@ #include "CarlaRingBuffer.hpp" -#define CARLA_PLUGIN_BRIDGE_API_VERSION 6 +// how much backwards compatible we are +#define CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM 6 + +// current API version, bumped when something is added +#define CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT 7 // ------------------------------------------------------------------------------------------------------------------- @@ -69,7 +73,9 @@ enum PluginBridgeNonRtClientOpcode { kPluginBridgeNonRtClientUiMidiProgramChange, // uint kPluginBridgeNonRtClientUiNoteOn, // byte, byte, byte kPluginBridgeNonRtClientUiNoteOff, // byte, byte - kPluginBridgeNonRtClientQuit + kPluginBridgeNonRtClientQuit, + // stuff added in API 7 + kPluginBridgeNonRtClientSetParameterMappedRange, // uint, float, float }; // Client sends these to server during non-RT @@ -103,7 +109,9 @@ enum PluginBridgeNonRtServerOpcode { kPluginBridgeNonRtServerReady, kPluginBridgeNonRtServerSaved, kPluginBridgeNonRtServerUiClosed, - kPluginBridgeNonRtServerError // uint/size, str[] + kPluginBridgeNonRtServerError, // uint/size, str[] + // stuff added in API 7 + kPluginBridgeNonRtServerVersion // uint }; // used for kPluginBridgeNonRtServerPortName diff --git a/source/utils/CarlaBridgeUtils.hpp b/source/utils/CarlaBridgeUtils.hpp index b511057f9..cc4f93f4a 100644 --- a/source/utils/CarlaBridgeUtils.hpp +++ b/source/utils/CarlaBridgeUtils.hpp @@ -120,6 +120,8 @@ const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcod return "kPluginBridgeNonRtClientUiNoteOff"; case kPluginBridgeNonRtClientQuit: return "kPluginBridgeNonRtClientQuit"; + case kPluginBridgeNonRtClientSetParameterMappedRange: + return "kPluginBridgeNonRtClientSetParameterMappedRange"; } carla_stderr("CarlaBackend::PluginBridgeNonRtClientOpcode2str(%i) - invalid opcode", opcode); @@ -191,6 +193,8 @@ const char* PluginBridgeNonRtServerOpcode2str(const PluginBridgeNonRtServerOpcod return "kPluginBridgeNonRtServerUiClosed"; case kPluginBridgeNonRtServerError: return "kPluginBridgeNonRtServerError"; + case kPluginBridgeNonRtServerVersion: + return "kPluginBridgeNonRtServerVersion"; } carla_stderr("CarlaBackend::PluginBridgeNonRtServerOpcode2str%i) - invalid opcode", opcode);