diff --git a/resources/ui/carla_add_jack.ui b/resources/ui/carla_add_jack.ui index 9945ab187..6fd3a5a33 100644 --- a/resources/ui/carla_add_jack.ui +++ b/resources/ui/carla_add_jack.ui @@ -6,7 +6,7 @@ 0 0 - 414 + 418 306 @@ -314,9 +314,6 @@ - - false - MIDI inputs: @@ -327,9 +324,6 @@ - - false - 1 diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index 4e8cc63e2..c9a01e155 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -1094,6 +1094,7 @@ protected: const uint8_t size(fShmRtClientControl.readByte()); CARLA_SAFE_ASSERT_BREAK(size > 0); + // FIXME variable-size stack uint8_t data[size]; for (uint8_t i=0; i 0); + + if (size > JackMidiPortBuffer::kMaxEventSize || ! fRealtimeThreadMutex.tryLock()) + { + for (uint8_t i=0; imidiIns.count() > 0) + { + if (JackPortState* const jport = jclient->midiIns.getFirst(nullptr)) + jport->buffer = &fMidiBufferIn; + } + + if (jclient->midiOuts.count() > 0) + { + if (JackPortState* const jport = jclient->midiOuts.getFirst(nullptr)) + jport->buffer = &fMidiBufferOut; + } + jclient->processCb(fServer.bufferSize, jclient->processCbPtr); if (fNumPorts.audioOuts > 0) @@ -612,6 +663,9 @@ bool CarlaJackAppClient::handleRtData() FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts); } + fMidiBufferIn.count = 0; + fMidiBufferIn.bufferPoolPos = 0; + if (fNumPorts.midiOuts > 0) carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize); } diff --git a/source/libjack/libjack.hpp b/source/libjack/libjack.hpp index 07033279e..e707944f2 100644 --- a/source/libjack/libjack.hpp +++ b/source/libjack/libjack.hpp @@ -59,6 +59,32 @@ class CarlaJackAppClient; struct JackClientState; struct JackServerState; +struct JackMidiPortBuffer { + static const size_t kMaxEventSize = 128; + static const size_t kMaxEventCount = 512; + static const size_t kBufferPoolSize = kMaxEventCount*8; + + uint16_t count; + bool isInput; + jack_midi_event_t* events; + + size_t bufferPoolPos; + jack_midi_data_t* bufferPool; + + JackMidiPortBuffer(const bool input) + : count(0), + isInput(input), + events(new jack_midi_event_t[kMaxEventCount]), + bufferPoolPos(0), + bufferPool(new jack_midi_data_t[kBufferPoolSize]) {} + + ~JackMidiPortBuffer() + { + delete[] events; + delete[] bufferPool; + } +}; + struct JackPortState { char* name; char* fullname; diff --git a/source/libjack/libjack_midi.cpp b/source/libjack/libjack_midi.cpp index b79a7cd6d..fdfd8f6b6 100644 --- a/source/libjack/libjack_midi.cpp +++ b/source/libjack/libjack_midi.cpp @@ -15,7 +15,6 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ -// need to include this first #include "libjack.hpp" CARLA_BACKEND_USE_NAMESPACE @@ -23,43 +22,90 @@ CARLA_BACKEND_USE_NAMESPACE // -------------------------------------------------------------------------------------------------------------------- CARLA_EXPORT -jack_nframes_t jack_midi_get_event_count(void*) +jack_nframes_t jack_midi_get_event_count(void* buf) { - return 0; + JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); + CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, 0); + CARLA_SAFE_ASSERT_RETURN(jmidibuf->isInput, 0); + + return jmidibuf->count; } CARLA_EXPORT -int jack_midi_event_get(jack_midi_event_t*, void*, uint32_t) +int jack_midi_event_get(jack_midi_event_t* ev, void* buf, uint32_t index) { - return ENODATA; + JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); + CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, EFAULT); + CARLA_SAFE_ASSERT_RETURN(jmidibuf->isInput, EFAULT); + CARLA_SAFE_ASSERT_RETURN(index < jmidibuf->count, ENODATA); + + std::memcpy(ev, &jmidibuf->events[index], sizeof(jack_midi_event_t)); + return 0; } CARLA_EXPORT -void jack_midi_clear_buffer(void*) +void jack_midi_clear_buffer(void* buf) { + JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); + CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr,); + CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput,); + + jmidibuf->count = 0; + jmidibuf->bufferPoolPos = 0; + std::memset(jmidibuf->bufferPool, 0, JackMidiPortBuffer::kBufferPoolSize); } CARLA_EXPORT -void jack_midi_reset_buffer(void*) +void jack_midi_reset_buffer(void* buf) { + jack_midi_clear_buffer(buf); } CARLA_EXPORT size_t jack_midi_max_event_size(void*) { - return 0; + return JackMidiPortBuffer::kMaxEventSize; } CARLA_EXPORT -jack_midi_data_t* jack_midi_event_reserve(void*, jack_nframes_t, size_t) +jack_midi_data_t* jack_midi_event_reserve(void* buf, jack_nframes_t frame, size_t size) { - return nullptr; + JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); + CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, nullptr); + CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput, nullptr); + CARLA_SAFE_ASSERT_RETURN(size > 0, nullptr); + + if (jmidibuf->count >= JackMidiPortBuffer::kMaxEventCount) + return nullptr; + if (jmidibuf->bufferPoolPos + size >= JackMidiPortBuffer::kBufferPoolSize) + return nullptr; + + jack_midi_data_t* const jmdata = jmidibuf->bufferPool + jmidibuf->bufferPoolPos; + jmidibuf->bufferPoolPos += size; + + jmidibuf->events[jmidibuf->count++] = { frame, size, jmdata }; + std::memset(jmdata, 0, size); + return jmdata; } CARLA_EXPORT -int jack_midi_event_write(void*, jack_nframes_t, const jack_midi_data_t*, size_t) +int jack_midi_event_write(void* buf, jack_nframes_t frame, const jack_midi_data_t* data, size_t size) { - return ENOBUFS; + JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); + CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, EFAULT); + CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput, EFAULT); + + if (jmidibuf->count >= JackMidiPortBuffer::kMaxEventCount) + return ENOBUFS; + if (jmidibuf->bufferPoolPos + size >= JackMidiPortBuffer::kBufferPoolSize) + return ENOBUFS; + + jack_midi_data_t* const jmdata = jmidibuf->bufferPool + jmidibuf->bufferPoolPos; + jmidibuf->bufferPoolPos += size; + + jmidibuf->events[jmidibuf->count++] = { frame, size, jmdata }; + std::memcpy(jmdata, data, size); + return 0; } CARLA_EXPORT