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