Browse Source

libjack: midi-in is working

tags/1.9.8
falkTX 7 years ago
parent
commit
0ec86ec2ff
5 changed files with 141 additions and 20 deletions
  1. +1
    -7
      resources/ui/carla_add_jack.ui
  2. +1
    -0
      source/backend/engine/CarlaEngineBridge.cpp
  3. +55
    -1
      source/libjack/libjack.cpp
  4. +26
    -0
      source/libjack/libjack.hpp
  5. +58
    -12
      source/libjack/libjack_midi.cpp

+ 1
- 7
resources/ui/carla_add_jack.ui View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>414</width>
<width>418</width>
<height>306</height>
</rect>
</property>
@@ -314,9 +314,6 @@
</item>
<item row="0" column="6">
<widget class="QLabel" name="label_7">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>MIDI inputs:</string>
</property>
@@ -327,9 +324,6 @@
</item>
<item row="0" column="7">
<widget class="QSpinBox" name="sb_midi_ins">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>1</number>
</property>


+ 1
- 0
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -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<size; ++i)


+ 55
- 1
source/libjack/libjack.cpp View File

@@ -89,6 +89,8 @@ public:
: fServer(this),
fAudioPoolCopy(nullptr),
fAudioTmpBuf(nullptr),
fMidiBufferIn(true),
fMidiBufferOut(false),
fIsOffline(false),
fLastPingTime(-1),
fRealtimeThread(this),
@@ -198,6 +200,9 @@ private:
float* fAudioPoolCopy;
float* fAudioTmpBuf;

JackMidiPortBuffer fMidiBufferIn;
JackMidiPortBuffer fMidiBufferOut;

char fBaseNameAudioPool[6+1];
char fBaseNameRtClientControl[6+1];
char fBaseNameNonRtClientControl[6+1];
@@ -448,9 +453,42 @@ bool CarlaJackAppClient::handleRtData()
case kPluginBridgeRtClientControlEventMidiProgram:
case kPluginBridgeRtClientControlEventAllSoundOff:
case kPluginBridgeRtClientControlEventAllNotesOff:
case kPluginBridgeRtClientMidiEvent:
break;

case kPluginBridgeRtClientMidiEvent: {
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t port(fShmRtClientControl.readByte());
const uint8_t size(fShmRtClientControl.readByte());
CARLA_SAFE_ASSERT_BREAK(size > 0);

if (size > JackMidiPortBuffer::kMaxEventSize || ! fRealtimeThreadMutex.tryLock())
{
for (uint8_t i=0; i<size; ++i)
fShmRtClientControl.readByte();
break;
}

if (fMidiBufferIn.count < JackMidiPortBuffer::kMaxEventCount &&
fMidiBufferIn.bufferPoolPos + size < JackMidiPortBuffer::kBufferPoolSize)
{
jack_midi_event_t& ev(fMidiBufferIn.events[fMidiBufferIn.count++]);

ev.time = time;
ev.size = size;
ev.buffer = fMidiBufferIn.bufferPool + fMidiBufferIn.bufferPoolPos;
fMidiBufferIn.bufferPoolPos += size;

for (uint8_t i=0; i<size; ++i)
ev.buffer[i] = fShmRtClientControl.readByte();
}

fRealtimeThreadMutex.unlock(true);

// TODO multiple midi ports
(void)port;
break;
}

case kPluginBridgeRtClientProcess: {
// FIXME - lock if offline
const CarlaMutexTryLocker cmtl(fRealtimeThreadMutex);
@@ -578,6 +616,19 @@ bool CarlaJackAppClient::handleRtData()
if (needsTmpBufClear)
FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);

// set midi buffers
if (jclient->midiIns.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);
}


+ 26
- 0
source/libjack/libjack.hpp View File

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


+ 58
- 12
source/libjack/libjack_midi.cpp View File

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


Loading…
Cancel
Save