Browse Source

Tweak API and param widget so we can have CV expose option (WIP)

tags/v2.1-rc1
falkTX 4 years ago
parent
commit
cacad4a52f
32 changed files with 421 additions and 380 deletions
  1. +4
    -38
      resources/ui/carla_parameter.ui
  2. +41
    -19
      source/backend/CarlaBackend.h
  3. +3
    -11
      source/backend/CarlaHost.h
  4. +3
    -10
      source/backend/CarlaPlugin.hpp
  5. +10
    -18
      source/backend/CarlaStandalone.cpp
  6. +21
    -16
      source/backend/engine/CarlaEngineNative.cpp
  7. +2
    -1
      source/backend/engine/CarlaEngineOsc.hpp
  8. +24
    -7
      source/backend/engine/CarlaEngineOscHandlers.cpp
  9. +1
    -1
      source/backend/engine/CarlaEngineOscSend.cpp
  10. +46
    -54
      source/backend/plugin/CarlaPlugin.cpp
  11. +14
    -10
      source/backend/plugin/CarlaPluginBridge.cpp
  12. +8
    -4
      source/backend/plugin/CarlaPluginFluidSynth.cpp
  13. +1
    -1
      source/backend/plugin/CarlaPluginInternal.cpp
  14. +1
    -1
      source/backend/plugin/CarlaPluginJuce.cpp
  15. +4
    -4
      source/backend/plugin/CarlaPluginLADSPADSSI.cpp
  16. +4
    -4
      source/backend/plugin/CarlaPluginLV2.cpp
  17. +7
    -3
      source/backend/plugin/CarlaPluginNative.cpp
  18. +1
    -1
      source/backend/plugin/CarlaPluginSFZero.cpp
  19. +1
    -1
      source/backend/plugin/CarlaPluginVST2.cpp
  20. +60
    -66
      source/frontend/carla_backend.py
  21. +1
    -1
      source/frontend/carla_backend_qt.py
  22. +2
    -2
      source/frontend/carla_control.py
  23. +2
    -2
      source/frontend/carla_host.py
  24. +5
    -5
      source/frontend/carla_skin.py
  25. +102
    -62
      source/frontend/carla_widgets.py
  26. +1
    -1
      source/includes/CarlaMIDI.h
  27. +6
    -3
      source/native-plugins/resources/carla-plugin
  28. +2
    -4
      source/utils/CarlaBackendUtils.hpp
  29. +20
    -20
      source/utils/CarlaBridgeDefines.hpp
  30. +2
    -2
      source/utils/CarlaBridgeUtils.hpp
  31. +21
    -7
      source/utils/CarlaStateUtils.cpp
  32. +1
    -1
      source/utils/CarlaStateUtils.hpp

+ 4
- 38
resources/ui/carla_parameter.ui View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>369</width>
<height>22</height>
<height>33</height>
</rect>
</property>
<property name="windowTitle">
@@ -41,43 +41,9 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="sb_control">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="specialValueText">
<string>(none)</string>
</property>
<property name="prefix">
<string>cc #</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>119</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="sb_channel">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="prefix">
<string>ch </string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="value">
<number>1</number>
<widget class="QToolButton" name="tb_options">
<property name="text">
<string>...</string>
</property>
</widget>
</item>


+ 41
- 19
source/backend/CarlaBackend.h View File

@@ -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.
*/


+ 3
- 11
source/backend/CarlaHost.h View File

@@ -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.


+ 3
- 10
source/backend/CarlaPlugin.hpp View File

@@ -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.


+ 10
- 18
source/backend/CarlaStandalone.cpp View File

@@ -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)


+ 21
- 16
source/backend/engine/CarlaEngineNative.cpp View File

@@ -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<double>(paramData.mappedMinimum),
static_cast<double>(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<uint8_t>(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<uint8_t>(channel), true, false);
plugin->setParameterMappedControlIndex(parameterId, static_cast<int16_t>(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<int16_t>(cc), true, false);
plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false);
}
else if (std::strcmp(msg, "set_parameter_touch") == 0)
{


+ 2
- 1
source/backend/engine/CarlaEngineOsc.hpp View File

@@ -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);


+ 24
- 7
source/backend/engine/CarlaEngineOscHandlers.cpp View File

@@ -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<uint32_t>(index), static_cast<int16_t>(cc), false, true);
plugin->setParameterMappedControlIndex(static_cast<uint32_t>(index), static_cast<int16_t>(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<uint32_t>(index), minimum, maximum, false, true);
return 0;
}



+ 1
- 1
source/backend/engine/CarlaEngineOscSend.cpp View File

@@ -149,7 +149,7 @@ void CarlaEngineOsc::sendPluginParameterInfo(const CarlaPlugin* const plugin, co
try_lo_send(fControlDataTCP.target, targetPath, "iiiiiissfffffff",
static_cast<int32_t>(plugin->getId()), static_cast<int32_t>(index),
static_cast<int32_t>(paramData.type), static_cast<int32_t>(paramData.hints),
static_cast<int32_t>(paramData.midiChannel), static_cast<int32_t>(paramData.midiCC),
static_cast<int32_t>(paramData.mappedControlIndex), static_cast<int32_t>(paramData.midiChannel),
bufName, bufUnit,
static_cast<double>(paramRanges.def),
static_cast<double>(paramRanges.min),


+ 46
- 54
source/backend/plugin/CarlaPlugin.cpp View File

@@ -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<uint32_t>(index), stateParameter->midiCC, true, true);
setParameterMappedControlIndex(static_cast<uint32_t>(index), stateParameter->mappedControlIndex, true, true);
setParameterMidiChannel(static_cast<uint32_t>(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<int>(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<int>(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<int>(parameterId),
0, 0, 0.0f,


+ 14
- 10
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -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<uint16_t>(pData->param.data[k].midiCC), value);
pData->event.portOut->writeControlEvent(0,
pData->param.data[k].midiChannel,
kEngineControlEventTypeParameter,
static_cast<uint16_t>(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<int32_t>(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;



+ 8
- 4
source/backend/plugin/CarlaPluginFluidSynth.cpp View File

@@ -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<uint16_t>(pData->param.data[k].midiCC), value);
pData->event.portOut->writeControlEvent(0,
pData->param.data[k].midiChannel,
kEngineControlEventTypeParameter,
static_cast<uint16_t>(pData->param.data[k].mappedControlIndex),
value);
}

} // End of Control Output


+ 1
- 1
source/backend/plugin/CarlaPluginInternal.cpp View File

@@ -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];


+ 1
- 1
source/backend/plugin/CarlaPluginJuce.cpp View File

@@ -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;


+ 4
- 4
source/backend/plugin/CarlaPluginLADSPADSSI.cpp View File

@@ -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<uint16_t>(pData->param.data[k].midiCC);
param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
}


+ 4
- 4
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -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<int16_t>(portMidiMap.Number);
pData->param.data[j].mappedControlIndex = static_cast<int16_t>(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<uint16_t>(pData->param.data[k].midiCC);
param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
}


+ 7
- 3
source/backend/plugin/CarlaPluginNative.cpp View File

@@ -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<uint16_t>(pData->param.data[k].midiCC), value);
pData->event.portOut->writeControlEvent(0,
pData->param.data[k].midiChannel,
kEngineControlEventTypeParameter,
static_cast<uint16_t>(pData->param.data[k].mappedControlIndex),
value);
}
}
} // End of Control Output


+ 1
- 1
source/backend/plugin/CarlaPluginSFZero.cpp View File

@@ -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;


+ 1
- 1
source/backend/plugin/CarlaPluginVST2.cpp View File

@@ -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;


+ 60
- 66
source/frontend/carla_backend.py View File

@@ -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)



+ 1
- 1
source/frontend/carla_backend_qt.py View File

@@ -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)


+ 2
- 2
source/frontend/carla_control.py View File

@@ -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)


+ 2
- 2
source/frontend/carla_host.py View File

@@ -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:


+ 5
- 5
source/frontend/carla_skin.py View File

@@ -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)


+ 102
- 62
source/frontend/carla_widgets.py View File

@@ -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()


+ 1
- 1
source/includes/CarlaMIDI.h View File

@@ -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


+ 6
- 3
source/native-plugins/resources/carla-plugin View File

@@ -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)



+ 2
- 4
source/utils/CarlaBackendUtils.hpp View File

@@ -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";
}


+ 20
- 20
source/utils/CarlaBridgeDefines.hpp View File

@@ -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


+ 2
- 2
source/utils/CarlaBridgeUtils.hpp View File

@@ -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:


+ 21
- 7
source/utils/CarlaStateUtils.cpp View File

@@ -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<int16_t>(cc);
if (cc > 0 && cc < MAX_MIDI_CONTROL)
stateParameter->mappedControlIndex = static_cast<int16_t>(cc);
}
else if (pTag == "MappedControlIndex")
{
const int ctrl(pText.getIntValue());
if (ctrl > CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED)
stateParameter->mappedControlIndex = static_cast<int16_t>(ctrl);
}
#endif
}
@@ -598,10 +604,18 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const
parameterXml << " <Symbol>" << xmlSafeString(stateParameter->symbol, true) << "</Symbol>\n";

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
if (stateParameter->midiCC > 0)
if (stateParameter->mappedControlIndex > CONTROL_INDEX_NONE && stateParameter->mappedControlIndex <= CONTROL_INDEX_MAX_ALLOWED)
{
parameterXml << " <MidiCC>" << stateParameter->midiCC << "</MidiCC>\n";
parameterXml << " <MidiChannel>" << stateParameter->midiChannel+1 << "</MidiChannel>\n";
parameterXml << " <MidiChannel>" << stateParameter->midiChannel+1 << "</MidiChannel>\n";
/*
parameterXml << " <MappedMinimum>" << stateParameter->mappedMinimum << "</MappedMinimum>\n";
parameterXml << " <MappedMaximum>" << stateParameter->mappedMaximum << "</MappedMaximum>\n";
*/
parameterXml << " <MappedControlIndex>" << stateParameter->mappedControlIndex << "</MappedControlIndex>\n";

// backwards compatibility for older carla versions
if (stateParameter->mappedControlIndex > 0 && stateParameter->mappedControlIndex < MAX_MIDI_CONTROL)
parameterXml << " <MidiCC>" << stateParameter->mappedControlIndex << "</MidiCC>\n";
}
#endif



+ 1
- 1
source/utils/CarlaStateUtils.hpp View File

@@ -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;


Loading…
Cancel
Save