@@ -7,7 +7,7 @@ | |||||
<x>0</x> | <x>0</x> | ||||
<y>0</y> | <y>0</y> | ||||
<width>369</width> | <width>369</width> | ||||
<height>22</height> | |||||
<height>33</height> | |||||
</rect> | </rect> | ||||
</property> | </property> | ||||
<property name="windowTitle"> | <property name="windowTitle"> | ||||
@@ -41,43 +41,9 @@ | |||||
</widget> | </widget> | ||||
</item> | </item> | ||||
<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> | </property> | ||||
</widget> | </widget> | ||||
</item> | </item> | ||||
@@ -748,6 +748,37 @@ typedef enum { | |||||
} InternalParameterIndex; | } 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 */ | * Engine Callback Opcode */ | ||||
@@ -808,12 +839,12 @@ typedef enum { | |||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #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 pluginId Plugin Id | ||||
* @a value1 Parameter index | * @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. | * A parameter's MIDI channel has changed. | ||||
@@ -1104,21 +1135,13 @@ typedef enum { | |||||
*/ | */ | ||||
ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED = 45, | 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 parameter's mapped range has changed. | ||||
* @a pluginId Plugin Id | * @a pluginId Plugin Id | ||||
* @a value1 Parameter index | * @a value1 Parameter index | ||||
* @a valueStr New mapped range as "%f:%f" syntax | * @a valueStr New mapped range as "%f:%f" syntax | ||||
*/ | */ | ||||
ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 47, | |||||
ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED = 46, | |||||
} EngineCallbackOpcode; | } EngineCallbackOpcode; | ||||
@@ -1565,19 +1588,18 @@ typedef struct { | |||||
*/ | */ | ||||
int32_t rindex; | 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. | * Currently mapped MIDI channel. | ||||
* Counts from 0 to 15. | * Counts from 0 to 15. | ||||
*/ | */ | ||||
uint8_t midiChannel; | uint8_t midiChannel; | ||||
/*! | |||||
* Currently mapped index. | |||||
* @see SpecialMappedControlIndex | |||||
*/ | |||||
int16_t mappedControlIndex; | |||||
/*! | /*! | ||||
* Minimum value that this parameter maps to. | * Minimum value that this parameter maps to. | ||||
*/ | */ | ||||
@@ -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); | CARLA_EXPORT void carla_set_parameter_value(uint pluginId, uint32_t parameterId, float value); | ||||
#ifndef BUILD_BRIDGE | #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. | * Change a plugin's parameter MIDI channel. | ||||
* @param pluginId Plugin | * @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); | 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 pluginId Plugin | ||||
* @param parameterId Parameter index | * @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. | * Change a plugin's parameter mapped range. | ||||
@@ -592,13 +592,6 @@ public: | |||||
*/ | */ | ||||
void setParameterValueByRealIndex(int32_t rindex, float value, bool sendGui, bool sendOsc, bool sendCallback) noexcept; | 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. | * Set parameter's @a parameterId MIDI channel to @a channel. | ||||
* @a channel must be between 0 and 15. | * @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; | 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. | * Set parameter's @a parameterId mapped range to @a minimum and @a maximum. | ||||
@@ -1443,8 +1443,10 @@ const ParameterData* carla_get_parameter_data(uint pluginId, uint32_t parameterI | |||||
retParamData.hints = 0x0; | retParamData.hints = 0x0; | ||||
retParamData.index = CB::PARAMETER_NULL; | retParamData.index = CB::PARAMETER_NULL; | ||||
retParamData.rindex = -1; | retParamData.rindex = -1; | ||||
retParamData.midiCC = -1; | |||||
retParamData.midiChannel = 0; | 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); | 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.hints = pluginParamData.hints; | ||||
retParamData.index = pluginParamData.index; | retParamData.index = pluginParamData.index; | ||||
retParamData.rindex = pluginParamData.rindex; | retParamData.rindex = pluginParamData.rindex; | ||||
retParamData.midiCC = pluginParamData.midiCC; | |||||
retParamData.midiChannel = pluginParamData.midiChannel; | retParamData.midiChannel = pluginParamData.midiChannel; | ||||
retParamData.mappedControlIndex = pluginParamData.mappedControlIndex; | |||||
retParamData.mappedMinimum = pluginParamData.mappedMinimum; | |||||
retParamData.mappedMaximum = pluginParamData.mappedMaximum; | |||||
return &plugin->getParameterData(parameterId); | return &plugin->getParameterData(parameterId); | ||||
} | } | ||||
@@ -1984,18 +1988,6 @@ void carla_set_parameter_value(uint pluginId, uint32_t parameterId, float value) | |||||
} | } | ||||
#ifndef BUILD_BRIDGE | #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) | 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); | 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(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)); | CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); | ||||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); | 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(),); | 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) | void carla_set_parameter_mapped_range(uint pluginId, uint32_t parameterId, float minimum, float maximum) | ||||
@@ -559,7 +559,11 @@ protected: | |||||
CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); | CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); | ||||
std::snprintf(tmpBuf, STR_MAX, "%i:%i:%i:%i\n", paramData.type, paramData.hints, | 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),); | CARLA_SAFE_ASSERT_RETURN(fUiServer.writeMessage(tmpBuf),); | ||||
if (plugin->getParameterName(i, tmpBuf)) { | if (plugin->getParameterName(i, tmpBuf)) { | ||||
@@ -2074,42 +2078,43 @@ bool CarlaEngineNativeUI::msgReceived(const char*const msg) noexcept | |||||
fEngine->setParameterValueFromUI(pluginId, parameterId, value); | 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(pluginId), true); | ||||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), 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)) | 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(pluginId), true); | ||||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), 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)) | 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; | uint32_t pluginId, parameterId; | ||||
int32_t cc; | |||||
float minimum, maximum; | |||||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); | CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(pluginId), true); | ||||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(parameterId), 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)) | 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) | else if (std::strcmp(msg, "set_parameter_touch") == 0) | ||||
{ | { | ||||
@@ -149,7 +149,8 @@ private: | |||||
int handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS); | int handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS); | ||||
int handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS); | int handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS); | ||||
int handleMsgSetParameterValue(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 handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS); | ||||
int handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); | int handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); | ||||
int handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); | int handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); | ||||
@@ -160,8 +160,10 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||||
return 0; //handleMsgSetControlChannel(plugin, argc, argv, types); // TODO | return 0; //handleMsgSetControlChannel(plugin, argc, argv, types); // TODO | ||||
if (std::strcmp(method, "set_parameter_value") == 0) | if (std::strcmp(method, "set_parameter_value") == 0) | ||||
return handleMsgSetParameterValue(plugin, argc, argv, types); | 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) | if (std::strcmp(method, "set_parameter_midi_channel") == 0) | ||||
return handleMsgSetParameterMidiChannel(plugin, argc, argv, types); | return handleMsgSetParameterMidiChannel(plugin, argc, argv, types); | ||||
if (std::strcmp(method, "set_program") == 0) | if (std::strcmp(method, "set_program") == 0) | ||||
@@ -630,18 +632,33 @@ int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
return 0; | 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"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | ||||
const int32_t index = argv[0]->i; | 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(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; | return 0; | ||||
} | } | ||||
@@ -149,7 +149,7 @@ void CarlaEngineOsc::sendPluginParameterInfo(const CarlaPlugin* const plugin, co | |||||
try_lo_send(fControlDataTCP.target, targetPath, "iiiiiissfffffff", | try_lo_send(fControlDataTCP.target, targetPath, "iiiiiissfffffff", | ||||
static_cast<int32_t>(plugin->getId()), static_cast<int32_t>(index), | 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.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, | bufName, bufUnit, | ||||
static_cast<double>(paramRanges.def), | static_cast<double>(paramRanges.def), | ||||
static_cast<double>(paramRanges.min), | static_cast<double>(paramRanges.min), | ||||
@@ -45,7 +45,7 @@ CARLA_BACKEND_START_NAMESPACE | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
// Fallback data | // 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 ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0.0001f, 0.1f }; | ||||
static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; | 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; | const bool dummy = paramData.type != PARAMETER_INPUT || usingChunk; | ||||
if (dummy && paramData.midiCC <= -1) | |||||
if (dummy && paramData.mappedControlIndex <= CONTROL_INDEX_NONE) | |||||
continue; | continue; | ||||
CarlaStateSave::Parameter* const stateParameter(new CarlaStateSave::Parameter()); | CarlaStateSave::Parameter* const stateParameter(new CarlaStateSave::Parameter()); | ||||
@@ -608,8 +608,8 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave) | |||||
stateParameter->dummy = dummy; | stateParameter->dummy = dummy; | ||||
stateParameter->index = paramData.index; | stateParameter->index = paramData.index; | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
stateParameter->midiCC = paramData.midiCC; | |||||
stateParameter->midiChannel = paramData.midiChannel; | |||||
stateParameter->mappedControlIndex = paramData.mappedControlIndex; | |||||
stateParameter->midiChannel = paramData.midiChannel; | |||||
#endif | #endif | ||||
if (! getParameterName(i, strBuf)) | if (! getParameterName(i, strBuf)) | ||||
@@ -821,7 +821,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||||
} | } | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #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); | setParameterMidiChannel(static_cast<uint32_t>(index), stateParameter->midiChannel, true, true); | ||||
#endif | #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 | void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept | ||||
{ | { | ||||
if (pData->engineBridged) { | 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(parameterId < pData->param.count,); | ||||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | ||||
if (pData->param.data[parameterId].midiChannel == channel) | |||||
return; | |||||
pData->param.data[parameterId].midiChannel = channel; | pData->param.data[parameterId].midiChannel = channel; | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
@@ -1735,7 +1695,7 @@ void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint | |||||
#endif | #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) { | if (pData->engineBridged) { | ||||
CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,); | 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(sendOsc || sendCallback,); // never call this from RT | ||||
} | } | ||||
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); | 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 | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
pData->engine->callback(sendCallback, sendOsc, | pData->engine->callback(sendCallback, sendOsc, | ||||
ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED, | |||||
ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED, | |||||
pData->id, | pData->id, | ||||
static_cast<int>(parameterId), | static_cast<int>(parameterId), | ||||
cc, | |||||
index, | |||||
0, 0.0f, nullptr); | 0, 0.0f, nullptr); | ||||
#endif | #endif | ||||
} | } | ||||
@@ -1766,6 +1754,10 @@ void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const floa | |||||
} | } | ||||
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); | 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].mappedMinimum = minimum; | ||||
pData->param.data[parameterId].mappedMaximum = maximum; | pData->param.data[parameterId].mappedMaximum = maximum; | ||||
@@ -1775,7 +1767,7 @@ void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const floa | |||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
pData->engine->callback(sendCallback, sendOsc, | pData->engine->callback(sendCallback, sendOsc, | ||||
ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED, | |||||
ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED, | |||||
pData->id, | pData->id, | ||||
static_cast<int>(parameterId), | static_cast<int>(parameterId), | ||||
0, 0, 0.0f, | 0, 0, 0.0f, | ||||
@@ -749,22 +749,22 @@ public: | |||||
CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback); | 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(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,); | CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); | ||||
{ | { | ||||
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); | ||||
fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiCC); | |||||
fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedControlIndex); | |||||
fShmNonRtClientControl.writeUInt(parameterId); | fShmNonRtClientControl.writeUInt(parameterId); | ||||
fShmNonRtClientControl.writeShort(cc); | |||||
fShmNonRtClientControl.writeShort(index); | |||||
fShmNonRtClientControl.commitWrite(); | 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 | 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) | if (pData->param.data[k].type != PARAMETER_OUTPUT) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC > 0) | |||||
if (pData->param.data[k].mappedControlIndex > 0) | |||||
{ | { | ||||
value = pData->param.ranges[k].getNormalizedValue(fParams[k].value); | 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 int32_t rindex = fShmNonRtServerControl.readInt(); | ||||
const uint32_t type = fShmNonRtServerControl.readUInt(); | const uint32_t type = fShmNonRtServerControl.readUInt(); | ||||
const uint32_t hints = 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); | CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count); | ||||
if (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].index = static_cast<int32_t>(index); | ||||
pData->param.data[index].rindex = rindex; | pData->param.data[index].rindex = rindex; | ||||
pData->param.data[index].hints = hints; | pData->param.data[index].hints = hints; | ||||
pData->param.data[index].midiCC = midiCC; | |||||
pData->param.data[index].mappedControlIndex = ctrl; | |||||
} | } | ||||
} break; | } break; | ||||
@@ -777,7 +777,7 @@ public: | |||||
pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/; | pData->param.data[j].hints = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/; | ||||
pData->param.data[j].index = j; | pData->param.data[j].index = j; | ||||
pData->param.data[j].rindex = 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].min = 0.0f; | ||||
pData->param.ranges[j].max = 1.0f; | pData->param.ranges[j].max = 1.0f; | ||||
pData->param.ranges[j].def = sFluidDefaults[j]; | pData->param.ranges[j].def = sFluidDefaults[j]; | ||||
@@ -1239,7 +1239,7 @@ public: | |||||
{ | { | ||||
if (pData->param.data[k].midiChannel != event.channel) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].hints != PARAMETER_INPUT) | if (pData->param.data[k].hints != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -1427,10 +1427,14 @@ public: | |||||
fParamBuffers[k] = float(fluid_synth_get_active_voice_count(fSynth)); | fParamBuffers[k] = float(fluid_synth_get_active_voice_count(fSynth)); | ||||
pData->param.ranges[k].fixValue(fParamBuffers[k]); | 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])); | 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 | } // End of Control Output | ||||
@@ -222,7 +222,7 @@ void PluginParameterData::createNew(const uint32_t newCount, const bool withSpec | |||||
{ | { | ||||
data[i].index = PARAMETER_NULL; | data[i].index = PARAMETER_NULL; | ||||
data[i].rindex = PARAMETER_NULL; | data[i].rindex = PARAMETER_NULL; | ||||
data[i].midiCC = -1; | |||||
data[i].mappedControlIndex = CONTROL_INDEX_NONE; | |||||
} | } | ||||
ranges = new ParameterRanges[newCount]; | ranges = new ParameterRanges[newCount]; | ||||
@@ -881,7 +881,7 @@ public: | |||||
{ | { | ||||
if (pData->param.data[k].midiChannel != event.channel) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].type != PARAMETER_INPUT) | if (pData->param.data[k].type != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -1132,7 +1132,7 @@ public: | |||||
{ | { | ||||
const int16_t cc = DSSI_CC_NUMBER(ctrl); | const int16_t cc = DSSI_CC_NUMBER(ctrl); | ||||
if (! MIDI_IS_CONTROL_BANK_SELECT(cc)) | 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) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].type != PARAMETER_INPUT) | if (pData->param.data[k].type != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -1943,10 +1943,10 @@ public: | |||||
pData->param.ranges[k].fixValue(fParamBuffers[k]); | 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; | 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]); | value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]); | ||||
pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value); | pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value); | ||||
} | } | ||||
@@ -2574,7 +2574,7 @@ public: | |||||
if (LV2_IS_PORT_MIDI_MAP_CC(portMidiMap.Type)) | if (LV2_IS_PORT_MIDI_MAP_CC(portMidiMap.Type)) | ||||
{ | { | ||||
if (portMidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(portMidiMap.Number)) | 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)) | else if (LV2_IS_PORT_OUTPUT(portTypes)) | ||||
@@ -3678,7 +3678,7 @@ public: | |||||
{ | { | ||||
if (pData->param.data[k].midiChannel != event.channel) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].type != PARAMETER_INPUT) | if (pData->param.data[k].type != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -4039,10 +4039,10 @@ public: | |||||
// plugin is responsible to ensure correct bounds | // plugin is responsible to ensure correct bounds | ||||
pData->param.ranges[k].fixValue(fParamBuffers[k]); | 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; | 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]); | value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]); | ||||
pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value); | pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value); | ||||
} | } | ||||
@@ -1941,7 +1941,7 @@ public: | |||||
{ | { | ||||
if (pData->param.data[k].midiChannel != event.channel) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].type != PARAMETER_INPUT) | if (pData->param.data[k].type != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -2191,10 +2191,14 @@ public: | |||||
curValue = fDescriptor->get_parameter_value(fHandle, k); | curValue = fDescriptor->get_parameter_value(fHandle, k); | ||||
pData->param.ranges[k].fixValue(curValue); | 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); | 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 | } // End of Control Output | ||||
@@ -457,7 +457,7 @@ public: | |||||
{ | { | ||||
if (pData->param.data[k].midiChannel != event.channel) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].hints != PARAMETER_INPUT) | if (pData->param.data[k].hints != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -1389,7 +1389,7 @@ public: | |||||
{ | { | ||||
if (pData->param.data[k].midiChannel != event.channel) | if (pData->param.data[k].midiChannel != event.channel) | ||||
continue; | continue; | ||||
if (pData->param.data[k].midiCC != ctrlEvent.param) | |||||
if (pData->param.data[k].mappedControlIndex != ctrlEvent.param) | |||||
continue; | continue; | ||||
if (pData->param.data[k].type != PARAMETER_INPUT) | if (pData->param.data[k].type != PARAMETER_INPUT) | ||||
continue; | continue; | ||||
@@ -539,6 +539,22 @@ PARAMETER_CTRL_CHANNEL = -8 | |||||
# Max value, defined only for convenience. | # Max value, defined only for convenience. | ||||
PARAMETER_MAX = -9 | 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 Opcode | ||||
# Engine callback opcodes. | # Engine callback opcodes. | ||||
@@ -580,11 +596,11 @@ ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED = 5 | |||||
# @a valuef New default value | # @a valuef New default value | ||||
ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED = 6 | 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 pluginId Plugin Id | ||||
# @a value1 Parameter index | # @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 parameter's MIDI channel has changed. | ||||
# @a pluginId Plugin Id | # @a pluginId Plugin Id | ||||
@@ -796,17 +812,11 @@ ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_REMOVED = 44 | |||||
# @see PatchbayPortGroupHints | # @see PatchbayPortGroupHints | ||||
ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED = 45 | 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 parameter's mapped range has changed. | ||||
# @a pluginId Plugin Id | # @a pluginId Plugin Id | ||||
# @a value1 Parameter index | # @a value1 Parameter index | ||||
# @a valueStr New mapped range as "%f:%f" syntax | # @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 | # NSM Callback Opcode | ||||
@@ -1089,15 +1099,14 @@ class ParameterData(Structure): | |||||
# Real index as seen by plugins. | # Real index as seen by plugins. | ||||
("rindex", c_int32), | ("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. | # Currently mapped MIDI channel. | ||||
# Counts from 0 to 15. | # Counts from 0 to 15. | ||||
("midiChannel", c_uint8), | ("midiChannel", c_uint8), | ||||
# Currently mapped index. | |||||
# @see SpecialMappedControlIndex | |||||
("mappedControlIndex", c_int16), | |||||
# Minimum value that this parameter maps to. | # Minimum value that this parameter maps to. | ||||
("mappedMinimum", c_uint8), | ("mappedMinimum", c_uint8), | ||||
@@ -1180,8 +1189,8 @@ PyParameterData = { | |||||
'hints': 0x0, | 'hints': 0x0, | ||||
'index': PARAMETER_NULL, | 'index': PARAMETER_NULL, | ||||
'rindex': -1, | 'rindex': -1, | ||||
'midiCC': -1, | |||||
'midiChannel': 0, | 'midiChannel': 0, | ||||
'mappedControlIndex': CONTROL_VALUE_NONE, | |||||
'mappedMinimum': 0.0, | 'mappedMinimum': 0.0, | ||||
'mappedMaximum': 1.0, | 'mappedMaximum': 1.0, | ||||
} | } | ||||
@@ -2050,15 +2059,7 @@ class CarlaHostMeta(object): | |||||
def set_parameter_value(self, pluginId, parameterId, value): | def set_parameter_value(self, pluginId, parameterId, value): | ||||
raise NotImplementedError | 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 pluginId Plugin | ||||
# @param parameterId Parameter index | # @param parameterId Parameter index | ||||
# @param cc New MIDI cc | # @param cc New MIDI cc | ||||
@@ -2069,9 +2070,9 @@ class CarlaHostMeta(object): | |||||
# Change a plugin's parameter MIDI channel. | # Change a plugin's parameter MIDI channel. | ||||
# @param pluginId Plugin | # @param pluginId Plugin | ||||
# @param parameterId Parameter index | # @param parameterId Parameter index | ||||
# @param channel New MIDI channel | |||||
# @param channel New control index | |||||
@abstractmethod | @abstractmethod | ||||
def set_parameter_midi_cc(self, pluginId, parameterId, cc): | |||||
def set_parameter_mapped_control_index(self, pluginId, parameterId, index): | |||||
raise NotImplementedError | raise NotImplementedError | ||||
# Change a plugin's parameter mapped range. | # Change a plugin's parameter mapped range. | ||||
@@ -2464,13 +2465,10 @@ class CarlaHostNull(CarlaHostMeta): | |||||
def set_parameter_value(self, pluginId, parameterId, value): | def set_parameter_value(self, pluginId, parameterId, value): | ||||
return | return | ||||
def set_parameter_cv_controlled(self, pluginId, parameterId, cv_controlled): | |||||
return | |||||
def set_parameter_midi_channel(self, pluginId, parameterId, channel): | def set_parameter_midi_channel(self, pluginId, parameterId, channel): | ||||
return | return | ||||
def set_parameter_midi_cc(self, pluginId, parameterId, cc): | |||||
def set_parameter_mapped_control_index(self, pluginId, parameterId, index): | |||||
return | return | ||||
def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum): | 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.argtypes = [c_uint, c_uint32, c_float] | ||||
self.lib.carla_set_parameter_value.restype = None | 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.argtypes = [c_uint, c_uint32, c_uint8] | ||||
self.lib.carla_set_parameter_midi_channel.restype = None | 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.argtypes = [c_uint, c_uint32, c_float, c_float] | ||||
self.lib.carla_set_parameter_mapped_range.restype = None | self.lib.carla_set_parameter_mapped_range.restype = None | ||||
@@ -3107,14 +3102,11 @@ class CarlaHostDLL(CarlaHostMeta): | |||||
def set_parameter_value(self, pluginId, parameterId, value): | def set_parameter_value(self, pluginId, parameterId, value): | ||||
self.lib.carla_set_parameter_value(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): | def set_parameter_midi_channel(self, pluginId, parameterId, channel): | ||||
self.lib.carla_set_parameter_midi_channel(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): | def set_parameter_mapped_range(self, pluginId, parameterId, minimum, maximum): | ||||
self.lib.carla_set_parameter_mapped_range(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.sendMsg(["set_parameter_value", pluginId, parameterId, value]) | ||||
self.fPluginsInfo[pluginId].parameterValues[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): | def set_parameter_midi_channel(self, pluginId, parameterId, channel): | ||||
self.sendMsg(["set_parameter_midi_channel", 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): | def set_parameter_touch(self, pluginId, parameterId, touch): | ||||
self.sendMsg(["set_parameter_touch", pluginId, parameterId, touch]) | self.sendMsg(["set_parameter_touch", pluginId, parameterId, touch]) | ||||
@@ -3768,36 +3762,36 @@ class CarlaHostPlugin(CarlaHostMeta): | |||||
else: | else: | ||||
print("_set_parameterDefault failed for", pluginId, "and index", paramIndex) | 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) | plugin = self.fPluginsInfo.get(pluginId, None) | ||||
if plugin is None: | if plugin is None: | ||||
print("_set_parameterMidiChannel failed for", pluginId) | |||||
print("_set_parameterMappedControlIndex failed for", pluginId) | |||||
return | return | ||||
if paramIndex < plugin.parameterCount: | if paramIndex < plugin.parameterCount: | ||||
plugin.parameterData[paramIndex]['midiChannel'] = channel | |||||
plugin.parameterData[paramIndex]['mappedControlIndex'] = index | |||||
else: | 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) | plugin = self.fPluginsInfo.get(pluginId, None) | ||||
if plugin is None: | if plugin is None: | ||||
print("_set_parameterMidiCC failed for", pluginId) | |||||
print("_set_parameterMappedRange failed for", pluginId) | |||||
return | return | ||||
if paramIndex < plugin.parameterCount: | if paramIndex < plugin.parameterCount: | ||||
plugin.parameterData[paramIndex]['midiCC'] = cc | |||||
plugin.parameterData[paramIndex]['mappedMinimum'] = minimum | |||||
plugin.parameterData[paramIndex]['mappedMaximum'] = maximum | |||||
else: | 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) | plugin = self.fPluginsInfo.get(pluginId, None) | ||||
if plugin is None: | if plugin is None: | ||||
print("_set_parameterMappedRange failed for", pluginId) | |||||
print("_set_parameterMidiChannel failed for", pluginId) | |||||
return | return | ||||
if paramIndex < plugin.parameterCount: | if paramIndex < plugin.parameterCount: | ||||
plugin.parameterData[paramIndex]['mappedMinimum'] = minimum | |||||
plugin.parameterData[paramIndex]['mappedMaximum'] = maximum | |||||
plugin.parameterData[paramIndex]['midiChannel'] = channel | |||||
else: | 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): | def _set_currentProgram(self, pluginId, pIndex): | ||||
plugin = self.fPluginsInfo.get(pluginId, None) | plugin = self.fPluginsInfo.get(pluginId, None) | ||||
@@ -3877,16 +3871,16 @@ class CarlaHostPlugin(CarlaHostMeta): | |||||
elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | ||||
self._set_parameterDefault(pluginId, value1, valuef) | 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: | elif action == ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED: | ||||
minimum, maximum = (float(i) for i in valueStr.split(":")) | minimum, maximum = (float(i) for i in valueStr.split(":")) | ||||
self._set_parameterMappedRange(pluginId, value1, minimum, maximum) | 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: | elif action == ENGINE_CALLBACK_PROGRAM_CHANGED: | ||||
self._set_currentProgram(pluginId, value1) | self._set_currentProgram(pluginId, value1) | ||||
@@ -38,7 +38,7 @@ class CarlaHostSignals(QObject): | |||||
PluginUnavailableCallback = pyqtSignal(int, str) | PluginUnavailableCallback = pyqtSignal(int, str) | ||||
ParameterValueChangedCallback = pyqtSignal(int, int, float) | ParameterValueChangedCallback = pyqtSignal(int, int, float) | ||||
ParameterDefaultChangedCallback = pyqtSignal(int, int, float) | ParameterDefaultChangedCallback = pyqtSignal(int, int, float) | ||||
ParameterMidiCcChangedCallback = pyqtSignal(int, int, int) | |||||
ParameterMappedControlIndexChangedCallback = pyqtSignal(int, int, int) | |||||
ParameterMidiChannelChangedCallback = pyqtSignal(int, int, int) | ParameterMidiChannelChangedCallback = pyqtSignal(int, int, int) | ||||
ProgramChangedCallback = pyqtSignal(int, int) | ProgramChangedCallback = pyqtSignal(int, int) | ||||
MidiProgramChangedCallback = pyqtSignal(int, int) | MidiProgramChangedCallback = pyqtSignal(int, int) | ||||
@@ -381,7 +381,7 @@ class CarlaControlServerTCP(Server): | |||||
if DEBUG: print(path, args) | if DEBUG: print(path, args) | ||||
self.fReceivedMsgs = True | 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 | def_, min_, max_, step, stepSmall, stepLarge, value | ||||
) = args | ) = args | ||||
@@ -400,7 +400,7 @@ class CarlaControlServerTCP(Server): | |||||
'hints': hints, | 'hints': hints, | ||||
'index': paramId, | 'index': paramId, | ||||
'rindex': -1, | 'rindex': -1, | ||||
'midiCC': midiCC, | |||||
'mappedControlIndex': mappedControlIndex, | |||||
'midiChannel': midiChan, | 'midiChannel': midiChan, | ||||
} | } | ||||
self.host._set_parameterData(pluginId, paramId, paramData) | self.host._set_parameterData(pluginId, paramId, paramData) | ||||
@@ -2749,8 +2749,8 @@ def engineCallback(host, action, pluginId, value1, value2, value3, valuef, value | |||||
host.ParameterValueChangedCallback.emit(pluginId, value1, valuef) | host.ParameterValueChangedCallback.emit(pluginId, value1, valuef) | ||||
elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | elif action == ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | ||||
host.ParameterDefaultChangedCallback.emit(pluginId, value1, valuef) | 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: | elif action == ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED: | ||||
host.ParameterMidiChannelChangedCallback.emit(pluginId, value1, value2) | host.ParameterMidiChannelChangedCallback.emit(pluginId, value1, value2) | ||||
elif action == ENGINE_CALLBACK_PROGRAM_CHANGED: | elif action == ENGINE_CALLBACK_PROGRAM_CHANGED: | ||||
@@ -286,8 +286,8 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta): | |||||
host.PluginUnavailableCallback.connect(self.slot_handlePluginUnavailableCallback) | host.PluginUnavailableCallback.connect(self.slot_handlePluginUnavailableCallback) | ||||
host.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback) | host.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback) | ||||
host.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback) | host.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback) | ||||
host.ParameterMappedControlIndexChangedCallback.connect(self.slot_handleParameterMappedControlIndexChangedCallback) | |||||
host.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback) | host.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback) | ||||
host.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback) | |||||
host.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback) | host.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback) | ||||
host.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback) | host.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback) | ||||
host.OptionChangedCallback.connect(self.slot_handleOptionChangedCallback) | host.OptionChangedCallback.connect(self.slot_handleOptionChangedCallback) | ||||
@@ -322,9 +322,9 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta): | |||||
self.setParameterDefault(index, value) | self.setParameterDefault(index, value) | ||||
@pyqtSlot(int, int, int) | @pyqtSlot(int, int, int) | ||||
def slot_handleParameterMidiCcChangedCallback(self, pluginId, index, cc): | |||||
def slot_handleParameterMappedControlIndexChangedCallback(self, pluginId, index, ctrl): | |||||
if self.fPluginId == pluginId: | if self.fPluginId == pluginId: | ||||
self.setParameterMidiControl(index, cc) | |||||
self.setParameterMappedControlIndex(index, ctrl) | |||||
@pyqtSlot(int, int, int) | @pyqtSlot(int, int, int) | ||||
def slot_handleParameterMidiChannelChangedCallback(self, pluginId, index, channel): | def slot_handleParameterMidiChannelChangedCallback(self, pluginId, index, channel): | ||||
@@ -738,8 +738,8 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta): | |||||
def setParameterDefault(self, parameterId, value): | def setParameterDefault(self, parameterId, value): | ||||
self.fEditDialog.setParameterDefault(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): | def setParameterMidiChannel(self, parameterId, channel): | ||||
self.fEditDialog.setParameterMidiChannel(parameterId, channel) | self.fEditDialog.setParameterMidiChannel(parameterId, channel) | ||||
@@ -211,9 +211,9 @@ class JuceAboutW(QDialog): | |||||
# Plugin Parameter | # Plugin Parameter | ||||
class PluginParameter(QWidget): | 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): | def __init__(self, parent, host, pInfo, pluginId, tabIndex): | ||||
QWidget.__init__(self, parent) | QWidget.__init__(self, parent) | ||||
@@ -229,7 +229,7 @@ class PluginParameter(QWidget): | |||||
# ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
# Internal stuff | # Internal stuff | ||||
self.fMidiControl = -1 | |||||
self.fMappedCtrl = CONTROL_VALUE_NONE | |||||
self.fMidiChannel = 1 | self.fMidiChannel = 1 | ||||
self.fParameterId = pInfo['index'] | self.fParameterId = pInfo['index'] | ||||
self.fPluginId = pluginId | self.fPluginId = pluginId | ||||
@@ -261,23 +261,21 @@ class PluginParameter(QWidget): | |||||
self.ui.label.setEnabled(False) | self.ui.label.setEnabled(False) | ||||
self.ui.widget.setEnabled(False) | self.ui.widget.setEnabled(False) | ||||
self.ui.widget.setReadOnly(True) | 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: | 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: | if pHints & PARAMETER_IS_READ_ONLY: | ||||
self.ui.widget.setReadOnly(True) | self.ui.widget.setReadOnly(True) | ||||
self.ui.tb_options.setEnabled(False) | |||||
elif pType == PARAMETER_OUTPUT: | elif pType == PARAMETER_OUTPUT: | ||||
self.ui.widget.setReadOnly(True) | self.ui.widget.setReadOnly(True) | ||||
else: | else: | ||||
self.ui.widget.setVisible(False) | 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 | # Only set value after all hints are handled | ||||
self.ui.widget.setValue(pInfo['current']) | self.ui.widget.setValue(pInfo['current']) | ||||
@@ -288,16 +286,13 @@ class PluginParameter(QWidget): | |||||
self.ui.widget.setValueCallback(self._valueCallBack) | self.ui.widget.setValueCallback(self._valueCallBack) | ||||
self.ui.widget.updateAll() | self.ui.widget.updateAll() | ||||
self.setMidiControl(pInfo['midiCC']) | |||||
self.setMappedControlIndex(pInfo['mappedControlIndex']) | |||||
self.setMidiChannel(pInfo['midiChannel']) | self.setMidiChannel(pInfo['midiChannel']) | ||||
# ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
# Set-up connections | # 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) | self.ui.widget.dragStateChanged.connect(self.slot_parameterDragStateChanged) | ||||
# ------------------------------------------------------------- | # ------------------------------------------------------------- | ||||
@@ -319,55 +314,91 @@ class PluginParameter(QWidget): | |||||
self.ui.widget.setValue(value) | self.ui.widget.setValue(value) | ||||
self.ui.widget.blockSignals(False) | 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): | def setMidiChannel(self, channel): | ||||
self.fMidiChannel = 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): | def setLabelWidth(self, width): | ||||
self.ui.label.setFixedWidth(width) | self.ui.label.setFixedWidth(width) | ||||
@pyqtSlot() | @pyqtSlot() | ||||
def slot_controlSpinboxCustomMenu(self): | |||||
def slot_optionsCustomMenu(self): | |||||
menu = QMenu(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: | 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): | for i in range(1, 16+1): | ||||
action = menu.addAction("%i" % i) | |||||
action = menuChannel.addAction("%i" % i) | |||||
actChannels.append(action) | |||||
if self.fMidiChannel == i: | if self.fMidiChannel == i: | ||||
action.setCheckable(True) | action.setCheckable(True) | ||||
@@ -375,19 +406,28 @@ class PluginParameter(QWidget): | |||||
actSel = menu.exec_(QCursor.pos()) | 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) | @pyqtSlot(bool) | ||||
def slot_parameterDragStateChanged(self, touch): | def slot_parameterDragStateChanged(self, touch): | ||||
@@ -856,7 +896,7 @@ class PluginEdit(QDialog): | |||||
'step': paramRanges['step'], | 'step': paramRanges['step'], | ||||
'stepSmall': paramRanges['stepSmall'], | 'stepSmall': paramRanges['stepSmall'], | ||||
'stepLarge': paramRanges['stepLarge'], | 'stepLarge': paramRanges['stepLarge'], | ||||
'midiCC': paramData['midiCC'], | |||||
'mappedControlIndex': paramData['mappedControlIndex'], | |||||
'midiChannel': paramData['midiChannel']+1, | 'midiChannel': paramData['midiChannel']+1, | ||||
'comment': paramInfo['comment'], | 'comment': paramInfo['comment'], | ||||
@@ -1000,10 +1040,10 @@ class PluginEdit(QDialog): | |||||
paramWidget.setDefault(value) | paramWidget.setDefault(value) | ||||
break | break | ||||
def setParameterMidiControl(self, parameterId, control): | |||||
def setParameterMappedControlIndex(self, parameterId, control): | |||||
for paramType, paramId, paramWidget in self.fParameterList: | for paramType, paramId, paramWidget in self.fParameterList: | ||||
if paramId == parameterId: | if paramId == parameterId: | ||||
paramWidget.setMidiControl(control) | |||||
paramWidget.setMappedControlIndex(control) | |||||
break | break | ||||
def setParameterMidiChannel(self, parameterId, channel): | def setParameterMidiChannel(self, parameterId, channel): | ||||
@@ -1310,8 +1350,8 @@ class PluginEdit(QDialog): | |||||
self.fParent.editDialogParameterValueChanged(self.fPluginId, parameterId, value) | self.fParent.editDialogParameterValueChanged(self.fPluginId, parameterId, value) | ||||
@pyqtSlot(int, int) | @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) | @pyqtSlot(int, int) | ||||
def slot_parameterMidiChannelChanged(self, parameterId, channel): | def slot_parameterMidiChannelChanged(self, parameterId, channel): | ||||
@@ -1514,7 +1554,7 @@ class PluginEdit(QDialog): | |||||
if paramType == PARAMETER_INPUT: | if paramType == PARAMETER_INPUT: | ||||
paramWidget.valueChanged.connect(self.slot_parameterValueChanged) | paramWidget.valueChanged.connect(self.slot_parameterValueChanged) | ||||
paramWidget.midiControlChanged.connect(self.slot_parameterMidiControlChanged) | |||||
paramWidget.mappedControlChanged.connect(self.slot_parameterMappedControlChanged) | |||||
paramWidget.midiChannelChanged.connect(self.slot_parameterMidiChannelChanged) | paramWidget.midiChannelChanged.connect(self.slot_parameterMidiChannelChanged) | ||||
scrollAreaLayout.addStretch() | scrollAreaLayout.addStretch() | ||||
@@ -21,7 +21,7 @@ | |||||
#define MAX_MIDI_CHANNELS 16 | #define MAX_MIDI_CHANNELS 16 | ||||
#define MAX_MIDI_NOTE 128 | #define MAX_MIDI_NOTE 128 | ||||
#define MAX_MIDI_VALUE 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_STATUS_BIT 0xF0 | ||||
#define MIDI_CHANNEL_BIT 0x0F | #define MIDI_CHANNEL_BIT 0x0F | ||||
@@ -278,7 +278,8 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
elif msg.startswith("PARAMETER_DATA_"): | elif msg.startswith("PARAMETER_DATA_"): | ||||
pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_DATA_", "").split(":")] | 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") | paramName = self.readlineblock().replace("\r", "\n") | ||||
paramUnit = self.readlineblock().replace("\r", "\n") | paramUnit = self.readlineblock().replace("\r", "\n") | ||||
paramComment = self.readlineblock().replace("\r", "\n") | paramComment = self.readlineblock().replace("\r", "\n") | ||||
@@ -299,8 +300,10 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||||
'hints': paramHints, | 'hints': paramHints, | ||||
'index': paramId, | 'index': paramId, | ||||
'rindex': -1, | 'rindex': -1, | ||||
'midiCC': midiCC, | |||||
'midiChannel': midiChannel | |||||
'midiChannel': midiChannel, | |||||
'mappedControlIndex': mappedControlIndex, | |||||
'mappedMinimum': mappedMinimum, | |||||
'mappedMaximum': mappedMaximum, | |||||
} | } | ||||
self.host._set_parameterData(pluginId, paramId, paramData) | self.host._set_parameterData(pluginId, paramId, paramData) | ||||
@@ -232,10 +232,10 @@ const char* EngineCallbackOpcode2Str(const EngineCallbackOpcode opcode) noexcept | |||||
case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | ||||
return "ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED"; | return "ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED"; | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #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: | case ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED: | ||||
return "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: | case ENGINE_CALLBACK_OPTION_CHANGED: | ||||
return "ENGINE_CALLBACK_OPTION_CHANGED"; | return "ENGINE_CALLBACK_OPTION_CHANGED"; | ||||
#endif | #endif | ||||
@@ -313,8 +313,6 @@ const char* EngineCallbackOpcode2Str(const EngineCallbackOpcode opcode) noexcept | |||||
return "ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_REMOVED"; | return "ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_REMOVED"; | ||||
case ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED: | case ENGINE_CALLBACK_PATCHBAY_PORT_GROUP_CHANGED: | ||||
return "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: | case ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED: | ||||
return "ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED"; | return "ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED"; | ||||
} | } | ||||
@@ -48,35 +48,35 @@ enum PluginBridgeRtClientOpcode { | |||||
// Server sends these to client during non-RT | // Server sends these to client during non-RT | ||||
enum PluginBridgeNonRtClientOpcode { | enum PluginBridgeNonRtClientOpcode { | ||||
kPluginBridgeNonRtClientNull = 0, | kPluginBridgeNonRtClientNull = 0, | ||||
kPluginBridgeNonRtClientVersion, // uint | |||||
kPluginBridgeNonRtClientVersion, // uint | |||||
kPluginBridgeNonRtClientPing, | kPluginBridgeNonRtClientPing, | ||||
kPluginBridgeNonRtClientPingOnOff, // bool | |||||
kPluginBridgeNonRtClientPingOnOff, // bool | |||||
kPluginBridgeNonRtClientActivate, | kPluginBridgeNonRtClientActivate, | ||||
kPluginBridgeNonRtClientDeactivate, | 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, | kPluginBridgeNonRtClientPrepareForSave, | ||||
kPluginBridgeNonRtClientRestoreLV2State, | kPluginBridgeNonRtClientRestoreLV2State, | ||||
kPluginBridgeNonRtClientShowUI, | kPluginBridgeNonRtClientShowUI, | ||||
kPluginBridgeNonRtClientHideUI, | 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, | kPluginBridgeNonRtClientQuit, | ||||
// stuff added in API 7 | // 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 | // Client sends these to server during non-RT | ||||
@@ -85,8 +85,8 @@ const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcod | |||||
return "kPluginBridgeNonRtClientSetParameterValue"; | return "kPluginBridgeNonRtClientSetParameterValue"; | ||||
case kPluginBridgeNonRtClientSetParameterMidiChannel: | case kPluginBridgeNonRtClientSetParameterMidiChannel: | ||||
return "kPluginBridgeNonRtClientSetParameterMidiChannel"; | return "kPluginBridgeNonRtClientSetParameterMidiChannel"; | ||||
case kPluginBridgeNonRtClientSetParameterMidiCC: | |||||
return "kPluginBridgeNonRtClientSetParameterMidiCC"; | |||||
case kPluginBridgeNonRtClientSetParameterMappedControlIndex: | |||||
return "kPluginBridgeNonRtClientSetParameterMappedControlIndex"; | |||||
case kPluginBridgeNonRtClientSetProgram: | case kPluginBridgeNonRtClientSetProgram: | ||||
return "kPluginBridgeNonRtClientSetProgram"; | return "kPluginBridgeNonRtClientSetProgram"; | ||||
case kPluginBridgeNonRtClientSetMidiProgram: | case kPluginBridgeNonRtClientSetMidiProgram: | ||||
@@ -124,8 +124,8 @@ CarlaStateSave::Parameter::Parameter() noexcept | |||||
symbol(nullptr), | symbol(nullptr), | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
value(0.0f), | value(0.0f), | ||||
midiChannel(0), | |||||
midiCC(-1) {} | |||||
mappedControlIndex(CONTROL_INDEX_NONE), | |||||
midiChannel(0) {} | |||||
#else | #else | ||||
value(0.0f) {} | value(0.0f) {} | ||||
#endif | #endif | ||||
@@ -441,8 +441,14 @@ bool CarlaStateSave::fillFromXmlElement(const XmlElement* const xmlElement) | |||||
else if (pTag == "MidiCC") | else if (pTag == "MidiCC") | ||||
{ | { | ||||
const int cc(pText.getIntValue()); | 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 | #endif | ||||
} | } | ||||
@@ -598,10 +604,18 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const | |||||
parameterXml << " <Symbol>" << xmlSafeString(stateParameter->symbol, true) << "</Symbol>\n"; | parameterXml << " <Symbol>" << xmlSafeString(stateParameter->symbol, true) << "</Symbol>\n"; | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #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 | #endif | ||||
@@ -35,8 +35,8 @@ struct CarlaStateSave { | |||||
const char* symbol; | const char* symbol; | ||||
float value; | float value; | ||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
int16_t mappedControlIndex; | |||||
uint8_t midiChannel; | uint8_t midiChannel; | ||||
int16_t midiCC; | |||||
#endif | #endif | ||||
Parameter() noexcept; | Parameter() noexcept; | ||||