| @@ -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; | |||