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. | * 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. | * 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. | * Remove a CV port as a source of events. | ||||
@@ -214,8 +214,8 @@ struct EnginePluginData { | |||||
struct CarlaEngineEventCV { | struct CarlaEngineEventCV { | ||||
CarlaEngineCVPort* cvPort; | CarlaEngineCVPort* cvPort; | ||||
float previousValue; | |||||
uint32_t indexOffset; | uint32_t indexOffset; | ||||
float previousValue; | |||||
}; | }; | ||||
struct CarlaEngineEventPort::ProtectedData { | struct CarlaEngineEventPort::ProtectedData { | ||||
@@ -223,30 +223,8 @@ struct CarlaEngineEventPort::ProtectedData { | |||||
const EngineProcessMode processMode; | const EngineProcessMode processMode; | ||||
LinkedList<CarlaEngineEventCV> cvs; | 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) | CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData) | ||||
}; | }; | ||||
@@ -28,6 +28,7 @@ CARLA_BACKEND_START_NAMESPACE | |||||
// Fallback data | // Fallback data | ||||
static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; | static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; | ||||
static CarlaEngineEventCV kFallbackEngineEventCV = { nullptr, (uint32_t)-1, 0.0f }; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Carla Engine port (Abstract) | // Carla Engine port (Abstract) | ||||
@@ -112,6 +113,34 @@ void CarlaEngineCVPort::setRange(const float min, const float max) noexcept | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Carla Engine Event port | // 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 | CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept | ||||
: CarlaEnginePort(client, isInputPort, indexOffset), | : CarlaEnginePort(client, isInputPort, indexOffset), | ||||
pData(new ProtectedData(client.getEngine().getProccessMode())) | pData(new ProtectedData(client.getEngine().getProccessMode())) | ||||
@@ -125,27 +154,31 @@ CarlaEngineEventPort::~CarlaEngineEventPort() noexcept | |||||
delete pData; | 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 != nullptr,); | ||||
CARLA_SAFE_ASSERT_RETURN(port->isInput(),); | CARLA_SAFE_ASSERT_RETURN(port->isInput(),); | ||||
carla_debug("CarlaEngineEventPort::addCVSource(%p)", port); | 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); | 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, | void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer, | ||||
const uint32_t frames, | const uint32_t frames, | ||||
@@ -177,7 +210,7 @@ void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer, | |||||
float previousValue = ecv.previousValue; | float previousValue = ecv.previousValue; | ||||
ecv.cvPort->getRange(min, max); | 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]; | v = buffer[i]; | ||||
@@ -185,7 +218,7 @@ void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer, | |||||
{ | { | ||||
previousValue = v; | previousValue = v; | ||||
EngineEvent& event(pData->buffer[i++]); | |||||
EngineEvent& event(pData->buffer[eventIndex++]); | |||||
event.type = kEngineEventTypeControl; | event.type = kEngineEventTypeControl; | ||||
event.time = i; | event.time = i; | ||||
@@ -1239,7 +1239,7 @@ public: | |||||
CarlaEngineCVPort* const cvPort = | CarlaEngineCVPort* const cvPort = | ||||
(CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, i); | (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, i); | ||||
cvPort->setRange(pData->param.ranges[i].min, pData->param.ranges[i].max); | 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); | portName.truncate(portNameSize); | ||||
pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); | 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) | if (needsCtrlOut) | ||||
@@ -2844,7 +2868,7 @@ public: | |||||
if (char* const midnam = fExt.midnam->midnam(fHandle)) | if (char* const midnam = fExt.midnam->midnam(fHandle)) | ||||
{ | { | ||||
fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", | fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", | ||||
midnam, "text/xml"); | |||||
midnam, "text/xml"); | |||||
if (fExt.midnam->free != nullptr) | if (fExt.midnam->free != nullptr) | ||||
fExt.midnam->free(midnam); | fExt.midnam->free(midnam); | ||||
} | } | ||||
@@ -3497,6 +3521,19 @@ public: | |||||
} // End of MIDI Input (External) | } // 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) | // Event Input (System) | ||||
@@ -3598,12 +3635,37 @@ public: | |||||
break; | break; | ||||
case kEngineControlEventTypeParameter: { | case kEngineControlEventTypeParameter: { | ||||
float value; | |||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #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 | // Control backend stuff | ||||
if (event.channel == pData->ctrlChannel) | if (event.channel == pData->ctrlChannel) | ||||
{ | { | ||||
float value; | |||||
if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) | if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0) | ||||
{ | { | ||||
value = ctrlEvent.value; | value = ctrlEvent.value; | ||||
@@ -3655,8 +3717,6 @@ public: | |||||
if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) | if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) | ||||
continue; | continue; | ||||
float value; | |||||
if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | ||||
{ | { | ||||
value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max; | value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max; | ||||