From d2501b170930b9bc3edd0225142795c9f89f454b Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 15 Jan 2020 14:16:09 +0000 Subject: [PATCH] Make CV control stuff work with JACK, finally Signed-off-by: falkTX --- source/backend/CarlaEngine.hpp | 12 +- source/backend/engine/CarlaEngineJack.cpp | 192 +++++++++++++++++++-- source/backend/engine/CarlaEnginePorts.cpp | 18 +- source/backend/engine/CarlaEnginePorts.hpp | 10 +- 4 files changed, 186 insertions(+), 46 deletions(-) diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index f62e02403..2c122de6b 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -646,16 +646,16 @@ public: virtual bool removeCVSource(uint32_t portIndexOffset); /*! - * Set value range for a CV port. + * Get events and add them to an event port. + * FIXME needs a better name... */ - bool setCVSourceRange(uint32_t portIndexOffset, float minimum, float maximum); + virtual void initPortBuffers(const float* const* buffers, uint32_t frames, + bool sampleAccurate, CarlaEngineEventPort* eventPort); /*! - * Get events and add them to an event port. - * FIXME needs a better name... + * Set value range for a CV port. */ - void initPortBuffers(const float* const* buffers, uint32_t frames, - bool sampleAccurate, CarlaEngineEventPort* eventPort); + bool setCVSourceRange(uint32_t portIndexOffset, float minimum, float maximum); #ifndef DOXYGEN protected: diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 41261fce9..31fe544c0 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -301,6 +301,8 @@ public: fJackPort(jackPort), fJackBuffer(nullptr), fRetEvent(kFallbackJackEngineEvent), + fCvSourceEvents(nullptr), + fCvSourceEventCount(0), kDeletionCallback(delCallback) { carla_debug("CarlaEngineJackEventPort::CarlaEngineJackEventPort(%s, %p, %p)", bool2str(isInputPort), jackClient, jackPort); @@ -340,6 +342,9 @@ public: if (fJackPort == nullptr) return CarlaEngineEventPort::initBuffer(); + fCvSourceEvents = nullptr; + fCvSourceEventCount = 0; + try { fJackBuffer = jackbridge_port_get_buffer(fJackPort, kClient.getEngine().getBufferSize()); } @@ -352,6 +357,12 @@ public: jackbridge_midi_clear_buffer(fJackBuffer); } + void setCvSourceEvents(EngineEvent* const events, const uint32_t eventCount) noexcept + { + fCvSourceEvents = events; + fCvSourceEventCount = eventCount; + } + uint32_t getEventCount() const noexcept override { if (fJackPort == nullptr) @@ -361,7 +372,7 @@ public: CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, 0); try { - return jackbridge_midi_get_event_count(fJackBuffer); + return jackbridge_midi_get_event_count(fJackBuffer) + fCvSourceEventCount; } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_get_event_count", 0); } @@ -378,6 +389,11 @@ public: const EngineEvent& getEventUnchecked(uint32_t index) const noexcept override { + if (index < fCvSourceEventCount) + return fCvSourceEvents[index]; + + index -= fCvSourceEventCount; + jack_midi_event_t jackEvent; bool test = false; @@ -487,6 +503,9 @@ private: mutable EngineEvent fRetEvent; + EngineEvent* fCvSourceEvents; + uint32_t fCvSourceEventCount; + JackPortDeletionCallback* const kDeletionCallback; friend class CarlaEngineJackClient; @@ -501,16 +520,132 @@ private: class CarlaEngineJackCVSourcePorts : public CarlaEngineCVSourcePorts { public: - CarlaEngineJackCVSourcePorts() - : CarlaEngineCVSourcePorts() + CarlaEngineJackCVSourcePorts(const bool useClient) + : CarlaEngineCVSourcePorts(), + fUseClient(useClient), + fBuffer(nullptr), + fBufferToDeleteLater(nullptr) {} - CarlaRecursiveMutex& getMutex() noexcept + ~CarlaEngineJackCVSourcePorts() override + { + if (fBufferToDeleteLater != nullptr) + { + delete[] fBufferToDeleteLater; + fBufferToDeleteLater = nullptr; + } + } + + bool addCVSource(CarlaEngineCVPort* const port, const uint32_t portIndexOffset) override + { + if (! fUseClient) + return CarlaEngineCVSourcePorts::addCVSource(port, portIndexOffset); + + const CarlaRecursiveMutexLocker crml(pData->rmutex); + + if (! CarlaEngineCVSourcePorts::addCVSource(port, portIndexOffset)) + return false; + + if (pData->cvs.size() == 1 && fBuffer == nullptr) + { + EngineEvent* const buffer = new EngineEvent[kMaxEngineEventInternalCount]; + carla_zeroStructs(buffer, kMaxEngineEventInternalCount); + + fBuffer = buffer; + } + + return true; + } + + bool removeCVSource(const uint32_t portIndexOffset) override + { + if (! fUseClient) + return CarlaEngineCVSourcePorts::removeCVSource(portIndexOffset); + + const CarlaRecursiveMutexLocker crml(pData->rmutex); + + if (! CarlaEngineCVSourcePorts::removeCVSource(portIndexOffset)) + return false; + + if (pData->cvs.size() == 0 && fBuffer != nullptr) + { + if (fBufferToDeleteLater != nullptr) + delete[] fBufferToDeleteLater; + + fBufferToDeleteLater = fBuffer; + fBuffer = nullptr; + } + + return true; + } + + void initPortBuffers(const float* const* const buffers, + const uint32_t frames, + const bool sampleAccurate, + CarlaEngineEventPort* const eventPort) override + { + if (! fUseClient) + return CarlaEngineCVSourcePorts::initPortBuffers(buffers, frames, sampleAccurate, eventPort); + + CARLA_SAFE_ASSERT_RETURN(buffers != nullptr,); + CARLA_SAFE_ASSERT_RETURN(eventPort != nullptr,); + + const CarlaRecursiveMutexTryLocker crmtl(pData->rmutex); + + if (! crmtl.wasLocked()) + return; + + const int numCVs = pData->cvs.size(); + + if (numCVs == 0) + return; + + EngineEvent* const buffer = fBuffer; + CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); + + uint32_t eventCount = 0; + float v, min, max; + + for (int i = 0; i < numCVs && eventCount < kMaxEngineEventInternalCount; ++i) + { + CarlaEngineEventCV& ecv(pData->cvs.getReference(i)); + CARLA_SAFE_ASSERT_CONTINUE(ecv.cvPort != nullptr); + CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); + + float previousValue = ecv.previousValue; + ecv.cvPort->getRange(min, max); + + v = buffers[i][0]; + + if (carla_isNotEqual(v, previousValue)) + { + previousValue = v; + + EngineEvent& event(buffer[eventCount++]); + + event.type = kEngineEventTypeControl; + event.time = frames-1U; + event.channel = kEngineEventNonMidiChannel; + + event.ctrl.type = kEngineControlEventTypeParameter; + event.ctrl.param = static_cast(i); + event.ctrl.value = carla_fixedValue(0.0f, 1.0f, (v - min) / (max - min)); + } + + ecv.previousValue = previousValue; + } + + if (eventCount != 0) + if (CarlaEngineJackEventPort* const jackEventPort = dynamic_cast(eventPort)) + jackEventPort->setCvSourceEvents(buffer, eventCount); + } + + CarlaRecursiveMutex& getMutex() const noexcept { return pData->rmutex; } - uint32_t getPortCount() const + uint32_t getPortCount() const noexcept { return static_cast(pData->cvs.size()); } @@ -526,6 +661,11 @@ public: pData->graph = graph; pData->plugin = plugin; } + +private: + const bool fUseClient; + EngineEvent* fBuffer; + EngineEvent* fBufferToDeleteLater; }; #endif @@ -549,7 +689,7 @@ public: fCVPorts(), fEventPorts(), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH - fCVSourcePorts(), + fCVSourcePorts(fUseClient), #endif fPreRenameMutex(), fPreRenameConnections() @@ -2744,8 +2884,16 @@ private: CarlaEngineJackCVSourcePorts& cvSourcePorts(client->getCVSourcePorts()); const CarlaRecursiveMutexTryLocker crmtl(cvSourcePorts.getMutex(), fFreewheel); + // const CarlaRecursiveMutexLocker crml(cvSourcePorts.getMutex()); #endif + /* + const uint32_t audioInCount = client->getPortCount(kEnginePortTypeAudio, true); + const uint32_t audioOutCount = client->getPortCount(kEnginePortTypeAudio, false); + const uint32_t cvInCount = client->getPortCount(kEnginePortTypeCV, true); + const uint32_t cvOutCount = client->getPortCount(kEnginePortTypeCV, false); + */ + const uint32_t audioInCount = plugin->getAudioInCount(); const uint32_t audioOutCount = plugin->getAudioOutCount(); const uint32_t cvInCount = plugin->getCVInCount(); @@ -2763,35 +2911,49 @@ private: for (uint32_t i=0; i < audioInCount; ++i) { - CarlaEngineAudioPort* const port(plugin->getAudioInPort(i)); - audioIn[i] = port->getBuffer(); + if (CarlaEngineAudioPort* const port = plugin->getAudioInPort(i)) + audioIn[i] = port->getBuffer(); + else + audioIn[i] = nullptr; } for (uint32_t i=0; i < audioOutCount; ++i) { - CarlaEngineAudioPort* const port(plugin->getAudioOutPort(i)); - audioOut[i] = port->getBuffer(); + if (CarlaEngineAudioPort* const port = plugin->getAudioOutPort(i)) + audioOut[i] = port->getBuffer(); + else + audioOut[i] = nullptr; } for (uint32_t i=0; i < cvInCount; ++i) { - CarlaEngineCVPort* const port(plugin->getCVInPort(i)); - cvIn[i] = port->getBuffer(); - CARLA_SAFE_ASSERT(cvIn[i] != nullptr); + if (CarlaEngineCVPort* const port = plugin->getCVInPort(i)) + cvIn[i] = port->getBuffer(); + else + cvIn[i] = nullptr; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH for (uint32_t i=cvInCount, j=0; j < cvsInCount; ++i, ++j) { if (CarlaEngineCVPort* const port = cvSourcePorts.getPort(j)) + { + port->initBuffer(); cvIn[i] = port->getBuffer(); + } + else + { + cvIn[i] = nullptr; + } } #endif for (uint32_t i=0; i < cvOutCount; ++i) { - CarlaEngineCVPort* const port(plugin->getCVOutPort(i)); - cvOut[i] = port->getBuffer(); + if (CarlaEngineCVPort* const port = plugin->getCVOutPort(i)) + cvOut[i] = port->getBuffer(); + else + cvOut[i] = nullptr; } float inPeaks[2] = { 0.0f }; diff --git a/source/backend/engine/CarlaEnginePorts.cpp b/source/backend/engine/CarlaEnginePorts.cpp index a39fb099b..6eee6601e 100644 --- a/source/backend/engine/CarlaEnginePorts.cpp +++ b/source/backend/engine/CarlaEnginePorts.cpp @@ -1,6 +1,6 @@ /* * Carla Plugin Host - * Copyright (C) 2011-2019 Filipe Coelho + * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -354,11 +354,6 @@ bool CarlaEngineCVSourcePorts::addCVSource(CarlaEngineCVPort* const port, const if (pData->graph != nullptr && pData->plugin != nullptr) pData->graph->reconfigureForCV(pData->plugin, static_cast(pData->cvs.size()-1), true); - - /* - if (pData->buffer == nullptr) - pData->buffer = new EngineEvent[kMaxEngineEventInternalCount]; - */ } return true; @@ -390,12 +385,6 @@ bool CarlaEngineCVSourcePorts::removeCVSource(const uint32_t portIndexOffset) } } - if (pData->buffer != nullptr) - { - delete[] pData->buffer; - pData->buffer = nullptr; - } - carla_stdout("did NOT found cv source to remove %u", portIndexOffset); return false; } @@ -439,10 +428,6 @@ void CarlaEngineCVSourcePorts::initPortBuffers(const float* const* const buffers EngineEvent* const buffer = eventPort->fBuffer; CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,); - /* - if (buffer == nullptr) - return; - */ uint32_t eventCount = 0; float v, min, max; @@ -462,6 +447,7 @@ void CarlaEngineCVSourcePorts::initPortBuffers(const float* const* const buffers { CarlaEngineEventCV& ecv(pData->cvs.getReference(i)); CARLA_SAFE_ASSERT_CONTINUE(ecv.cvPort != nullptr); + CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); float previousValue = ecv.previousValue; ecv.cvPort->getRange(min, max); diff --git a/source/backend/engine/CarlaEnginePorts.hpp b/source/backend/engine/CarlaEnginePorts.hpp index 6a9d7abfe..25340a810 100644 --- a/source/backend/engine/CarlaEnginePorts.hpp +++ b/source/backend/engine/CarlaEnginePorts.hpp @@ -1,6 +1,6 @@ /* * Carla Plugin Host - * Copyright (C) 2011-2019 Filipe Coelho + * Copyright (C) 2011-2020 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -34,7 +34,6 @@ struct CarlaEngineEventCV { struct CarlaEngineCVSourcePorts::ProtectedData { CarlaRecursiveMutex rmutex; - EngineEvent* buffer; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH PatchbayGraph* graph; CarlaPlugin* plugin; @@ -43,7 +42,6 @@ struct CarlaEngineCVSourcePorts::ProtectedData { ProtectedData() noexcept : rmutex(), - buffer(nullptr), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH graph(nullptr), plugin(nullptr), @@ -60,12 +58,6 @@ struct CarlaEngineCVSourcePorts::ProtectedData { cvs.clear(); } - - if (buffer != nullptr) - { - delete[] buffer; - buffer = nullptr; - } } CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData)