diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h index 8e51044fd..ea2b55f1d 100644 --- a/source/backend/CarlaBackend.h +++ b/source/backend/CarlaBackend.h @@ -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 diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index d49e0b26c..a58e24e97 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -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*); diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp index d1ba3789a..2a6160cbc 100644 --- a/source/backend/CarlaStandalone.cpp +++ b/source/backend/CarlaStandalone.cpp @@ -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); diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index b09a60d80..e7e8142e5 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -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 diff --git a/source/backend/engine/CarlaEngineClient.cpp b/source/backend/engine/CarlaEngineClient.cpp index 7f9830ebc..001157568 100644 --- a/source/backend/engine/CarlaEngineClient.cpp +++ b/source/backend/engine/CarlaEngineClient.cpp @@ -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 diff --git a/source/backend/engine/CarlaEngineGraph.cpp b/source/backend/engine/CarlaEngineGraph.cpp index c1c73c7fb..455e17e0a 100644 --- a/source/backend/engine/CarlaEngineGraph.cpp +++ b/source/backend/engine/CarlaEngineGraph.cpp @@ -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(plugin->getId())); addNodeToPatchbay(sendHost, sendOSC, kEngine, node->nodeId, static_cast(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(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(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(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) diff --git a/source/backend/engine/CarlaEngineGraph.hpp b/source/backend/engine/CarlaEngineGraph.hpp index 7043ede15..033bdf33b 100644 --- a/source/backend/engine/CarlaEngineGraph.hpp +++ b/source/backend/engine/CarlaEngineGraph.hpp @@ -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(); diff --git a/source/backend/engine/CarlaEngineInternal.hpp b/source/backend/engine/CarlaEngineInternal.hpp index d8ce95124..2eccba77f 100644 --- a/source/backend/engine/CarlaEngineInternal.hpp +++ b/source/backend/engine/CarlaEngineInternal.hpp @@ -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 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 diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 43d81438c..556009969 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -510,18 +510,24 @@ public: const int ioffset = static_cast(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 diff --git a/source/backend/engine/CarlaEnginePorts.cpp b/source/backend/engine/CarlaEnginePorts.cpp index 65bea4f7a..fbfa8bf0e 100644 --- a/source/backend/engine/CarlaEnginePorts.cpp +++ b/source/backend/engine/CarlaEnginePorts.cpp @@ -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); diff --git a/source/backend/plugin/CarlaPluginInternal.cpp b/source/backend/plugin/CarlaPluginInternal.cpp index 27005bed5..2de1a7482 100644 --- a/source/backend/plugin/CarlaPluginInternal.cpp +++ b/source/backend/plugin/CarlaPluginInternal.cpp @@ -173,11 +173,7 @@ void PluginEventData::clear() noexcept } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH - if (cvSourcePorts != nullptr) - { - delete cvSourcePorts; - cvSourcePorts = nullptr; - } + cvSourcePorts = nullptr; #endif } diff --git a/source/backend/plugin/CarlaPluginNative.cpp b/source/backend/plugin/CarlaPluginNative.cpp index 0ee60dd83..4125731aa 100644 --- a/source/backend/plugin/CarlaPluginNative.cpp +++ b/source/backend/plugin/CarlaPluginNative.cpp @@ -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)); diff --git a/source/modules/water/processors/AudioProcessor.cpp b/source/modules/water/processors/AudioProcessor.cpp index 5ad3870e1..e8e09a2fc 100644 --- a/source/modules/water/processors/AudioProcessor.cpp +++ b/source/modules/water/processors/AudioProcessor.cpp @@ -87,6 +87,7 @@ void AudioProcessor::suspendProcessing (const bool shouldBeSuspended) } void AudioProcessor::reset() {} +void AudioProcessor::reconfigure() {} uint AudioProcessor::getTotalNumInputChannels(ChannelType t) const noexcept { diff --git a/source/modules/water/processors/AudioProcessor.h b/source/modules/water/processors/AudioProcessor.h index 6c9f249cc..78ad04530 100644 --- a/source/modules/water/processors/AudioProcessor.h +++ b/source/modules/water/processors/AudioProcessor.h @@ -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. diff --git a/source/modules/water/processors/AudioProcessorGraph.h b/source/modules/water/processors/AudioProcessorGraph.h index 151277e22..a6528f0f1 100644 --- a/source/modules/water/processors/AudioProcessorGraph.h +++ b/source/modules/water/processors/AudioProcessorGraph.h @@ -389,6 +389,7 @@ private: bool isPrepared, needsReorder; CarlaRecursiveMutex reorderMutex; +public: void clearRenderingSequence(); void buildRenderingSequence(); bool isAnInputTo (uint32 possibleInputId, uint32 possibleDestinationId, int recursionCheck) const;