Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
@@ -553,12 +553,12 @@ public: | |||
/*! | |||
* Add a CV port as a source of events. | |||
*/ | |||
void addCVSource(CarlaEngineCVPort* port) noexcept; | |||
void addCVSource(CarlaEngineCVPort* port, uint32_t portIndexOffset) noexcept; | |||
/*! | |||
* Remove a CV port as a source of events. | |||
*/ | |||
void removeCVSource(CarlaEngineCVPort* port) noexcept; | |||
void removeCVSource(uint32_t portIndexOffset) noexcept; | |||
/*! | |||
* Remove a CV port as a source of events. | |||
@@ -214,8 +214,8 @@ struct EnginePluginData { | |||
struct CarlaEngineEventCV { | |||
CarlaEngineCVPort* cvPort; | |||
float previousValue; | |||
uint32_t indexOffset; | |||
float previousValue; | |||
}; | |||
struct CarlaEngineEventPort::ProtectedData { | |||
@@ -223,30 +223,8 @@ struct CarlaEngineEventPort::ProtectedData { | |||
const EngineProcessMode processMode; | |||
LinkedList<CarlaEngineEventCV> cvs; | |||
ProtectedData(const EngineProcessMode pm) noexcept | |||
: buffer(nullptr), | |||
processMode(pm), | |||
cvs() | |||
{ | |||
if (processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
buffer = new EngineEvent[kMaxEngineEventInternalCount]; | |||
carla_zeroStructs(buffer, kMaxEngineEventInternalCount); | |||
} | |||
} | |||
~ProtectedData() noexcept | |||
{ | |||
cvs.clear(); | |||
if (processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); | |||
delete[] buffer; | |||
buffer = nullptr; | |||
} | |||
} | |||
ProtectedData(const EngineProcessMode pm) noexcept; | |||
~ProtectedData() noexcept; | |||
CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData) | |||
}; | |||
@@ -28,6 +28,7 @@ CARLA_BACKEND_START_NAMESPACE | |||
// Fallback data | |||
static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; | |||
static CarlaEngineEventCV kFallbackEngineEventCV = { nullptr, (uint32_t)-1, 0.0f }; | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine port (Abstract) | |||
@@ -112,6 +113,34 @@ void CarlaEngineCVPort::setRange(const float min, const float max) noexcept | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine Event port | |||
CarlaEngineEventPort::ProtectedData::ProtectedData(const EngineProcessMode pm) noexcept | |||
: buffer(nullptr), | |||
processMode(pm), | |||
cvs() | |||
{ | |||
if (processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
buffer = new EngineEvent[kMaxEngineEventInternalCount]; | |||
carla_zeroStructs(buffer, kMaxEngineEventInternalCount); | |||
} | |||
} | |||
CarlaEngineEventPort::ProtectedData::~ProtectedData() noexcept | |||
{ | |||
for (LinkedList<CarlaEngineEventCV>::Itenerator it = cvs.begin2(); it.valid(); it.next()) | |||
delete it.getValue(kFallbackEngineEventCV).cvPort; | |||
cvs.clear(); | |||
if (processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); | |||
delete[] buffer; | |||
buffer = nullptr; | |||
} | |||
} | |||
CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept | |||
: CarlaEnginePort(client, isInputPort, indexOffset), | |||
pData(new ProtectedData(client.getEngine().getProccessMode())) | |||
@@ -125,27 +154,31 @@ CarlaEngineEventPort::~CarlaEngineEventPort() noexcept | |||
delete pData; | |||
} | |||
void CarlaEngineEventPort::addCVSource(CarlaEngineCVPort* const port) noexcept | |||
void CarlaEngineEventPort::addCVSource(CarlaEngineCVPort* const port, const uint32_t portIndexOffset) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(port != nullptr,); | |||
CARLA_SAFE_ASSERT_RETURN(port->isInput(),); | |||
carla_debug("CarlaEngineEventPort::addCVSource(%p)", port); | |||
const CarlaEngineEventCV ecv { port, 0.0f, port->getIndexOffset() }; | |||
const CarlaEngineEventCV ecv { port, portIndexOffset, 0.0f }; | |||
pData->cvs.append(ecv); | |||
} | |||
void CarlaEngineEventPort::removeCVSource(CarlaEngineCVPort* const port) noexcept | |||
void CarlaEngineEventPort::removeCVSource(const uint32_t portIndexOffset) noexcept | |||
{ | |||
carla_debug("CarlaEngineEventPort::removeCVSource(%p)", port); | |||
carla_debug("CarlaEngineEventPort::removeCVSource(%u)", portIndexOffset); | |||
// pData->cvPorts.removeOne(port); | |||
// TODO | |||
return; | |||
(void)port; | |||
} | |||
for (LinkedList<CarlaEngineEventCV>::Itenerator it = pData->cvs.begin2(); it.valid(); it.next()) | |||
{ | |||
CarlaEngineEventCV& ecv(it.getValue(kFallbackEngineEventCV)); | |||
static CarlaEngineEventCV kFallbackEngineEventCV = { nullptr, 0.0f, (uint32_t)-1 }; | |||
if (ecv.indexOffset == portIndexOffset) | |||
{ | |||
pData->cvs.remove(it); | |||
break; | |||
} | |||
} | |||
} | |||
void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer, | |||
const uint32_t frames, | |||
@@ -177,7 +210,7 @@ void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer, | |||
float previousValue = ecv.previousValue; | |||
ecv.cvPort->getRange(min, max); | |||
for (uint32_t i=0; i<frames; ++i) | |||
for (uint32_t i=0; i<frames; i+=32) | |||
{ | |||
v = buffer[i]; | |||
@@ -185,7 +218,7 @@ void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer, | |||
{ | |||
previousValue = v; | |||
EngineEvent& event(pData->buffer[i++]); | |||
EngineEvent& event(pData->buffer[eventIndex++]); | |||
event.type = kEngineEventTypeControl; | |||
event.time = i; | |||
@@ -1239,7 +1239,7 @@ public: | |||
CarlaEngineCVPort* const cvPort = | |||
(CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, i); | |||
cvPort->setRange(pData->param.ranges[i].min, pData->param.ranges[i].max); | |||
pData->event.portIn->addCVSource(cvPort); | |||
pData->event.portIn->addCVSource(cvPort, i); | |||
} | |||
} | |||
@@ -2798,6 +2798,30 @@ public: | |||
portName.truncate(portNameSize); | |||
pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); | |||
for (uint32_t i=0; i < params; ++i) | |||
{ | |||
const int32_t rindex = pData->param.data[i].rindex; | |||
CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0 && rindex < static_cast<int32_t>(fRdfDescriptor->PortCount)); | |||
if (pData->param.data[i].type != PARAMETER_INPUT) | |||
continue; | |||
if (fRdfDescriptor->Ports[rindex].Name == nullptr || fRdfDescriptor->Ports[rindex].Name[0] == '\0') | |||
continue; | |||
portName = fRdfDescriptor->Ports[rindex].Name; | |||
portName.truncate(portNameSize); | |||
// Parameter as CV | |||
CarlaEngineCVPort* const cvPort = | |||
(CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, i); | |||
if (true) | |||
cvPort->setRange(0.0f, 3.0f + (float)i); | |||
else | |||
cvPort->setRange(pData->param.ranges[i].min, pData->param.ranges[i].max); | |||
pData->event.portIn->addCVSource(cvPort, i); | |||
} | |||
} | |||
if (needsCtrlOut) | |||
@@ -2844,7 +2868,7 @@ public: | |||
if (char* const midnam = fExt.midnam->midnam(fHandle)) | |||
{ | |||
fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", | |||
midnam, "text/xml"); | |||
midnam, "text/xml"); | |||
if (fExt.midnam->free != nullptr) | |||
fExt.midnam->free(midnam); | |||
} | |||
@@ -3497,6 +3521,19 @@ public: | |||
} // End of MIDI Input (External) | |||
// ---------------------------------------------------------------------------------------------------- | |||
// CV Control Input | |||
for (uint32_t i=0, j=0; i < pData->param.count; ++i) | |||
{ | |||
if (pData->param.data[i].type != PARAMETER_INPUT) | |||
continue; | |||
const uint32_t cvIndex = j++; | |||
pData->event.portIn->mixWithCvBuffer(cvIn[pData->cvIn.count + cvIndex], frames, i); | |||
} | |||
// ---------------------------------------------------------------------------------------------------- | |||
// Event Input (System) | |||
@@ -3598,12 +3635,37 @@ public: | |||
break; | |||
case kEngineControlEventTypeParameter: { | |||
float value; | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
// via CV | |||
if (event.channel == 0xFF) | |||
{ | |||
const uint32_t k = ctrlEvent.param; | |||
CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count); | |||
if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
{ | |||
value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max; | |||
} | |||
else | |||
{ | |||
if (pData->param.data[k].hints & PARAMETER_IS_LOGARITHMIC) | |||
value = pData->param.ranges[k].getUnnormalizedLogValue(ctrlEvent.value); | |||
else | |||
value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value); | |||
if (pData->param.data[k].hints & PARAMETER_IS_INTEGER) | |||
value = std::rint(value); | |||
} | |||
setParameterValueRT(k, value, true); | |||
continue; | |||
} | |||
// Control backend stuff | |||
if (event.channel == pData->ctrlChannel) | |||
{ | |||
float value; | |||
if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) | |||
{ | |||
value = ctrlEvent.value; | |||
@@ -3655,8 +3717,6 @@ public: | |||
if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) | |||
continue; | |||
float value; | |||
if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
{ | |||
value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max; | |||