@@ -1833,6 +1833,7 @@ typedef struct { | |||
/* Forward declarations of commonly used Carla classes */ | |||
class CarlaEngine; | |||
class CarlaEngineClient; | |||
class CarlaEngineCVSourcePorts; | |||
class CarlaPlugin; | |||
/* End namespace */ | |||
CARLA_BACKEND_END_NAMESPACE | |||
@@ -361,7 +361,7 @@ class CARLA_API CarlaEnginePort | |||
{ | |||
protected: | |||
/*! | |||
* The constructor. | |||
* The constructor, protected. | |||
* All constructor parameters are constant and will never change in the lifetime of the port. | |||
*/ | |||
CarlaEnginePort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; | |||
@@ -626,17 +626,17 @@ protected: | |||
*/ | |||
class CARLA_API CarlaEngineCVSourcePorts | |||
{ | |||
public: | |||
protected: | |||
/*! | |||
* The constructor. | |||
* All constructor parameters are constant and will never change in the lifetime of the port. | |||
* The constructor, protected. | |||
*/ | |||
CarlaEngineCVSourcePorts(/*const CarlaEngineClient& client*/); | |||
CarlaEngineCVSourcePorts(); | |||
public: | |||
/*! | |||
* The destructor. | |||
*/ | |||
~CarlaEngineCVSourcePorts(); | |||
virtual ~CarlaEngineCVSourcePorts(); | |||
/*! | |||
* Add a CV port as a source of events. | |||
@@ -664,7 +664,6 @@ public: | |||
protected: | |||
struct ProtectedData; | |||
ProtectedData* const pData; | |||
friend class CarlaPluginInstance; | |||
CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineCVSourcePorts) | |||
#endif | |||
@@ -680,13 +679,6 @@ protected: | |||
class CARLA_API CarlaEngineClient | |||
{ | |||
public: | |||
/*! | |||
* The constructor, protected. | |||
* All constructor parameters are constant and will never change in the lifetime of the client. | |||
* Client starts in deactivated state. | |||
*/ | |||
CarlaEngineClient(const CarlaEngine& engine); | |||
/*! | |||
* The destructor. | |||
*/ | |||
@@ -778,6 +770,12 @@ protected: | |||
struct ProtectedData; | |||
ProtectedData* const pData; | |||
/*! | |||
* The constructor, protected. | |||
*/ | |||
CarlaEngineClient(ProtectedData* pData); | |||
/** internal */ | |||
void _addAudioPortName(bool, const char*); | |||
void _addCVPortName(bool, const char*); | |||
void _addEventPortName(bool, const char*); | |||
@@ -2011,7 +2011,7 @@ void carla_set_parameter_mapped_control_index(uint pluginId, uint32_t parameterI | |||
CarlaPlugin* const plugin(gStandalone.engine->getPlugin(pluginId)); | |||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); | |||
carla_debug("carla_set_parameter_mapped_control_index(%i, %i, %i)", pluginId, parameterId, cc); | |||
carla_debug("carla_set_parameter_mapped_control_index(%i, %i, %i)", pluginId, parameterId, index); | |||
CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),); | |||
return plugin->setParameterMappedControlIndex(parameterId, index, true, false); | |||
@@ -376,9 +376,9 @@ void CarlaEngine::idle() noexcept | |||
#endif | |||
} | |||
CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const) | |||
CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const plugin) | |||
{ | |||
return new CarlaEngineClient(*this); | |||
return new CarlaEngineClient2(*this, pData->graph, plugin); | |||
} | |||
float CarlaEngine::getDSPLoad() const noexcept | |||
@@ -703,7 +703,7 @@ bool CarlaEngine::addPlugin(const BinaryType btype, | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
pData->graph.addPlugin(plugin); | |||
pData->graph.addPlugin(plugin, 1); | |||
#endif | |||
} | |||
@@ -2571,7 +2571,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc) | |||
callback(true, true, ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, 0, 0, 0, 0.0f, plugin->getName()); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
pData->graph.addPlugin(plugin); | |||
pData->graph.addPlugin(plugin, 1); | |||
} | |||
else | |||
{ | |||
@@ -2714,7 +2714,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc) | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
pData->graph.addPlugin(plugin); | |||
pData->graph.addPlugin(plugin, 1); | |||
#endif | |||
} | |||
else | |||
@@ -16,12 +16,34 @@ | |||
*/ | |||
#include "CarlaEngineUtils.hpp" | |||
#include "CarlaEngineInternal.hpp" | |||
#include "CarlaString.hpp" | |||
#include "CarlaStringList.hpp" | |||
CARLA_BACKEND_START_NAMESPACE | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine Meta CV port | |||
class CarlaEngineCVSourcePorts2 : public CarlaEngineCVSourcePorts | |||
{ | |||
public: | |||
CarlaEngineCVSourcePorts2() | |||
: CarlaEngineCVSourcePorts() | |||
{} | |||
~CarlaEngineCVSourcePorts2() override {} | |||
void setGraphAndPlugin(PatchbayGraph* const graph, CarlaPlugin* const plugin) noexcept | |||
{ | |||
pData->graph = graph; | |||
pData->plugin = plugin; | |||
} | |||
}; | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine client (Abstract) | |||
@@ -31,6 +53,12 @@ struct CarlaEngineClient::ProtectedData { | |||
bool active; | |||
uint32_t latency; | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
CarlaEngineCVSourcePorts2 cvSourcePorts; | |||
EngineInternalGraph& egraph; | |||
CarlaPlugin* const plugin; | |||
#endif | |||
CarlaStringList audioInList; | |||
CarlaStringList audioOutList; | |||
CarlaStringList cvInList; | |||
@@ -38,10 +66,15 @@ struct CarlaEngineClient::ProtectedData { | |||
CarlaStringList eventInList; | |||
CarlaStringList eventOutList; | |||
ProtectedData(const CarlaEngine& eng) noexcept | |||
ProtectedData(const CarlaEngine& eng, EngineInternalGraph& eg, CarlaPlugin* const p) noexcept | |||
: engine(eng), | |||
active(false), | |||
latency(0), | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
cvSourcePorts(), | |||
egraph(eg), | |||
plugin(p), | |||
#endif | |||
audioInList(), | |||
audioOutList(), | |||
cvInList(), | |||
@@ -55,8 +88,27 @@ struct CarlaEngineClient::ProtectedData { | |||
#endif | |||
}; | |||
CarlaEngineClient::CarlaEngineClient(const CarlaEngine& engine) | |||
: pData(new ProtectedData(engine)) | |||
CarlaEngineClient2::CarlaEngineClient2(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin) | |||
: CarlaEngineClient(new ProtectedData(engine, egraph, plugin)) | |||
{ | |||
} | |||
CarlaEngineClient2::~CarlaEngineClient2() | |||
{ | |||
} | |||
PatchbayGraph* CarlaEngineClient2::getPatchbayGraph() const noexcept | |||
{ | |||
return pData->egraph.getPatchbayGraph(); | |||
} | |||
CarlaPlugin* CarlaEngineClient2::getPlugin() const noexcept | |||
{ | |||
return pData->plugin; | |||
} | |||
CarlaEngineClient::CarlaEngineClient(ProtectedData* const p) | |||
: pData(p) | |||
{ | |||
carla_debug("CarlaEngineClient::CarlaEngineClient()"); | |||
} | |||
@@ -132,11 +184,8 @@ CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
CarlaEngineCVSourcePorts* CarlaEngineClient::createCVSourcePorts() | |||
{ | |||
// AudioProcessorGraph::Node* const oldNode(graph.getNodeForId(oldPlugin->getPatchbayNodeId())); | |||
// CARLA_SAFE_ASSERT_RETURN(oldNode != nullptr,); | |||
// pData->engine.pData->graph; | |||
return new CarlaEngineCVSourcePorts(); | |||
pData->cvSourcePorts.setGraphAndPlugin(pData->egraph.getPatchbayGraph(), pData->plugin); | |||
return &pData->cvSourcePorts; | |||
} | |||
#endif | |||
@@ -306,6 +355,11 @@ void CarlaEngineClient::_clearPorts() | |||
pData->eventOutList.clear(); | |||
} | |||
// void* CarlaEngineClient::_getNode() const noexcept | |||
// { | |||
// return pData->node; | |||
// } | |||
// ----------------------------------------------------------------------- | |||
CARLA_BACKEND_END_NAMESPACE |
@@ -1388,7 +1388,7 @@ public: | |||
: kEngine(engine), | |||
fPlugin(plugin) | |||
{ | |||
CarlaEngineClient* const client = fPlugin->getEngineClient(); | |||
CarlaEngineClient* const client = plugin->getEngineClient(); | |||
setPlayConfigDetails(client->getPortCount(kEnginePortTypeAudio, true), | |||
client->getPortCount(kEnginePortTypeAudio, false), | |||
@@ -1403,6 +1403,24 @@ public: | |||
{ | |||
} | |||
void reconfigure() override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
CarlaEngineClient* const client = fPlugin->getEngineClient(); | |||
CARLA_SAFE_ASSERT_RETURN(client != nullptr,); | |||
carla_stdout("reconfigure called"); | |||
setPlayConfigDetails(client->getPortCount(kEnginePortTypeAudio, true), | |||
client->getPortCount(kEnginePortTypeAudio, false), | |||
client->getPortCount(kEnginePortTypeCV, true), | |||
client->getPortCount(kEnginePortTypeCV, false), | |||
client->getPortCount(kEnginePortTypeEvent, true), | |||
client->getPortCount(kEnginePortTypeEvent, false), | |||
getSampleRate(), getBlockSize()); | |||
} | |||
void invalidatePlugin() noexcept | |||
{ | |||
fPlugin = nullptr; | |||
@@ -1778,14 +1796,14 @@ void PatchbayGraph::setOffline(const bool offline) | |||
graph.setNonRealtime(offline); | |||
} | |||
void PatchbayGraph::addPlugin(CarlaPlugin* const plugin) | |||
AudioProcessorGraph::Node* PatchbayGraph::addPlugin(CarlaPlugin* const plugin, bool) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); | |||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr); | |||
carla_debug("PatchbayGraph::addPlugin(%p)", plugin); | |||
CarlaPluginInstance* const instance(new CarlaPluginInstance(kEngine, plugin)); | |||
AudioProcessorGraph::Node* const node(graph.addNode(instance)); | |||
CARLA_SAFE_ASSERT_RETURN(node != nullptr,); | |||
CARLA_SAFE_ASSERT_RETURN(node != nullptr, nullptr); | |||
const bool sendHost = !usingExternalHost; | |||
const bool sendOSC = !usingExternalOSC; | |||
@@ -1796,6 +1814,8 @@ void PatchbayGraph::addPlugin(CarlaPlugin* const plugin) | |||
node->properties.set("pluginId", static_cast<int>(plugin->getId())); | |||
addNodeToPatchbay(sendHost, sendOSC, kEngine, node->nodeId, static_cast<int>(plugin->getId()), instance); | |||
return node; | |||
} | |||
void PatchbayGraph::replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin) | |||
@@ -1848,6 +1868,60 @@ void PatchbayGraph::renamePlugin(CarlaPlugin* const plugin, const char* const ne | |||
newName); | |||
} | |||
void PatchbayGraph::reconfigureForCV(CarlaPlugin* const plugin, const uint portIndex, bool added) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); | |||
carla_debug("PatchbayGraph::reconfigureForCV(%p, %u, %s)", plugin, portIndex, bool2str(added)); | |||
AudioProcessorGraph::Node* const node = graph.getNodeForId(plugin->getPatchbayNodeId()); | |||
CARLA_SAFE_ASSERT_RETURN(node != nullptr,); | |||
CarlaPluginInstance* const proc = dynamic_cast<CarlaPluginInstance*>(node->getProcessor()); | |||
CARLA_SAFE_ASSERT_RETURN(proc != nullptr,); | |||
const bool sendHost = !usingExternalHost; | |||
const bool sendOSC = !usingExternalOSC; | |||
const uint oldCvIn = proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); | |||
const uint oldCvOut = proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); | |||
{ | |||
const CarlaRecursiveMutexLocker crml(graph.getCallbackLock()); | |||
proc->reconfigure(); | |||
graph.buildRenderingSequence(); | |||
} | |||
const uint newCvIn = proc->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV); | |||
const uint newCvOut = proc->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV); | |||
if (added) | |||
{ | |||
CARLA_SAFE_ASSERT_UINT2_RETURN(newCvIn >= oldCvIn, newCvIn, oldCvIn,); | |||
CARLA_SAFE_ASSERT_UINT2_RETURN(newCvOut >= oldCvOut, newCvOut, oldCvOut,); | |||
kEngine->callback(sendHost, sendOSC, | |||
ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, | |||
node->nodeId, | |||
static_cast<int>(kCVInputPortOffset + plugin->getCVInCount() + portIndex), | |||
PATCHBAY_PORT_TYPE_CV|PATCHBAY_PORT_IS_INPUT, | |||
0, 0.0f, | |||
proc->getInputChannelName(AudioProcessor::ChannelTypeCV, portIndex).toRawUTF8()); | |||
} | |||
else | |||
{ | |||
CARLA_SAFE_ASSERT_UINT2_RETURN(newCvIn <= oldCvIn, newCvIn, oldCvIn,); | |||
CARLA_SAFE_ASSERT_UINT2_RETURN(newCvOut <= oldCvOut, newCvOut, oldCvOut,); | |||
kEngine->callback(sendHost, sendOSC, | |||
ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, | |||
node->nodeId, | |||
static_cast<int>(kCVInputPortOffset + plugin->getCVInCount() + portIndex), | |||
0, 0, 0.0f, nullptr); | |||
} | |||
} | |||
void PatchbayGraph::removePlugin(CarlaPlugin* const plugin) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); | |||
@@ -2443,10 +2517,10 @@ void EngineInternalGraph::processRack(CarlaEngine::ProtectedData* const data, co | |||
// ----------------------------------------------------------------------- | |||
// used for internal patchbay mode | |||
void EngineInternalGraph::addPlugin(CarlaPlugin* const plugin) | |||
water::AudioProcessorGraph::Node* EngineInternalGraph::addPlugin(CarlaPlugin* const plugin, bool x) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); | |||
fPatchbay->addPlugin(plugin); | |||
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr, nullptr); | |||
return fPatchbay->addPlugin(plugin, x); | |||
} | |||
void EngineInternalGraph::replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin) | |||
@@ -179,9 +179,11 @@ public: | |||
void setSampleRate(double sampleRate); | |||
void setOffline(bool offline); | |||
void addPlugin(CarlaPlugin* plugin); | |||
AudioProcessorGraph::Node* addPlugin(CarlaPlugin* plugin, bool); | |||
void replacePlugin(CarlaPlugin* oldPlugin, CarlaPlugin* newPlugin); | |||
void renamePlugin(CarlaPlugin* plugin, const char* newName); | |||
void reconfigureForCV(CarlaPlugin* const plugin, const uint portIndex, bool added); | |||
void reconfigurePlugin(CarlaPlugin* plugin, bool portsAdded); | |||
void removePlugin(CarlaPlugin* plugin); | |||
void removeAllPlugins(); | |||
@@ -28,6 +28,7 @@ | |||
#endif | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
# include "water/processors/AudioProcessorGraph.h" | |||
# include "water/containers/Array.h" | |||
# include "water/memory/Atomic.h" | |||
#endif | |||
@@ -94,7 +95,7 @@ public: | |||
void processRack(CarlaEngine::ProtectedData* data, const float* inBuf[2], float* outBuf[2], uint32_t frames); | |||
// used for internal patchbay mode | |||
void addPlugin(CarlaPlugin* plugin); | |||
water::AudioProcessorGraph::Node* addPlugin(CarlaPlugin* plugin, bool); | |||
void replacePlugin(CarlaPlugin* oldPlugin, CarlaPlugin* newPlugin); | |||
void renamePlugin(CarlaPlugin* plugin, const char* newName); | |||
void removePlugin(CarlaPlugin* plugin); | |||
@@ -225,6 +226,9 @@ struct CarlaEngineCVSourcePorts::ProtectedData { | |||
EngineEvent* buffer; | |||
water::Array<CarlaEngineEventCV> cvs; | |||
PatchbayGraph* graph; | |||
CarlaPlugin* plugin; | |||
ProtectedData(); | |||
~ProtectedData(); | |||
@@ -232,6 +236,19 @@ struct CarlaEngineCVSourcePorts::ProtectedData { | |||
}; | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
class CarlaEngineClient2 : public CarlaEngineClient | |||
{ | |||
public: | |||
CarlaEngineClient2(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin); | |||
virtual ~CarlaEngineClient2() override; | |||
protected: | |||
PatchbayGraph* getPatchbayGraph() const noexcept; | |||
CarlaPlugin* getPlugin() const noexcept; | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// CarlaEngineProtectedData | |||
@@ -510,18 +510,24 @@ public: | |||
const int ioffset = static_cast<int>(portIndexOffset); | |||
return pData->cvs[ioffset].cvPort; | |||
} | |||
void setGraphAndPlugin(PatchbayGraph* const graph, CarlaPlugin* const plugin) noexcept | |||
{ | |||
pData->graph = graph; | |||
pData->plugin = plugin; | |||
} | |||
}; | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Jack Engine client | |||
class CarlaEngineJackClient : public CarlaEngineClient, | |||
class CarlaEngineJackClient : public CarlaEngineClient2, | |||
private JackPortDeletionCallback | |||
{ | |||
public: | |||
CarlaEngineJackClient(const CarlaEngine& engine, jack_client_t* const jackClient) | |||
: CarlaEngineClient(engine), | |||
CarlaEngineJackClient(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin, jack_client_t* const jackClient) | |||
: CarlaEngineClient2(engine, egraph, plugin), | |||
fJackClient(jackClient), | |||
fUseClient(engine.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT || engine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS), | |||
fAudioPorts(), | |||
@@ -696,6 +702,7 @@ public: | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
CarlaEngineCVSourcePorts* createCVSourcePorts() override | |||
{ | |||
fCVSourcePorts.setGraphAndPlugin(getPatchbayGraph(), getPlugin()); | |||
return &fCVSourcePorts; | |||
} | |||
@@ -1437,7 +1444,7 @@ public: | |||
#endif | |||
} | |||
return new CarlaEngineJackClient(*this, client); | |||
return new CarlaEngineJackClient(*this, pData->graph, plugin, client); | |||
} | |||
#ifndef BUILD_BRIDGE | |||
@@ -16,6 +16,7 @@ | |||
*/ | |||
#include "CarlaEngineInternal.hpp" | |||
#include "CarlaEngineGraph.hpp" | |||
#include "CarlaEngineUtils.hpp" | |||
#include "CarlaMathUtils.hpp" | |||
#include "CarlaMIDI.h" | |||
@@ -329,7 +330,9 @@ bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha | |||
CarlaEngineCVSourcePorts::ProtectedData::ProtectedData() | |||
: rmutex(), | |||
buffer(nullptr), | |||
cvs() | |||
cvs(), | |||
graph(nullptr), | |||
plugin(nullptr) | |||
{ | |||
} | |||
@@ -337,8 +340,12 @@ CarlaEngineCVSourcePorts::ProtectedData::~ProtectedData() | |||
{ | |||
const CarlaRecursiveMutexLocker crml(rmutex); | |||
carla_stdout("CarlaEngineCVSourcePorts::ProtectedData::~ProtectedData size %i", cvs.size()); | |||
/* | |||
for (int i = cvs.size(); --i >= 0;) | |||
delete cvs[i].cvPort; | |||
*/ | |||
cvs.clear(); | |||
@@ -349,7 +356,7 @@ CarlaEngineCVSourcePorts::ProtectedData::~ProtectedData() | |||
} | |||
} | |||
CarlaEngineCVSourcePorts::CarlaEngineCVSourcePorts(/*const CarlaEngineClient& client*/) | |||
CarlaEngineCVSourcePorts::CarlaEngineCVSourcePorts() | |||
: pData(new ProtectedData()) | |||
{ | |||
carla_debug("CarlaEngineCVSourcePorts::CarlaEngineCVSourcePorts()"); | |||
@@ -358,6 +365,7 @@ CarlaEngineCVSourcePorts::CarlaEngineCVSourcePorts(/*const CarlaEngineClient& cl | |||
CarlaEngineCVSourcePorts::~CarlaEngineCVSourcePorts() | |||
{ | |||
carla_debug("CarlaEngineCVSourcePorts::~CarlaEngineCVSourcePorts()"); | |||
delete pData; | |||
} | |||
bool CarlaEngineCVSourcePorts::addCVSource(CarlaEngineCVPort* const port, const uint32_t portIndexOffset) | |||
@@ -366,16 +374,21 @@ bool CarlaEngineCVSourcePorts::addCVSource(CarlaEngineCVPort* const port, const | |||
CARLA_SAFE_ASSERT_RETURN(port->isInput(), false); | |||
carla_debug("CarlaEngineCVSourcePorts::addCVSource(%p)", port); | |||
const CarlaRecursiveMutexLocker crml(pData->rmutex); | |||
{ | |||
const CarlaRecursiveMutexLocker crml(pData->rmutex); | |||
const CarlaEngineEventCV ecv = { port, portIndexOffset, 0.0f }; | |||
if (! pData->cvs.add(ecv)) | |||
return false; | |||
const CarlaEngineEventCV ecv = { port, portIndexOffset, 0.0f }; | |||
if (! pData->cvs.add(ecv)) | |||
return false; | |||
/* | |||
if (pData->buffer == nullptr) | |||
pData->buffer = new EngineEvent[kMaxEngineEventInternalCount]; | |||
*/ | |||
if (pData->graph != nullptr && pData->plugin != nullptr) | |||
pData->graph->reconfigureForCV(pData->plugin, pData->cvs.size()-1, true); | |||
/* | |||
if (pData->buffer == nullptr) | |||
pData->buffer = new EngineEvent[kMaxEngineEventInternalCount]; | |||
*/ | |||
} | |||
return true; | |||
} | |||
@@ -384,16 +397,24 @@ bool CarlaEngineCVSourcePorts::removeCVSource(const uint32_t portIndexOffset) | |||
{ | |||
carla_debug("CarlaEngineCVSourcePorts::removeCVSource(%u)", portIndexOffset); | |||
const CarlaRecursiveMutexLocker crml(pData->rmutex); | |||
for (int i = pData->cvs.size(); --i >= 0;) | |||
{ | |||
const CarlaEngineEventCV& ecv(pData->cvs[i]); | |||
const CarlaRecursiveMutexLocker crml(pData->rmutex); | |||
if (ecv.indexOffset == portIndexOffset) | |||
for (int i = pData->cvs.size(); --i >= 0;) | |||
{ | |||
pData->cvs.remove(i); | |||
break; | |||
const CarlaEngineEventCV& ecv(pData->cvs[i]); | |||
if (ecv.indexOffset == portIndexOffset) | |||
{ | |||
if (pData->graph != nullptr && pData->plugin != nullptr) | |||
pData->graph->reconfigureForCV(pData->plugin, i, false); | |||
carla_stdout("found cv source to remove %u", portIndexOffset); | |||
delete ecv.cvPort; | |||
pData->cvs.remove(i); | |||
return true; | |||
} | |||
} | |||
} | |||
@@ -403,7 +424,8 @@ bool CarlaEngineCVSourcePorts::removeCVSource(const uint32_t portIndexOffset) | |||
pData->buffer = nullptr; | |||
} | |||
return true; | |||
carla_stdout("did NOT found cv source to remove %u", portIndexOffset); | |||
return false; | |||
} | |||
bool CarlaEngineCVSourcePorts::setCVSourceRange(const uint32_t portIndexOffset, const float minimum, const float maximum) | |||
@@ -438,6 +460,19 @@ void CarlaEngineCVSourcePorts::initPortBuffers(const float* const* const buffers | |||
if (! crmtl.wasLocked()) | |||
return; | |||
const int numCVs = pData->cvs.size(); | |||
static int oldNumCVs = 0; | |||
if (oldNumCVs != numCVs) | |||
{ | |||
carla_stdout("initPortBuffers %i %i", numCVs, oldNumCVs); | |||
oldNumCVs = numCVs; | |||
} | |||
if (numCVs == 0) | |||
return; | |||
EngineEvent* const buffer = eventPort->fBuffer; | |||
CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); | |||
/* | |||
@@ -459,7 +494,7 @@ void CarlaEngineCVSourcePorts::initPortBuffers(const float* const* const buffers | |||
if (sampleAccurate || true) | |||
{ | |||
for (int i = 0; i < pData->cvs.size() && eventCount < kMaxEngineEventInternalCount; ++i) | |||
for (int i = 0; i < numCVs && eventCount < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
CarlaEngineEventCV& ecv(pData->cvs.getReference(i)); | |||
CARLA_SAFE_ASSERT_CONTINUE(ecv.cvPort != nullptr); | |||
@@ -173,11 +173,7 @@ void PluginEventData::clear() noexcept | |||
} | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
if (cvSourcePorts != nullptr) | |||
{ | |||
delete cvSourcePorts; | |||
cvSourcePorts = nullptr; | |||
} | |||
cvSourcePorts = nullptr; | |||
#endif | |||
} | |||
@@ -1310,6 +1310,9 @@ public: | |||
portName.truncate(portNameSize); | |||
pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0); | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); | |||
#endif | |||
} | |||
if (needsCtrlOut || mOuts == 1) | |||
@@ -1469,10 +1472,15 @@ public: | |||
// extra parameter hints | |||
if (paramInfo->hints & NATIVE_PARAMETER_IS_ENABLED) | |||
{ | |||
pData->param.data[j].hints |= PARAMETER_IS_ENABLED; | |||
if (paramInfo->hints & NATIVE_PARAMETER_IS_AUTOMABLE) | |||
pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; | |||
if (paramInfo->hints & NATIVE_PARAMETER_IS_AUTOMABLE) | |||
{ | |||
pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE; | |||
pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED; | |||
} | |||
} | |||
if (paramInfo->hints & NATIVE_PARAMETER_IS_LOGARITHMIC) | |||
pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC; | |||
@@ -1821,7 +1829,7 @@ public: | |||
#ifndef BUILD_BRIDGE | |||
bool allNotesOffSent = false; | |||
#endif | |||
bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; | |||
uint32_t startTime = 0; | |||
uint32_t timeOffset = 0; | |||
@@ -1832,6 +1840,11 @@ public: | |||
else | |||
nextBankId = 0; | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr) | |||
pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn); | |||
#endif | |||
for (;;) | |||
{ | |||
const EngineEvent& event(findNextEvent()); | |||
@@ -1849,7 +1862,7 @@ public: | |||
eventTime = timeOffset; | |||
} | |||
if (sampleAccurate && eventTime > timeOffset) | |||
if (isSampleAccurate && eventTime > timeOffset) | |||
{ | |||
if (processSingle(audioIn, audioOut, cvIn, cvOut, eventTime - timeOffset, timeOffset)) | |||
{ | |||
@@ -1976,7 +1989,7 @@ public: | |||
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
nativeEvent.time = sampleAccurate ? startTime : eventTime; | |||
nativeEvent.time = isSampleAccurate ? startTime : eventTime; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = uint8_t(ctrlEvent.param); | |||
nativeEvent.data[2] = uint8_t(ctrlEvent.value*127.0f); | |||
@@ -2000,7 +2013,7 @@ public: | |||
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
nativeEvent.time = sampleAccurate ? startTime : eventTime; | |||
nativeEvent.time = isSampleAccurate ? startTime : eventTime; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = MIDI_CONTROL_BANK_SELECT; | |||
nativeEvent.data[2] = uint8_t(ctrlEvent.param); | |||
@@ -2047,7 +2060,7 @@ public: | |||
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
nativeEvent.time = sampleAccurate ? startTime : eventTime; | |||
nativeEvent.time = isSampleAccurate ? startTime : eventTime; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = uint8_t(ctrlEvent.param); | |||
nativeEvent.size = 2; | |||
@@ -2063,7 +2076,7 @@ public: | |||
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
nativeEvent.time = sampleAccurate ? startTime : eventTime; | |||
nativeEvent.time = isSampleAccurate ? startTime : eventTime; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
nativeEvent.data[2] = 0; | |||
@@ -2088,7 +2101,7 @@ public: | |||
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]); | |||
carla_zeroStruct(nativeEvent); | |||
nativeEvent.time = sampleAccurate ? startTime : eventTime; | |||
nativeEvent.time = isSampleAccurate ? startTime : eventTime; | |||
nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)); | |||
nativeEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
nativeEvent.data[2] = 0; | |||
@@ -2130,7 +2143,7 @@ public: | |||
carla_zeroStruct(nativeEvent); | |||
nativeEvent.port = midiEvent.port; | |||
nativeEvent.time = sampleAccurate ? startTime : eventTime; | |||
nativeEvent.time = isSampleAccurate ? startTime : eventTime; | |||
nativeEvent.size = midiEvent.size; | |||
nativeEvent.data[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT)); | |||
@@ -87,6 +87,7 @@ void AudioProcessor::suspendProcessing (const bool shouldBeSuspended) | |||
} | |||
void AudioProcessor::reset() {} | |||
void AudioProcessor::reconfigure() {} | |||
uint AudioProcessor::getTotalNumInputChannels(ChannelType t) const noexcept | |||
{ | |||
@@ -270,6 +270,13 @@ public: | |||
*/ | |||
virtual void reset(); | |||
/** A plugin can override this to be told when it should reconfigure itself. | |||
The default implementation does nothing, but a host may call this to tell the | |||
plugin that it should call setPlayConfigDetails again. | |||
*/ | |||
virtual void reconfigure(); | |||
//============================================================================== | |||
/** Returns true if the processor is being run in an offline mode for rendering. | |||
@@ -389,6 +389,7 @@ private: | |||
bool isPrepared, needsReorder; | |||
CarlaRecursiveMutex reorderMutex; | |||
public: | |||
void clearRenderingSequence(); | |||
void buildRenderingSequence(); | |||
bool isAnInputTo (uint32 possibleInputId, uint32 possibleDestinationId, int recursionCheck) const; | |||