diff --git a/resources/ui/carla_parameter.ui b/resources/ui/carla_parameter.ui
index 288abe345..2d3cf6009 100644
--- a/resources/ui/carla_parameter.ui
+++ b/resources/ui/carla_parameter.ui
@@ -7,7 +7,7 @@
0
0
369
- 22
+ 33
@@ -41,43 +41,9 @@
-
-
-
- Qt::CustomContextMenu
-
-
- (none)
-
-
- cc #
-
-
- -1
-
-
- 119
-
-
- -1
-
-
-
- -
-
-
- Qt::CustomContextMenu
-
-
- ch
-
-
- 1
-
-
- 16
-
-
- 1
+
+
+ ...
diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h
index 272e11ade..8e51044fd 100644
--- a/source/backend/CarlaBackend.h
+++ b/source/backend/CarlaBackend.h
@@ -748,6 +748,37 @@ typedef enum {
} InternalParameterIndex;
+/* ------------------------------------------------------------------------------------------------------------
+ * Special Mapped Control Index */
+
+/*!
+ * Specially designated mapped control indexes.
+ * Values between 0 and 119 (0x77) are reserved for MIDI CC, which uses direct values.
+ * @see ParameterData::mappedControlIndex
+ */
+typedef enum {
+ /*!
+ * Unused control index, meaning no mapping is enabled.
+ */
+ CONTROL_INDEX_NONE = -1,
+
+ /*!
+ * CV control index, meaning the parameter is exposed as CV port.
+ */
+ CONTROL_INDEX_CV = 130,
+
+ /*!
+ * Special value to indicate MIDI pitchbend.
+ */
+ CONTROL_INDEX_MIDI_PITCHBEND = 131,
+
+ /*!
+ * Highest index allowed for mappings.
+ */
+ CONTROL_INDEX_MAX_ALLOWED = CONTROL_INDEX_MIDI_PITCHBEND,
+
+} SpecialMappedControlIndex;
+
/* ------------------------------------------------------------------------------------------------------------
* Engine Callback Opcode */
@@ -808,12 +839,12 @@ typedef enum {
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
/*!
- * A parameter's MIDI CC has changed.
+ * A parameter's mapped control index has changed.
* @a pluginId Plugin Id
* @a value1 Parameter index
- * @a value2 New MIDI CC
+ * @a value2 New control index
*/
- ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED = 7,
+ ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED = 7,
/*!
* A parameter's MIDI channel has changed.
@@ -1104,21 +1135,13 @@ typedef enum {
*/
ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED = 45,
- /*!
- * A parameter's CV controlled status has changed.
- * @a pluginId Plugin Id
- * @a value1 Parameter index
- * @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,
+ ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 46,
} EngineCallbackOpcode;
@@ -1565,19 +1588,18 @@ typedef struct {
*/
int32_t rindex;
- /*!
- * Currently mapped MIDI CC.
- * A value lower than 0 means invalid or unused.
- * Maximum allowed value is 119 (0x77).
- */
- int16_t midiCC;
-
/*!
* Currently mapped MIDI channel.
* Counts from 0 to 15.
*/
uint8_t midiChannel;
+ /*!
+ * Currently mapped index.
+ * @see SpecialMappedControlIndex
+ */
+ int16_t mappedControlIndex;
+
/*!
* Minimum value that this parameter maps to.
*/
diff --git a/source/backend/CarlaHost.h b/source/backend/CarlaHost.h
index 700b20ba2..626b5110f 100644
--- a/source/backend/CarlaHost.h
+++ b/source/backend/CarlaHost.h
@@ -941,14 +941,6 @@ CARLA_EXPORT void carla_set_option(uint pluginId, uint option, bool yesNo);
CARLA_EXPORT void carla_set_parameter_value(uint pluginId, uint32_t parameterId, float value);
#ifndef BUILD_BRIDGE
-/*!
- * Change a plugin's parameter cv controlled status.
- * @param pluginId Plugin
- * @param parameterId Parameter index
- * @param cv_controlled New CV controlled Status
- */
-CARLA_EXPORT void carla_set_parameter_cv_controlled(uint pluginId, uint32_t parameterId, bool cv_controlled);
-
/*!
* Change a plugin's parameter MIDI channel.
* @param pluginId Plugin
@@ -958,12 +950,12 @@ CARLA_EXPORT void carla_set_parameter_cv_controlled(uint pluginId, uint32_t para
CARLA_EXPORT void carla_set_parameter_midi_channel(uint pluginId, uint32_t parameterId, uint8_t channel);
/*!
- * Change a plugin's parameter MIDI cc.
+ * Change a plugin's parameter mapped control index.
* @param pluginId Plugin
* @param parameterId Parameter index
- * @param cc New MIDI cc
+ * @param cc New control index
*/
-CARLA_EXPORT void carla_set_parameter_midi_cc(uint pluginId, uint32_t parameterId, int16_t cc);
+CARLA_EXPORT void carla_set_parameter_mapped_control_index(uint pluginId, uint32_t parameterId, int16_t index);
/*!
* Change a plugin's parameter mapped range.
diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp
index 4877f95c5..fa042721f 100644
--- a/source/backend/CarlaPlugin.hpp
+++ b/source/backend/CarlaPlugin.hpp
@@ -592,13 +592,6 @@ public:
*/
void setParameterValueByRealIndex(int32_t rindex, float value, bool sendGui, bool sendOsc, bool sendCallback) noexcept;
-#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
- /*!
- * Change parameter's @a parameterId CV controlled status.
- */
- void setParameterAsCvControl(uint32_t parameterId, bool cv_controlled, bool sendOsc, bool sendCallback) noexcept;
-#endif
-
/*!
* Set parameter's @a parameterId MIDI channel to @a channel.
* @a channel must be between 0 and 15.
@@ -606,10 +599,10 @@ public:
virtual void setParameterMidiChannel(uint32_t parameterId, uint8_t channel, bool sendOsc, bool sendCallback) noexcept;
/*!
- * Set parameter's @a parameterId MIDI CC to @a cc.
- * @a cc must be between 0 and 119 (0x77), or -1 for invalid.
+ * Set parameter's @a parameterId mapped control index to @a index.
+ * @see ParameterData::mappedControlIndex
*/
- virtual void setParameterMidiCC(uint32_t parameterId, int16_t cc, bool sendOsc, bool sendCallback) noexcept;
+ virtual void setParameterMappedControlIndex(uint32_t parameterId, int16_t index, bool sendOsc, bool sendCallback) noexcept;
/*!
* Set parameter's @a parameterId mapped range to @a minimum and @a maximum.
diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp
index e3cc6122a..d1ba3789a 100644
--- a/source/backend/CarlaStandalone.cpp
+++ b/source/backend/CarlaStandalone.cpp
@@ -1443,8 +1443,10 @@ const ParameterData* carla_get_parameter_data(uint pluginId, uint32_t parameterI
retParamData.hints = 0x0;
retParamData.index = CB::PARAMETER_NULL;
retParamData.rindex = -1;
- retParamData.midiCC = -1;
retParamData.midiChannel = 0;
+ retParamData.mappedControlIndex = CB::CONTROL_INDEX_NONE;
+ retParamData.mappedMinimum = 0.0f;
+ retParamData.mappedMaximum = 0.0f;
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr, &retParamData);
@@ -1459,8 +1461,10 @@ const ParameterData* carla_get_parameter_data(uint pluginId, uint32_t parameterI
retParamData.hints = pluginParamData.hints;
retParamData.index = pluginParamData.index;
retParamData.rindex = pluginParamData.rindex;
- retParamData.midiCC = pluginParamData.midiCC;
retParamData.midiChannel = pluginParamData.midiChannel;
+ retParamData.mappedControlIndex = pluginParamData.mappedControlIndex;
+ retParamData.mappedMinimum = pluginParamData.mappedMinimum;
+ retParamData.mappedMaximum = pluginParamData.mappedMaximum;
return &plugin->getParameterData(parameterId);
}
@@ -1984,18 +1988,6 @@ void carla_set_parameter_value(uint pluginId, uint32_t parameterId, float value)
}
#ifndef BUILD_BRIDGE
-void carla_set_parameter_cv_controlled(uint pluginId, uint32_t parameterId, bool cv_controlled)
-{
- 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_cv_controlled(%u, %u, %s)", pluginId, parameterId, bool2str(cv_controlled));
- CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),);
-
- return plugin->setParameterAsCvControl(parameterId, cv_controlled, true, false);
-}
void carla_set_parameter_midi_channel(uint pluginId, uint32_t parameterId, uint8_t channel)
{
@@ -2011,18 +2003,18 @@ void carla_set_parameter_midi_channel(uint pluginId, uint32_t parameterId, uint8
return plugin->setParameterMidiChannel(parameterId, channel, true, false);
}
-void carla_set_parameter_midi_cc(uint pluginId, uint32_t parameterId, int16_t cc)
+void carla_set_parameter_mapped_control_index(uint pluginId, uint32_t parameterId, int16_t index)
{
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL,);
+ CARLA_SAFE_ASSERT_RETURN(index >= CB::CONTROL_INDEX_NONE && index <= CB::CONTROL_INDEX_MAX_ALLOWED,);
CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId));
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
- carla_debug("carla_set_parameter_midi_cc(%i, %i, %i)", pluginId, parameterId, cc);
+ carla_debug("carla_set_parameter_mapped_control_index(%i, %i, %i)", pluginId, parameterId, cc);
CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),);
- return plugin->setParameterMidiCC(parameterId, cc, true, false);
+ return plugin->setParameterMappedControlIndex(parameterId, index, true, false);
}
void carla_set_parameter_mapped_range(uint pluginId, uint32_t parameterId, float minimum, float maximum)
diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp
index 72ce4a1af..291a71a0e 100644
--- a/source/backend/engine/CarlaEngineNative.cpp
+++ b/source/backend/engine/CarlaEngineNative.cpp
@@ -559,7 +559,11 @@ protected:
CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
std::snprintf(tmpBuf, STR_MAX, "%i:%i:%i:%i\n", paramData.type, paramData.hints,
- paramData.midiChannel, paramData.midiCC);
+ paramData.mappedControlIndex, paramData.midiChannel);
+ CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
+
+ std::snprintf(tmpBuf, STR_MAX, "%.12g:%.12g\n", static_cast(paramData.mappedMinimum),
+ static_cast(paramData.mappedMaximum));
CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),);
if (plugin->getParameterName(i, tmpBuf)) {
@@ -2074,42 +2078,43 @@ bool CarlaEngineNativeUI::msgReceived(const char*const msg) noexcept
fEngine->setParameterValueFromUI(pluginId, parameterId, value);
}
}
- else if (std::strcmp(msg, "set_parameter_cv_controlled") == 0)
+ else if (std::strcmp(msg, "set_parameter_midi_channel") == 0)
{
- uint32_t pluginId, parameterId;
- bool cv_controlled;
+ uint32_t pluginId, parameterId, channel;
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
- CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(cv_controlled), true);
+ CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
+ CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
- plugin->setParameterAsCvControl(parameterId, cv_controlled, true, false);
+ plugin->setParameterMidiChannel(parameterId, static_cast(channel), true, false);
}
- else if (std::strcmp(msg, "set_parameter_midi_channel") == 0)
+ else if (std::strcmp(msg, "set_parameter_mapped_control_index") == 0)
{
- uint32_t pluginId, parameterId, channel;
+ uint32_t pluginId, parameterId;
+ int32_t ctrl;
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
- CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(channel), true);
- CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, true);
+ CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(ctrl), true);
+ CARLA_SAFE_ASSERT_RETURN(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED, true);
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
- plugin->setParameterMidiChannel(parameterId, static_cast(channel), true, false);
+ plugin->setParameterMappedControlIndex(parameterId, static_cast(ctrl), true, false);
}
- else if (std::strcmp(msg, "set_parameter_midi_cc") == 0)
+ else if (std::strcmp(msg, "set_parameter_mapped_range") == 0)
{
uint32_t pluginId, parameterId;
- int32_t cc;
+ float minimum, maximum;
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true);
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), true);
- CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(cc), true);
- CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL, true);
+ CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(minimum), true);
+ CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(maximum), true);
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId))
- plugin->setParameterMidiCC(parameterId, static_cast(cc), true, false);
+ plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false);
}
else if (std::strcmp(msg, "set_parameter_touch") == 0)
{
diff --git a/source/backend/engine/CarlaEngineOsc.hpp b/source/backend/engine/CarlaEngineOsc.hpp
index 7c6cbbd06..26da48764 100644
--- a/source/backend/engine/CarlaEngineOsc.hpp
+++ b/source/backend/engine/CarlaEngineOsc.hpp
@@ -149,7 +149,8 @@ private:
int handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS);
int handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS);
int handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS);
- int handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS);
+ int handleMsgSetParameterMappedControlIndex(CARLA_ENGINE_OSC_HANDLE_ARGS);
+ int handleMsgSetParameterMappedRange(CARLA_ENGINE_OSC_HANDLE_ARGS);
int handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS);
int handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS);
int handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS);
diff --git a/source/backend/engine/CarlaEngineOscHandlers.cpp b/source/backend/engine/CarlaEngineOscHandlers.cpp
index ce344ddf9..1cea6c8a6 100644
--- a/source/backend/engine/CarlaEngineOscHandlers.cpp
+++ b/source/backend/engine/CarlaEngineOscHandlers.cpp
@@ -160,8 +160,10 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons
return 0; //handleMsgSetControlChannel(plugin, argc, argv, types); // TODO
if (std::strcmp(method, "set_parameter_value") == 0)
return handleMsgSetParameterValue(plugin, argc, argv, types);
- if (std::strcmp(method, "set_parameter_midi_cc") == 0)
- return handleMsgSetParameterMidiCC(plugin, argc, argv, types);
+ if (std::strcmp(method, "set_parameter_mapped_control_index") == 0)
+ return handleMsgSetParameterMappedControlIndex(plugin, argc, argv, types);
+ if (std::strcmp(method, "set_parameter_mapped_range") == 0)
+ return handleMsgSetParameterMappedRange(plugin, argc, argv, types);
if (std::strcmp(method, "set_parameter_midi_channel") == 0)
return handleMsgSetParameterMidiChannel(plugin, argc, argv, types);
if (std::strcmp(method, "set_program") == 0)
@@ -630,18 +632,33 @@ int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS)
return 0;
}
-int CarlaEngineOsc::handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS)
+int CarlaEngineOsc::handleMsgSetParameterMappedControlIndex(CARLA_ENGINE_OSC_HANDLE_ARGS)
{
- carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiCC()");
+ carla_debug("CarlaEngineOsc::handleMsgSetParameterMappedIndex()");
CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
const int32_t index = argv[0]->i;
- const int32_t cc = argv[1]->i;
+ const int32_t ctrl = argv[1]->i;
CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
- CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL, 0);
+ CARLA_SAFE_ASSERT_RETURN(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED, 0);
- plugin->setParameterMidiCC(static_cast(index), static_cast(cc), false, true);
+ plugin->setParameterMappedControlIndex(static_cast(index), static_cast(ctrl), false, true);
+ return 0;
+}
+
+int CarlaEngineOsc::handleMsgSetParameterMappedRange(CARLA_ENGINE_OSC_HANDLE_ARGS)
+{
+ carla_debug("CarlaEngineOsc::handleMsgSetParameterMappedRange()");
+ CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "iff");
+
+ const int32_t index = argv[0]->i;
+ const float minimum = argv[1]->f;
+ const float maximum = argv[2]->f;
+
+ CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
+
+ plugin->setParameterMappedRange(static_cast(index), minimum, maximum, false, true);
return 0;
}
diff --git a/source/backend/engine/CarlaEngineOscSend.cpp b/source/backend/engine/CarlaEngineOscSend.cpp
index bc11e3ac7..4247969a4 100644
--- a/source/backend/engine/CarlaEngineOscSend.cpp
+++ b/source/backend/engine/CarlaEngineOscSend.cpp
@@ -149,7 +149,7 @@ void CarlaEngineOsc::sendPluginParameterInfo(const CarlaPlugin* const plugin, co
try_lo_send(fControlDataTCP.target, targetPath, "iiiiiissfffffff",
static_cast(plugin->getId()), static_cast(index),
static_cast(paramData.type), static_cast(paramData.hints),
- static_cast(paramData.midiChannel), static_cast(paramData.midiCC),
+ static_cast(paramData.mappedControlIndex), static_cast(paramData.midiChannel),
bufName, bufUnit,
static_cast(paramRanges.def),
static_cast(paramRanges.min),
diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp
index f57e9cecc..89a0359c5 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, 0.0f, 1.0f };
+static const ParameterData kParameterDataNull = { PARAMETER_UNKNOWN, 0x0, PARAMETER_NULL, -1, 0, CONTROL_INDEX_NONE, 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 };
@@ -600,7 +600,7 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)
const bool dummy = paramData.type != PARAMETER_INPUT || usingChunk;
- if (dummy && paramData.midiCC <= -1)
+ if (dummy && paramData.mappedControlIndex <= CONTROL_INDEX_NONE)
continue;
CarlaStateSave::Parameter* const stateParameter(new CarlaStateSave::Parameter());
@@ -608,8 +608,8 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)
stateParameter->dummy = dummy;
stateParameter->index = paramData.index;
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
- stateParameter->midiCC = paramData.midiCC;
- stateParameter->midiChannel = paramData.midiChannel;
+ stateParameter->mappedControlIndex = paramData.mappedControlIndex;
+ stateParameter->midiChannel = paramData.midiChannel;
#endif
if (! getParameterName(i, strBuf))
@@ -821,7 +821,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
}
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
- setParameterMidiCC(static_cast(index), stateParameter->midiCC, true, true);
+ setParameterMappedControlIndex(static_cast(index), stateParameter->mappedControlIndex, true, true);
setParameterMidiChannel(static_cast(index), stateParameter->midiChannel, true, true);
#endif
}
@@ -1670,49 +1670,6 @@ void CarlaPlugin::setParameterValueByRealIndex(const int32_t rindex, const float
}
}
-#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
-void CarlaPlugin::setParameterAsCvControl(uint32_t parameterId, bool cv_controlled, bool sendOsc, 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,);
- CARLA_SAFE_ASSERT_RETURN(pData->param.data[parameterId].type == PARAMETER_INPUT,);
- CARLA_SAFE_ASSERT_RETURN(pData->param.data[parameterId].hints & PARAMETER_CAN_BE_CV_CONTROLLED,);
- CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,);
-
- if (cv_controlled)
- {
- char strBuf[STR_MAX+1];
- carla_zeroChars(strBuf, STR_MAX+1);
- if (! getParameterName(parameterId, strBuf))
- std::snprintf(strBuf, STR_MAX, "Param %u", parameterId);
-
- const uint portNameSize = pData->engine->getMaxPortNameSize();
- if (portNameSize < STR_MAX)
- strBuf[portNameSize] = '\0';
-
- CarlaEngineCVPort* const cvPort =
- (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, strBuf, true, parameterId);
- cvPort->setRange(pData->param.ranges[parameterId].min, pData->param.ranges[parameterId].max);
- pData->event.cvSourcePorts->addCVSource(cvPort, parameterId);
- }
- else
- {
- pData->event.cvSourcePorts->removeCVSource(parameterId);
- }
-
- pData->engine->callback(sendCallback, sendOsc,
- ENGINE_CALLBACK_PARAMETER_CV_CONTROLLED_STATUS_CHANGED,
- pData->id,
- static_cast(parameterId),
- cv_controlled ? 1 : 0,
- 0, 0.0f, nullptr);
-}
-#endif
-
void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept
{
if (pData->engineBridged) {
@@ -1723,6 +1680,9 @@ void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
+ if (pData->param.data[parameterId].midiChannel == channel)
+ return;
+
pData->param.data[parameterId].midiChannel = channel;
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
@@ -1735,7 +1695,7 @@ void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint
#endif
}
-void CarlaPlugin::setParameterMidiCC(const uint32_t parameterId, const int16_t cc, const bool sendOsc, const bool sendCallback) noexcept
+void CarlaPlugin::setParameterMappedControlIndex(const uint32_t parameterId, const int16_t index, const bool sendOsc, const bool sendCallback) noexcept
{
if (pData->engineBridged) {
CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
@@ -1743,16 +1703,44 @@ void CarlaPlugin::setParameterMidiCC(const uint32_t parameterId, const int16_t c
CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
}
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
- CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL,);
+ CARLA_SAFE_ASSERT_RETURN(index >= CONTROL_INDEX_NONE && index <= CONTROL_INDEX_MAX_ALLOWED,);
+
+ if (pData->param.data[parameterId].mappedControlIndex == index)
+ return;
+
+ if (index == CONTROL_INDEX_CV)
+ {
+ CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,);
+
+ char strBuf[STR_MAX+1];
+ carla_zeroChars(strBuf, STR_MAX+1);
+ if (! getParameterName(parameterId, strBuf))
+ std::snprintf(strBuf, STR_MAX, "Param %u", parameterId);
+
+ const uint portNameSize = pData->engine->getMaxPortNameSize();
+ if (portNameSize < STR_MAX)
+ strBuf[portNameSize] = '\0';
+
+ CarlaEngineCVPort* const cvPort =
+ (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, strBuf, true, parameterId);
+ cvPort->setRange(pData->param.ranges[parameterId].min, pData->param.ranges[parameterId].max);
+ pData->event.cvSourcePorts->addCVSource(cvPort, parameterId);
+ }
+ else if (pData->param.data[parameterId].mappedControlIndex == CONTROL_INDEX_CV)
+ {
+ CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,);
+
+ pData->event.cvSourcePorts->removeCVSource(parameterId);
+ }
- pData->param.data[parameterId].midiCC = cc;
+ pData->param.data[parameterId].mappedControlIndex = index;
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
pData->engine->callback(sendCallback, sendOsc,
- ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED,
+ ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED,
pData->id,
static_cast(parameterId),
- cc,
+ index,
0, 0.0f, nullptr);
#endif
}
@@ -1766,6 +1754,10 @@ void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const floa
}
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
+ if (carla_isEqual(pData->param.data[parameterId].mappedMinimum, minimum) &&
+ carla_isEqual(pData->param.data[parameterId].mappedMaximum, maximum))
+ return;
+
pData->param.data[parameterId].mappedMinimum = minimum;
pData->param.data[parameterId].mappedMaximum = maximum;
@@ -1775,7 +1767,7 @@ void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const floa
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
pData->engine->callback(sendCallback, sendOsc,
- ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED,
+ ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED,
pData->id,
static_cast(parameterId),
0, 0, 0.0f,
diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp
index 380710909..02d17c657 100644
--- a/source/backend/plugin/CarlaPluginBridge.cpp
+++ b/source/backend/plugin/CarlaPluginBridge.cpp
@@ -749,22 +749,22 @@ public:
CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback);
}
- void setParameterMidiCC(const uint32_t parameterId, const int16_t cc, const bool sendOsc, const bool sendCallback) noexcept override
+ void setParameterMappedControlIndex(const uint32_t parameterId, const int16_t index, const bool sendOsc, const bool sendCallback) noexcept override
{
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
- CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL,);
+ CARLA_SAFE_ASSERT_RETURN(index >= CONTROL_INDEX_NONE && index <= CONTROL_INDEX_MAX_ALLOWED,);
CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,);
{
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
- fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiCC);
+ fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedControlIndex);
fShmNonRtClientControl.writeUInt(parameterId);
- fShmNonRtClientControl.writeShort(cc);
+ fShmNonRtClientControl.writeShort(index);
fShmNonRtClientControl.commitWrite();
}
- CarlaPlugin::setParameterMidiCC(parameterId, cc, sendOsc, sendCallback);
+ CarlaPlugin::setParameterMappedControlIndex(parameterId, index, sendOsc, sendCallback);
}
void setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept override
@@ -1533,10 +1533,14 @@ public:
if (pData->param.data[k].type != PARAMETER_OUTPUT)
continue;
- if (pData->param.data[k].midiCC > 0)
+ if (pData->param.data[k].mappedControlIndex > 0)
{
value = pData->param.ranges[k].getNormalizedValue(fParams[k].value);
- pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast(pData->param.data[k].midiCC), value);
+ pData->event.portOut->writeControlEvent(0,
+ pData->param.data[k].midiChannel,
+ kEngineControlEventTypeParameter,
+ static_cast(pData->param.data[k].mappedControlIndex),
+ value);
}
}
@@ -2117,9 +2121,9 @@ public:
const int32_t rindex = fShmNonRtServerControl.readInt();
const uint32_t type = fShmNonRtServerControl.readUInt();
const uint32_t hints = fShmNonRtServerControl.readUInt();
- const int16_t midiCC = fShmNonRtServerControl.readShort();
+ const int16_t ctrl = fShmNonRtServerControl.readShort();
- CARLA_SAFE_ASSERT_BREAK(midiCC >= -1 && midiCC < MAX_MIDI_CONTROL);
+ CARLA_SAFE_ASSERT_BREAK(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED);
CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
if (index < pData->param.count)
@@ -2128,7 +2132,7 @@ public:
pData->param.data[index].index = static_cast(index);
pData->param.data[index].rindex = rindex;
pData->param.data[index].hints = hints;
- pData->param.data[index].midiCC = midiCC;
+ pData->param.data[index].mappedControlIndex = ctrl;
}
} break;
diff --git a/source/backend/plugin/CarlaPluginFluidSynth.cpp b/source/backend/plugin/CarlaPluginFluidSynth.cpp
index 60f19b756..b5e43e5af 100644
--- a/source/backend/plugin/CarlaPluginFluidSynth.cpp
+++ b/source/backend/plugin/CarlaPluginFluidSynth.cpp
@@ -777,7 +777,7 @@ public:
pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/;
pData->param.data[j].index = j;
pData->param.data[j].rindex = j;
- pData->param.data[j].midiCC = MIDI_CONTROL_REVERB_SEND_LEVEL;
+ pData->param.data[j].mappedControlIndex = MIDI_CONTROL_REVERB_SEND_LEVEL;
pData->param.ranges[j].min = 0.0f;
pData->param.ranges[j].max = 1.0f;
pData->param.ranges[j].def = sFluidDefaults[j];
@@ -1239,7 +1239,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].hints != PARAMETER_INPUT)
continue;
@@ -1427,10 +1427,14 @@ public:
fParamBuffers[k] = float(fluid_synth_get_active_voice_count(fSynth));
pData->param.ranges[k].fixValue(fParamBuffers[k]);
- if (pData->param.data[k].midiCC > 0)
+ if (pData->param.data[k].mappedControlIndex > 0)
{
float value(pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]));
- pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast(pData->param.data[k].midiCC), value);
+ pData->event.portOut->writeControlEvent(0,
+ pData->param.data[k].midiChannel,
+ kEngineControlEventTypeParameter,
+ static_cast(pData->param.data[k].mappedControlIndex),
+ value);
}
} // End of Control Output
diff --git a/source/backend/plugin/CarlaPluginInternal.cpp b/source/backend/plugin/CarlaPluginInternal.cpp
index 4f572e02b..dce584904 100644
--- a/source/backend/plugin/CarlaPluginInternal.cpp
+++ b/source/backend/plugin/CarlaPluginInternal.cpp
@@ -222,7 +222,7 @@ void PluginParameterData::createNew(const uint32_t newCount, const bool withSpec
{
data[i].index = PARAMETER_NULL;
data[i].rindex = PARAMETER_NULL;
- data[i].midiCC = -1;
+ data[i].mappedControlIndex = CONTROL_INDEX_NONE;
}
ranges = new ParameterRanges[newCount];
diff --git a/source/backend/plugin/CarlaPluginJuce.cpp b/source/backend/plugin/CarlaPluginJuce.cpp
index d8bb20f7f..cf7b5e99f 100644
--- a/source/backend/plugin/CarlaPluginJuce.cpp
+++ b/source/backend/plugin/CarlaPluginJuce.cpp
@@ -881,7 +881,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].type != PARAMETER_INPUT)
continue;
diff --git a/source/backend/plugin/CarlaPluginLADSPADSSI.cpp b/source/backend/plugin/CarlaPluginLADSPADSSI.cpp
index f200fbe78..1603a5779 100644
--- a/source/backend/plugin/CarlaPluginLADSPADSSI.cpp
+++ b/source/backend/plugin/CarlaPluginLADSPADSSI.cpp
@@ -1132,7 +1132,7 @@ public:
{
const int16_t cc = DSSI_CC_NUMBER(ctrl);
if (! MIDI_IS_CONTROL_BANK_SELECT(cc))
- pData->param.data[j].midiCC = cc;
+ pData->param.data[j].mappedControlIndex = cc;
}
}
}
@@ -1702,7 +1702,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].type != PARAMETER_INPUT)
continue;
@@ -1943,10 +1943,10 @@ public:
pData->param.ranges[k].fixValue(fParamBuffers[k]);
- if (pData->param.data[k].midiCC > 0)
+ if (pData->param.data[k].mappedControlIndex > 0)
{
channel = pData->param.data[k].midiChannel;
- param = static_cast(pData->param.data[k].midiCC);
+ param = static_cast(pData->param.data[k].mappedControlIndex);
value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
}
diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp
index f7214418a..9ae5482fa 100644
--- a/source/backend/plugin/CarlaPluginLV2.cpp
+++ b/source/backend/plugin/CarlaPluginLV2.cpp
@@ -2574,7 +2574,7 @@ public:
if (LV2_IS_PORT_MIDI_MAP_CC(portMidiMap.Type))
{
if (portMidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(portMidiMap.Number))
- pData->param.data[j].midiCC = static_cast(portMidiMap.Number);
+ pData->param.data[j].mappedControlIndex = static_cast(portMidiMap.Number);
}
}
else if (LV2_IS_PORT_OUTPUT(portTypes))
@@ -3678,7 +3678,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].type != PARAMETER_INPUT)
continue;
@@ -4039,10 +4039,10 @@ public:
// plugin is responsible to ensure correct bounds
pData->param.ranges[k].fixValue(fParamBuffers[k]);
- if (pData->param.data[k].midiCC > 0)
+ if (pData->param.data[k].mappedControlIndex > 0)
{
channel = pData->param.data[k].midiChannel;
- param = static_cast(pData->param.data[k].midiCC);
+ param = static_cast(pData->param.data[k].mappedControlIndex);
value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
}
diff --git a/source/backend/plugin/CarlaPluginNative.cpp b/source/backend/plugin/CarlaPluginNative.cpp
index ee9b7aaa4..0ee60dd83 100644
--- a/source/backend/plugin/CarlaPluginNative.cpp
+++ b/source/backend/plugin/CarlaPluginNative.cpp
@@ -1941,7 +1941,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].type != PARAMETER_INPUT)
continue;
@@ -2191,10 +2191,14 @@ public:
curValue = fDescriptor->get_parameter_value(fHandle, k);
pData->param.ranges[k].fixValue(curValue);
- if (pData->param.data[k].midiCC > 0)
+ if (pData->param.data[k].mappedControlIndex > 0)
{
value = pData->param.ranges[k].getNormalizedValue(curValue);
- pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast(pData->param.data[k].midiCC), value);
+ pData->event.portOut->writeControlEvent(0,
+ pData->param.data[k].midiChannel,
+ kEngineControlEventTypeParameter,
+ static_cast(pData->param.data[k].mappedControlIndex),
+ value);
}
}
} // End of Control Output
diff --git a/source/backend/plugin/CarlaPluginSFZero.cpp b/source/backend/plugin/CarlaPluginSFZero.cpp
index 843893955..a87856a43 100644
--- a/source/backend/plugin/CarlaPluginSFZero.cpp
+++ b/source/backend/plugin/CarlaPluginSFZero.cpp
@@ -457,7 +457,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].hints != PARAMETER_INPUT)
continue;
diff --git a/source/backend/plugin/CarlaPluginVST2.cpp b/source/backend/plugin/CarlaPluginVST2.cpp
index 07c030378..2c73999bb 100644
--- a/source/backend/plugin/CarlaPluginVST2.cpp
+++ b/source/backend/plugin/CarlaPluginVST2.cpp
@@ -1389,7 +1389,7 @@ public:
{
if (pData->param.data[k].midiChannel != event.channel)
continue;
- if (pData->param.data[k].midiCC != ctrlEvent.param)
+ if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
continue;
if (pData->param.data[k].type != PARAMETER_INPUT)
continue;
diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py
index 2c89641de..c496ee831 100644
--- a/source/frontend/carla_backend.py
+++ b/source/frontend/carla_backend.py
@@ -539,6 +539,22 @@ PARAMETER_CTRL_CHANNEL = -8
# Max value, defined only for convenience.
PARAMETER_MAX = -9
+# ------------------------------------------------------------------------------------------------------------
+# Special Mapped Control Index
+
+# Specially designated mapped control indexes.
+# Values between 0 and 119 (0x77) are reserved for MIDI CC, which uses direct values.
+# @see ParameterData::mappedControlIndex
+
+# Unused control index, meaning no mapping is enabled.
+CONTROL_VALUE_NONE = -1
+
+# CV control index, meaning the parameter is exposed as CV port.
+CONTROL_VALUE_CV = 130
+
+# Special value to indicate MIDI pitchbend.
+CONTROL_VALUE_MIDI_PITCHBEND = 131
+
# ------------------------------------------------------------------------------------------------------------
# Engine Callback Opcode
# Engine callback opcodes.
@@ -580,11 +596,11 @@ ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED = 5
# @a valuef New default value
ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED = 6
-# A parameter's MIDI CC has changed.
+# A parameter's mapped control index has changed.
# @a pluginId Plugin Id
# @a value1 Parameter index
-# @a value2 New MIDI CC
-ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED = 7
+# @a value2 New control index
+ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED = 7
# A parameter's MIDI channel has changed.
# @a pluginId Plugin Id
@@ -796,17 +812,11 @@ ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_REMOVED = 44
# @see PatchbayPortGroupHints
ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED = 45
-# A parameter's CV controlled status has changed.
-# @a pluginId Plugin Id
-# @a value1 Parameter index
-# @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
+ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 46
# ------------------------------------------------------------------------------------------------------------
# NSM Callback Opcode
@@ -1089,15 +1099,14 @@ class ParameterData(Structure):
# Real index as seen by plugins.
("rindex", c_int32),
- # Currently mapped MIDI CC.
- # A value lower than 0 means invalid or unused.
- # Maximum allowed value is 119 (0x77).
- ("midiCC", c_int16),
-
# Currently mapped MIDI channel.
# Counts from 0 to 15.
("midiChannel", c_uint8),
+ # Currently mapped index.
+ # @see SpecialMappedControlIndex
+ ("mappedControlIndex", c_int16),
+
# Minimum value that this parameter maps to.
("mappedMinimum", c_uint8),
@@ -1180,8 +1189,8 @@ PyParameterData = {
'hints': 0x0,
'index': PARAMETER_NULL,
'rindex': -1,
- 'midiCC': -1,
'midiChannel': 0,
+ 'mappedControlIndex': CONTROL_VALUE_NONE,
'mappedMinimum': 0.0,
'mappedMaximum': 1.0,
}
@@ -2050,15 +2059,7 @@ class CarlaHostMeta(object):
def set_parameter_value(self, pluginId, parameterId, value):
raise NotImplementedError
- # Change a plugin's parameter cv controlled status.
- # @param pluginId Plugin
- # @param parameterId Parameter index
- # @param cv_controlled New CV controlled Status
- @abstractmethod
- def set_parameter_cv_controlled(self, pluginId, parameterId, cv_controlled):
- raise NotImplementedError
-
- # Change a plugin's parameter MIDI cc.
+ # Change a plugin's parameter mapped control index.
# @param pluginId Plugin
# @param parameterId Parameter index
# @param cc New MIDI cc
@@ -2069,9 +2070,9 @@ class CarlaHostMeta(object):
# Change a plugin's parameter MIDI channel.
# @param pluginId Plugin
# @param parameterId Parameter index
- # @param channel New MIDI channel
+ # @param channel New control index
@abstractmethod
- def set_parameter_midi_cc(self, pluginId, parameterId, cc):
+ def set_parameter_mapped_control_index(self, pluginId, parameterId, index):
raise NotImplementedError
# Change a plugin's parameter mapped range.
@@ -2464,13 +2465,10 @@ class CarlaHostNull(CarlaHostMeta):
def set_parameter_value(self, pluginId, parameterId, value):
return
- def set_parameter_cv_controlled(self, pluginId, parameterId, cv_controlled):
- return
-
def set_parameter_midi_channel(self, pluginId, parameterId, channel):
return
- def set_parameter_midi_cc(self, pluginId, parameterId, cc):
+ def set_parameter_mapped_control_index(self, pluginId, parameterId, index):
return
def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum):
@@ -2782,14 +2780,11 @@ class CarlaHostDLL(CarlaHostMeta):
self.lib.carla_set_parameter_value.argtypes = [c_uint, c_uint32, c_float]
self.lib.carla_set_parameter_value.restype = None
- self.lib.carla_set_parameter_cv_controlled.argtypes = [c_uint, c_uint32, c_bool]
- self.lib.carla_set_parameter_cv_controlled.restype = None
-
self.lib.carla_set_parameter_midi_channel.argtypes = [c_uint, c_uint32, c_uint8]
self.lib.carla_set_parameter_midi_channel.restype = None
- 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_control_index.argtypes = [c_uint, c_uint32, c_int16]
+ self.lib.carla_set_parameter_mapped_control_index.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
@@ -3107,14 +3102,11 @@ class CarlaHostDLL(CarlaHostMeta):
def set_parameter_value(self, pluginId, parameterId, value):
self.lib.carla_set_parameter_value(pluginId, parameterId, value)
- def set_parameter_cv_controlled(self, pluginId, parameterId, cv_controlled):
- self.lib.carla_set_parameter_cv_controlled(pluginId, parameterId, cv_controlled)
-
def set_parameter_midi_channel(self, pluginId, parameterId, channel):
self.lib.carla_set_parameter_midi_channel(pluginId, parameterId, channel)
- def set_parameter_midi_cc(self, pluginId, parameterId, cc):
- self.lib.carla_set_parameter_midi_cc(pluginId, parameterId, cc)
+ def set_parameter_mapped_control_index(self, pluginId, parameterId, index):
+ self.lib.carla_set_parameter_mapped_control_index(pluginId, parameterId, index)
def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum):
self.lib.carla_set_parameter_mapped_range(pluginId, parameterId, minimum, maximum)
@@ -3513,16 +3505,18 @@ class CarlaHostPlugin(CarlaHostMeta):
self.sendMsg(["set_parameter_value", pluginId, parameterId, value])
self.fPluginsInfo[pluginId].parameterValues[parameterId] = value
- def set_parameter_cv_controlled(self, pluginId, parameterId, cv_controlled):
- self.sendMsg(["set_parameter_cv_controlled", pluginId, parameterId, cv_controlled])
-
def set_parameter_midi_channel(self, pluginId, parameterId, channel):
self.sendMsg(["set_parameter_midi_channel", pluginId, parameterId, channel])
- self.fPluginsInfo[pluginId].parameterData[parameterId]['midiCC'] = channel
+ self.fPluginsInfo[pluginId].parameterData[parameterId]['midiChannel'] = channel
- def set_parameter_midi_cc(self, pluginId, parameterId, cc):
- self.sendMsg(["set_parameter_midi_cc", pluginId, parameterId, cc])
- self.fPluginsInfo[pluginId].parameterData[parameterId]['midiCC'] = cc
+ def set_parameter_mapped_control_index(self, pluginId, parameterId, index):
+ self.sendMsg(["set_parameter_mapped_control_index", pluginId, parameterId, index])
+ self.fPluginsInfo[pluginId].parameterData[parameterId]['mappedControlIndex'] = index
+
+ def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum):
+ self.sendMsg(["set_parameter_mapped_range", pluginId, parameterId, minimum, maximum])
+ self.fPluginsInfo[pluginId].parameterData[parameterId]['mappedMinimum'] = minimum
+ self.fPluginsInfo[pluginId].parameterData[parameterId]['mappedMaximum'] = maximum
def set_parameter_touch(self, pluginId, parameterId, touch):
self.sendMsg(["set_parameter_touch", pluginId, parameterId, touch])
@@ -3768,36 +3762,36 @@ class CarlaHostPlugin(CarlaHostMeta):
else:
print("_set_parameterDefault failed for", pluginId, "and index", paramIndex)
- def _set_parameterMidiChannel(self, pluginId, paramIndex, channel):
+ def _set_parameterMappedControlIndex(self, pluginId, paramIndex, index):
plugin = self.fPluginsInfo.get(pluginId, None)
if plugin is None:
- print("_set_parameterMidiChannel failed for", pluginId)
+ print("_set_parameterMappedControlIndex failed for", pluginId)
return
if paramIndex < plugin.parameterCount:
- plugin.parameterData[paramIndex]['midiChannel'] = channel
+ plugin.parameterData[paramIndex]['mappedControlIndex'] = index
else:
- print("_set_parameterMidiChannel failed for", pluginId, "and index", paramIndex)
+ print("_set_parameterMappedControlIndex failed for", pluginId, "and index", paramIndex)
- def _set_parameterMidiCC(self, pluginId, paramIndex, cc):
+ def _set_parameterMappedRange(self, pluginId, paramIndex, minimum, maximum):
plugin = self.fPluginsInfo.get(pluginId, None)
if plugin is None:
- print("_set_parameterMidiCC failed for", pluginId)
+ print("_set_parameterMappedRange failed for", pluginId)
return
if paramIndex < plugin.parameterCount:
- plugin.parameterData[paramIndex]['midiCC'] = cc
+ plugin.parameterData[paramIndex]['mappedMinimum'] = minimum
+ plugin.parameterData[paramIndex]['mappedMaximum'] = maximum
else:
- print("_set_parameterMidiCC failed for", pluginId, "and index", paramIndex)
+ print("_set_parameterMappedRange failed for", pluginId, "and index", paramIndex)
- def _set_parameterMappedRange(self, pluginId, paramIndex, minimum, maximum):
+ def _set_parameterMidiChannel(self, pluginId, paramIndex, channel):
plugin = self.fPluginsInfo.get(pluginId, None)
if plugin is None:
- print("_set_parameterMappedRange failed for", pluginId)
+ print("_set_parameterMidiChannel failed for", pluginId)
return
if paramIndex < plugin.parameterCount:
- plugin.parameterData[paramIndex]['mappedMinimum'] = minimum
- plugin.parameterData[paramIndex]['mappedMaximum'] = maximum
+ plugin.parameterData[paramIndex]['midiChannel'] = channel
else:
- print("_set_parameterMappedRange failed for", pluginId, "and index", paramIndex)
+ print("_set_parameterMidiChannel failed for", pluginId, "and index", paramIndex)
def _set_currentProgram(self, pluginId, pIndex):
plugin = self.fPluginsInfo.get(pluginId, None)
@@ -3877,16 +3871,16 @@ class CarlaHostPlugin(CarlaHostMeta):
elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED:
self._set_parameterDefault(pluginId, value1, valuef)
- elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED:
- self._set_parameterMidiCC(pluginId, value1, value2)
-
- elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
- self._set_parameterMidiChannel(pluginId, value1, value2)
+ elif action == ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED:
+ self._set_parameterMappedControlIndex(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_PARAMETER_MIDI_CHANNEL_CHANGED:
+ self._set_parameterMidiChannel(pluginId, value1, value2)
+
elif action == ENGINE_CALLBACK_PROGRAM_CHANGED:
self._set_currentProgram(pluginId, value1)
diff --git a/source/frontend/carla_backend_qt.py b/source/frontend/carla_backend_qt.py
index 2aee74b65..44cfd79fe 100644
--- a/source/frontend/carla_backend_qt.py
+++ b/source/frontend/carla_backend_qt.py
@@ -38,7 +38,7 @@ class CarlaHostSignals(QObject):
PluginUnavailableCallback = pyqtSignal(int, str)
ParameterValueChangedCallback = pyqtSignal(int, int, float)
ParameterDefaultChangedCallback = pyqtSignal(int, int, float)
- ParameterMidiCcChangedCallback = pyqtSignal(int, int, int)
+ ParameterMappedControlIndexChangedCallback = pyqtSignal(int, int, int)
ParameterMidiChannelChangedCallback = pyqtSignal(int, int, int)
ProgramChangedCallback = pyqtSignal(int, int)
MidiProgramChangedCallback = pyqtSignal(int, int)
diff --git a/source/frontend/carla_control.py b/source/frontend/carla_control.py
index 51066c354..a9345de72 100755
--- a/source/frontend/carla_control.py
+++ b/source/frontend/carla_control.py
@@ -381,7 +381,7 @@ class CarlaControlServerTCP(Server):
if DEBUG: print(path, args)
self.fReceivedMsgs = True
(
- pluginId, paramId, type_, hints, midiChan, midiCC, name, unit,
+ pluginId, paramId, type_, hints, mappedControlIndex, midiChan, name, unit,
def_, min_, max_, step, stepSmall, stepLarge, value
) = args
@@ -400,7 +400,7 @@ class CarlaControlServerTCP(Server):
'hints': hints,
'index': paramId,
'rindex': -1,
- 'midiCC': midiCC,
+ 'mappedControlIndex': mappedControlIndex,
'midiChannel': midiChan,
}
self.host._set_parameterData(pluginId, paramId, paramData)
diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py
index 75aa17a05..632b69f8e 100644
--- a/source/frontend/carla_host.py
+++ b/source/frontend/carla_host.py
@@ -2749,8 +2749,8 @@ def engineCallback(host, action, pluginId, value1, value2, value3, valuef, value
host.ParameterValueChangedCallback.emit(pluginId, value1, valuef)
elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED:
host.ParameterDefaultChangedCallback.emit(pluginId, value1, valuef)
- elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED:
- host.ParameterMidiCcChangedCallback.emit(pluginId, value1, value2)
+ elif action == ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED:
+ host.ParameterMappedControlIndexChangedCallback.emit(pluginId, value1, value2)
elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
host.ParameterMidiChannelChangedCallback.emit(pluginId, value1, value2)
elif action == ENGINE_CALLBACK_PROGRAM_CHANGED:
diff --git a/source/frontend/carla_skin.py b/source/frontend/carla_skin.py
index 2d1b9884f..902069dd8 100644
--- a/source/frontend/carla_skin.py
+++ b/source/frontend/carla_skin.py
@@ -286,8 +286,8 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta):
host.PluginUnavailableCallback.connect(self.slot_handlePluginUnavailableCallback)
host.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback)
host.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback)
+ host.ParameterMappedControlIndexChangedCallback.connect(self.slot_handleParameterMappedControlIndexChangedCallback)
host.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback)
- host.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback)
host.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback)
host.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback)
host.OptionChangedCallback.connect(self.slot_handleOptionChangedCallback)
@@ -322,9 +322,9 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta):
self.setParameterDefault(index, value)
@pyqtSlot(int, int, int)
- def slot_handleParameterMidiCcChangedCallback(self, pluginId, index, cc):
+ def slot_handleParameterMappedControlIndexChangedCallback(self, pluginId, index, ctrl):
if self.fPluginId == pluginId:
- self.setParameterMidiControl(index, cc)
+ self.setParameterMappedControlIndex(index, ctrl)
@pyqtSlot(int, int, int)
def slot_handleParameterMidiChannelChangedCallback(self, pluginId, index, channel):
@@ -738,8 +738,8 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta):
def setParameterDefault(self, parameterId, value):
self.fEditDialog.setParameterDefault(parameterId, value)
- def setParameterMidiControl(self, parameterId, control):
- self.fEditDialog.setParameterMidiControl(parameterId, control)
+ def setParameterMappedControlIndex(self, parameterId, control):
+ self.fEditDialog.setParameterMappedControlIndex(parameterId, control)
def setParameterMidiChannel(self, parameterId, channel):
self.fEditDialog.setParameterMidiChannel(parameterId, channel)
diff --git a/source/frontend/carla_widgets.py b/source/frontend/carla_widgets.py
index 2e4138414..5a92fe693 100755
--- a/source/frontend/carla_widgets.py
+++ b/source/frontend/carla_widgets.py
@@ -211,9 +211,9 @@ class JuceAboutW(QDialog):
# Plugin Parameter
class PluginParameter(QWidget):
- midiControlChanged = pyqtSignal(int, int)
- midiChannelChanged = pyqtSignal(int, int)
- valueChanged = pyqtSignal(int, float)
+ mappedControlChanged = pyqtSignal(int, int)
+ midiChannelChanged = pyqtSignal(int, int)
+ valueChanged = pyqtSignal(int, float)
def __init__(self, parent, host, pInfo, pluginId, tabIndex):
QWidget.__init__(self, parent)
@@ -229,7 +229,7 @@ class PluginParameter(QWidget):
# -------------------------------------------------------------
# Internal stuff
- self.fMidiControl = -1
+ self.fMappedCtrl = CONTROL_VALUE_NONE
self.fMidiChannel = 1
self.fParameterId = pInfo['index']
self.fPluginId = pluginId
@@ -261,23 +261,21 @@ class PluginParameter(QWidget):
self.ui.label.setEnabled(False)
self.ui.widget.setEnabled(False)
self.ui.widget.setReadOnly(True)
- self.ui.sb_control.setEnabled(False)
- self.ui.sb_channel.setEnabled(False)
+ self.ui.tb_options.setEnabled(False)
elif not pHints & PARAMETER_IS_AUTOMABLE:
- self.ui.sb_control.setEnabled(False)
- self.ui.sb_channel.setEnabled(False)
+ self.ui.tb_options.setEnabled(False)
if pHints & PARAMETER_IS_READ_ONLY:
self.ui.widget.setReadOnly(True)
+ self.ui.tb_options.setEnabled(False)
elif pType == PARAMETER_OUTPUT:
self.ui.widget.setReadOnly(True)
else:
self.ui.widget.setVisible(False)
- self.ui.sb_control.setVisible(False)
- self.ui.sb_channel.setVisible(False)
+ self.ui.tb_options.setVisible(False)
# Only set value after all hints are handled
self.ui.widget.setValue(pInfo['current'])
@@ -288,16 +286,13 @@ class PluginParameter(QWidget):
self.ui.widget.setValueCallback(self._valueCallBack)
self.ui.widget.updateAll()
- self.setMidiControl(pInfo['midiCC'])
+ self.setMappedControlIndex(pInfo['mappedControlIndex'])
self.setMidiChannel(pInfo['midiChannel'])
# -------------------------------------------------------------
# Set-up connections
- self.ui.sb_control.customContextMenuRequested.connect(self.slot_controlSpinboxCustomMenu)
- self.ui.sb_channel.customContextMenuRequested.connect(self.slot_channelSpinboxCustomMenu)
- self.ui.sb_control.valueChanged.connect(self.slot_controlSpinboxChanged)
- self.ui.sb_channel.valueChanged.connect(self.slot_channelSpinboxChanged)
+ self.ui.tb_options.clicked.connect(self.slot_optionsCustomMenu)
self.ui.widget.dragStateChanged.connect(self.slot_parameterDragStateChanged)
# -------------------------------------------------------------
@@ -319,55 +314,91 @@ class PluginParameter(QWidget):
self.ui.widget.setValue(value)
self.ui.widget.blockSignals(False)
- def setMidiControl(self, control):
- self.fMidiControl = control
- self.ui.sb_control.blockSignals(True)
- self.ui.sb_control.setValue(control)
- self.ui.sb_control.blockSignals(False)
+ def setMappedControlIndex(self, control):
+ self.fMappedCtrl = control
def setMidiChannel(self, channel):
self.fMidiChannel = channel
- self.ui.sb_channel.blockSignals(True)
- self.ui.sb_channel.setValue(channel)
- self.ui.sb_channel.blockSignals(False)
def setLabelWidth(self, width):
self.ui.label.setFixedWidth(width)
@pyqtSlot()
- def slot_controlSpinboxCustomMenu(self):
+ def slot_optionsCustomMenu(self):
menu = QMenu(self)
- actNone = menu.addAction(self.tr("None"))
+ if self.fMappedCtrl == CONTROL_VALUE_NONE:
+ title = self.tr("Unmapped")
+ elif self.fMappedCtrl == CONTROL_VALUE_CV:
+ title = self.tr("Exposed as CV")
+ else:
+ title = self.tr("Mapped to CC %i, channel %i" % (self.fMappedCtrl, self.fMidiChannel))
- if self.fMidiControl == -1:
- actNone.setCheckable(True)
- actNone.setChecked(True)
+ actTitle = menu.addAction(title)
+ actTitle.setEnabled(False)
+
+ menu.addSeparator()
+
+ actUnmap = menu.addAction(self.tr("Unmap"))
+
+ if self.fMappedCtrl == CONTROL_VALUE_NONE:
+ actUnmap.setCheckable(True)
+ actUnmap.setChecked(True)
+
+ menu.addSection("CV")
+
+ actCV = menu.addAction(self.tr("Expose as CV port"))
+ if self.fMappedCtrl == CONTROL_VALUE_CV:
+ actCV.setCheckable(True)
+ actCV.setChecked(True)
+
+ menu.addSection("MIDI")
+
+ menuMIDI = menu.addMenu(self.tr("MIDI Control"))
+
+ if self.fMappedCtrl not in (CONTROL_VALUE_NONE, CONTROL_VALUE_CV, CONTROL_VALUE_MIDI_PITCHBEND):
+ action = menuMIDI.menuAction()
+ action.setCheckable(True)
+ action.setChecked(True)
+
+ inlist = False
+ actCCs = []
for cc in MIDI_CC_LIST:
- action = menu.addAction(cc)
+ action = menuMIDI.addAction(cc)
+ actCCs.append(action)
- if self.fMidiControl != -1 and int(cc.split(" ", 1)[0], 16) == self.fMidiControl:
- action.setCheckable(True)
- action.setChecked(True)
+ if self.fMappedCtrl >= 0:
+ ccx = int(cc.split(" ", 1)[0], 16)
- actSel = menu.exec_(QCursor.pos())
+ if ccx > self.fMappedCtrl and not inlist:
+ inlist = True
+ action = menuMIDI.addAction(self.tr("0x%x (Custom)" % self.fMappedCtrl))
+ action.setCheckable(True)
+ action.setChecked(True)
+ actCCs.append(action)
- if not actSel:
- pass
- elif actSel == actNone:
- self.ui.sb_control.setValue(-1)
- else:
- selControlStr = actSel.text()
- selControl = int(selControlStr.split(" ", 1)[0].replace("&",""), 16)
- self.ui.sb_control.setValue(selControl)
+ elif ccx == self.fMappedCtrl:
+ inlist = True
+ action.setCheckable(True)
+ action.setChecked(True)
- @pyqtSlot()
- def slot_channelSpinboxCustomMenu(self):
- menu = QMenu(self)
+ # TODO
+ #menuMIDI.addAction(self.tr("Custom..."))
+
+ # TODO
+ #actPitchbend = menu.addAction(self.tr("MIDI Pitchbend"))
+ #if self.fMappedCtrl == CONTROL_VALUE_MIDI_PITCHBEND:
+ #actPitchbend.setCheckable(True)
+ #actPitchbend.setChecked(True)
+
+ menuChannel = menu.addMenu(self.tr("MIDI Channel"))
+
+ actChannels = []
for i in range(1, 16+1):
- action = menu.addAction("%i" % i)
+ action = menuChannel.addAction("%i" % i)
+ actChannels.append(action)
if self.fMidiChannel == i:
action.setCheckable(True)
@@ -375,19 +406,28 @@ class PluginParameter(QWidget):
actSel = menu.exec_(QCursor.pos())
- if actSel:
- selChannel = int(actSel.text())
- self.ui.sb_channel.setValue(selChannel)
+ if not actSel:
+ return
- @pyqtSlot(int)
- def slot_controlSpinboxChanged(self, control):
- self.fMidiControl = control
- self.midiControlChanged.emit(self.fParameterId, control)
+ if actSel in actChannels:
+ channel = int(actSel.text())
+ self.fMidiChannel = channel
+ self.midiChannelChanged.emit(self.fParameterId, channel)
+ return
- @pyqtSlot(int)
- def slot_channelSpinboxChanged(self, channel):
- self.fMidiChannel = channel
- self.midiChannelChanged.emit(self.fParameterId, channel)
+ if actSel == actUnmap:
+ ctrl = CONTROL_VALUE_NONE
+ elif actSel == actCV:
+ ctrl = CONTROL_VALUE_CV
+ elif actSel in actCCs:
+ ctrl = int(actSel.text().split(" ", 1)[0].replace("&",""), 16)
+ #elif actSel in actPitchbend:
+ #ctrl = CONTROL_VALUE_MIDI_PITCHBEND
+ else:
+ return
+
+ self.fMappedCtrl = ctrl
+ self.mappedControlChanged.emit(self.fParameterId, ctrl)
@pyqtSlot(bool)
def slot_parameterDragStateChanged(self, touch):
@@ -856,7 +896,7 @@ class PluginEdit(QDialog):
'step': paramRanges['step'],
'stepSmall': paramRanges['stepSmall'],
'stepLarge': paramRanges['stepLarge'],
- 'midiCC': paramData['midiCC'],
+ 'mappedControlIndex': paramData['mappedControlIndex'],
'midiChannel': paramData['midiChannel']+1,
'comment': paramInfo['comment'],
@@ -1000,10 +1040,10 @@ class PluginEdit(QDialog):
paramWidget.setDefault(value)
break
- def setParameterMidiControl(self, parameterId, control):
+ def setParameterMappedControlIndex(self, parameterId, control):
for paramType, paramId, paramWidget in self.fParameterList:
if paramId == parameterId:
- paramWidget.setMidiControl(control)
+ paramWidget.setMappedControlIndex(control)
break
def setParameterMidiChannel(self, parameterId, channel):
@@ -1310,8 +1350,8 @@ class PluginEdit(QDialog):
self.fParent.editDialogParameterValueChanged(self.fPluginId, parameterId, value)
@pyqtSlot(int, int)
- def slot_parameterMidiControlChanged(self, parameterId, control):
- self.host.set_parameter_midi_cc(self.fPluginId, parameterId, control)
+ def slot_parameterMappedControlChanged(self, parameterId, control):
+ self.host.set_parameter_mapped_control_index(self.fPluginId, parameterId, control)
@pyqtSlot(int, int)
def slot_parameterMidiChannelChanged(self, parameterId, channel):
@@ -1514,7 +1554,7 @@ class PluginEdit(QDialog):
if paramType == PARAMETER_INPUT:
paramWidget.valueChanged.connect(self.slot_parameterValueChanged)
- paramWidget.midiControlChanged.connect(self.slot_parameterMidiControlChanged)
+ paramWidget.mappedControlChanged.connect(self.slot_parameterMappedControlChanged)
paramWidget.midiChannelChanged.connect(self.slot_parameterMidiChannelChanged)
scrollAreaLayout.addStretch()
diff --git a/source/includes/CarlaMIDI.h b/source/includes/CarlaMIDI.h
index 566892967..50b58b080 100644
--- a/source/includes/CarlaMIDI.h
+++ b/source/includes/CarlaMIDI.h
@@ -21,7 +21,7 @@
#define MAX_MIDI_CHANNELS 16
#define MAX_MIDI_NOTE 128
#define MAX_MIDI_VALUE 128
-#define MAX_MIDI_CONTROL 120 /* 0x77 */
+#define MAX_MIDI_CONTROL 120 /* 0x77 + 1 */
#define MIDI_STATUS_BIT 0xF0
#define MIDI_CHANNEL_BIT 0x0F
diff --git a/source/native-plugins/resources/carla-plugin b/source/native-plugins/resources/carla-plugin
index 4f4136d71..a6b29d026 100755
--- a/source/native-plugins/resources/carla-plugin
+++ b/source/native-plugins/resources/carla-plugin
@@ -278,7 +278,8 @@ class CarlaMiniW(ExternalUI, HostWindow):
elif msg.startswith("PARAMETER_DATA_"):
pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_DATA_", "").split(":")]
- paramType, paramHints, midiChannel, midiCC = [int(i) for i in self.readlineblock().split(":")]
+ paramType, paramHints, mappedControlIndex, midiChannel = [int(i) for i in self.readlineblock().split(":")]
+ mappedMinimum, mappedMaximum = [float(i) for i in self.readlineblock().split(":")]
paramName = self.readlineblock().replace("\r", "\n")
paramUnit = self.readlineblock().replace("\r", "\n")
paramComment = self.readlineblock().replace("\r", "\n")
@@ -299,8 +300,10 @@ class CarlaMiniW(ExternalUI, HostWindow):
'hints': paramHints,
'index': paramId,
'rindex': -1,
- 'midiCC': midiCC,
- 'midiChannel': midiChannel
+ 'midiChannel': midiChannel,
+ 'mappedControlIndex': mappedControlIndex,
+ 'mappedMinimum': mappedMinimum,
+ 'mappedMaximum': mappedMaximum,
}
self.host._set_parameterData(pluginId, paramId, paramData)
diff --git a/source/utils/CarlaBackendUtils.hpp b/source/utils/CarlaBackendUtils.hpp
index 2971be15c..9be61bb7f 100644
--- a/source/utils/CarlaBackendUtils.hpp
+++ b/source/utils/CarlaBackendUtils.hpp
@@ -232,10 +232,10 @@ const char* EngineCallbackOpcode2Str(const EngineCallbackOpcode opcode) noexcept
case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED:
return "ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED";
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
+ case ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED:
+ return "ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED";
case ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
return "ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED";
- case ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED:
- return "ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED";
case ENGINE_CALLBACK_OPTION_CHANGED:
return "ENGINE_CALLBACK_OPTION_CHANGED";
#endif
@@ -313,8 +313,6 @@ const char* EngineCallbackOpcode2Str(const EngineCallbackOpcode opcode) noexcept
return "ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_REMOVED";
case ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED:
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";
}
diff --git a/source/utils/CarlaBridgeDefines.hpp b/source/utils/CarlaBridgeDefines.hpp
index 281e484ca..b4affd899 100644
--- a/source/utils/CarlaBridgeDefines.hpp
+++ b/source/utils/CarlaBridgeDefines.hpp
@@ -48,35 +48,35 @@ enum PluginBridgeRtClientOpcode {
// Server sends these to client during non-RT
enum PluginBridgeNonRtClientOpcode {
kPluginBridgeNonRtClientNull = 0,
- kPluginBridgeNonRtClientVersion, // uint
+ kPluginBridgeNonRtClientVersion, // uint
kPluginBridgeNonRtClientPing,
- kPluginBridgeNonRtClientPingOnOff, // bool
+ kPluginBridgeNonRtClientPingOnOff, // bool
kPluginBridgeNonRtClientActivate,
kPluginBridgeNonRtClientDeactivate,
- kPluginBridgeNonRtClientInitialSetup, // uint, double
- kPluginBridgeNonRtClientSetParameterValue, // uint, float
- kPluginBridgeNonRtClientSetParameterMidiChannel, // uint, byte
- kPluginBridgeNonRtClientSetParameterMidiCC, // uint, short
- kPluginBridgeNonRtClientSetProgram, // int
- kPluginBridgeNonRtClientSetMidiProgram, // int
- kPluginBridgeNonRtClientSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[]
- kPluginBridgeNonRtClientSetChunkDataFile, // uint/size, str[] (filename, base64 content)
- kPluginBridgeNonRtClientSetCtrlChannel, // short
- kPluginBridgeNonRtClientSetOption, // uint/option, bool
- kPluginBridgeNonRtClientGetParameterText, // uint
+ kPluginBridgeNonRtClientInitialSetup, // uint, double
+ kPluginBridgeNonRtClientSetParameterValue, // uint, float
+ kPluginBridgeNonRtClientSetParameterMidiChannel, // uint, byte
+ kPluginBridgeNonRtClientSetParameterMappedControlIndex, // uint, short
+ kPluginBridgeNonRtClientSetProgram, // int
+ kPluginBridgeNonRtClientSetMidiProgram, // int
+ kPluginBridgeNonRtClientSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[]
+ kPluginBridgeNonRtClientSetChunkDataFile, // uint/size, str[] (filename, base64 content)
+ kPluginBridgeNonRtClientSetCtrlChannel, // short
+ kPluginBridgeNonRtClientSetOption, // uint/option, bool
+ kPluginBridgeNonRtClientGetParameterText, // uint
kPluginBridgeNonRtClientPrepareForSave,
kPluginBridgeNonRtClientRestoreLV2State,
kPluginBridgeNonRtClientShowUI,
kPluginBridgeNonRtClientHideUI,
- kPluginBridgeNonRtClientUiParameterChange, // uint, float
- kPluginBridgeNonRtClientUiProgramChange, // uint
- kPluginBridgeNonRtClientUiMidiProgramChange, // uint
- kPluginBridgeNonRtClientUiNoteOn, // byte, byte, byte
- kPluginBridgeNonRtClientUiNoteOff, // byte, byte
+ kPluginBridgeNonRtClientUiParameterChange, // uint, float
+ kPluginBridgeNonRtClientUiProgramChange, // uint
+ kPluginBridgeNonRtClientUiMidiProgramChange, // uint
+ kPluginBridgeNonRtClientUiNoteOn, // byte, byte, byte
+ kPluginBridgeNonRtClientUiNoteOff, // byte, byte
kPluginBridgeNonRtClientQuit,
// stuff added in API 7
- kPluginBridgeNonRtClientSetParameterMappedRange, // uint, float, float
- kPluginBridgeNonRtClientSetOptions, // uint
+ kPluginBridgeNonRtClientSetParameterMappedRange, // uint, float, float
+ kPluginBridgeNonRtClientSetOptions, // uint
};
// Client sends these to server during non-RT
diff --git a/source/utils/CarlaBridgeUtils.hpp b/source/utils/CarlaBridgeUtils.hpp
index 862e8a48d..4e9b56190 100644
--- a/source/utils/CarlaBridgeUtils.hpp
+++ b/source/utils/CarlaBridgeUtils.hpp
@@ -85,8 +85,8 @@ const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcod
return "kPluginBridgeNonRtClientSetParameterValue";
case kPluginBridgeNonRtClientSetParameterMidiChannel:
return "kPluginBridgeNonRtClientSetParameterMidiChannel";
- case kPluginBridgeNonRtClientSetParameterMidiCC:
- return "kPluginBridgeNonRtClientSetParameterMidiCC";
+ case kPluginBridgeNonRtClientSetParameterMappedControlIndex:
+ return "kPluginBridgeNonRtClientSetParameterMappedControlIndex";
case kPluginBridgeNonRtClientSetProgram:
return "kPluginBridgeNonRtClientSetProgram";
case kPluginBridgeNonRtClientSetMidiProgram:
diff --git a/source/utils/CarlaStateUtils.cpp b/source/utils/CarlaStateUtils.cpp
index c209500e3..7ecf86871 100644
--- a/source/utils/CarlaStateUtils.cpp
+++ b/source/utils/CarlaStateUtils.cpp
@@ -124,8 +124,8 @@ CarlaStateSave::Parameter::Parameter() noexcept
symbol(nullptr),
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
value(0.0f),
- midiChannel(0),
- midiCC(-1) {}
+ mappedControlIndex(CONTROL_INDEX_NONE),
+ midiChannel(0) {}
#else
value(0.0f) {}
#endif
@@ -441,8 +441,14 @@ bool CarlaStateSave::fillFromXmlElement(const XmlElement* const xmlElement)
else if (pTag == "MidiCC")
{
const int cc(pText.getIntValue());
- if (cc >= -1 && cc < MAX_MIDI_CONTROL)
- stateParameter->midiCC = static_cast(cc);
+ if (cc > 0 && cc < MAX_MIDI_CONTROL)
+ stateParameter->mappedControlIndex = static_cast(cc);
+ }
+ else if (pTag == "MappedControlIndex")
+ {
+ const int ctrl(pText.getIntValue());
+ if (ctrl > CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED)
+ stateParameter->mappedControlIndex = static_cast(ctrl);
}
#endif
}
@@ -598,10 +604,18 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const
parameterXml << " " << xmlSafeString(stateParameter->symbol, true) << "\n";
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
- if (stateParameter->midiCC > 0)
+ if (stateParameter->mappedControlIndex > CONTROL_INDEX_NONE && stateParameter->mappedControlIndex <= CONTROL_INDEX_MAX_ALLOWED)
{
- parameterXml << " " << stateParameter->midiCC << "\n";
- parameterXml << " " << stateParameter->midiChannel+1 << "\n";
+ parameterXml << " " << stateParameter->midiChannel+1 << "\n";
+ /*
+ parameterXml << " " << stateParameter->mappedMinimum << "\n";
+ parameterXml << " " << stateParameter->mappedMaximum << "\n";
+ */
+ parameterXml << " " << stateParameter->mappedControlIndex << "\n";
+
+ // backwards compatibility for older carla versions
+ if (stateParameter->mappedControlIndex > 0 && stateParameter->mappedControlIndex < MAX_MIDI_CONTROL)
+ parameterXml << " " << stateParameter->mappedControlIndex << "\n";
}
#endif
diff --git a/source/utils/CarlaStateUtils.hpp b/source/utils/CarlaStateUtils.hpp
index 65681aa44..c83f5b355 100644
--- a/source/utils/CarlaStateUtils.hpp
+++ b/source/utils/CarlaStateUtils.hpp
@@ -35,8 +35,8 @@ struct CarlaStateSave {
const char* symbol;
float value;
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
+ int16_t mappedControlIndex;
uint8_t midiChannel;
- int16_t midiCC;
#endif
Parameter() noexcept;