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