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


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

@@ -1094,6 +1094,7 @@ protected:
const uint8_t size(fShmRtClientControl.readByte()); const uint8_t size(fShmRtClientControl.readByte());
CARLA_SAFE_ASSERT_BREAK(size > 0); CARLA_SAFE_ASSERT_BREAK(size > 0);


// FIXME variable-size stack
uint8_t data[size]; uint8_t data[size];


for (uint8_t i=0; i<size; ++i) for (uint8_t i=0; i<size; ++i)


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

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


JackMidiPortBuffer fMidiBufferIn;
JackMidiPortBuffer fMidiBufferOut;

char fBaseNameAudioPool[6+1]; char fBaseNameAudioPool[6+1];
char fBaseNameRtClientControl[6+1]; char fBaseNameRtClientControl[6+1];
char fBaseNameNonRtClientControl[6+1]; char fBaseNameNonRtClientControl[6+1];
@@ -448,9 +453,42 @@ bool CarlaJackAppClient::handleRtData()
case kPluginBridgeRtClientControlEventMidiProgram: case kPluginBridgeRtClientControlEventMidiProgram:
case kPluginBridgeRtClientControlEventAllSoundOff: case kPluginBridgeRtClientControlEventAllSoundOff:
case kPluginBridgeRtClientControlEventAllNotesOff: case kPluginBridgeRtClientControlEventAllNotesOff:
case kPluginBridgeRtClientMidiEvent:
break; 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: { case kPluginBridgeRtClientProcess: {
// FIXME - lock if offline // FIXME - lock if offline
const CarlaMutexTryLocker cmtl(fRealtimeThreadMutex); const CarlaMutexTryLocker cmtl(fRealtimeThreadMutex);
@@ -578,6 +616,19 @@ bool CarlaJackAppClient::handleRtData()
if (needsTmpBufClear) if (needsTmpBufClear)
FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize); 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); jclient->processCb(fServer.bufferSize, jclient->processCbPtr);


if (fNumPorts.audioOuts > 0) if (fNumPorts.audioOuts > 0)
@@ -612,6 +663,9 @@ bool CarlaJackAppClient::handleRtData()
FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts); FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);
} }


fMidiBufferIn.count = 0;
fMidiBufferIn.bufferPoolPos = 0;

if (fNumPorts.midiOuts > 0) if (fNumPorts.midiOuts > 0)
carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize); carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);
} }


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

@@ -59,6 +59,32 @@ class CarlaJackAppClient;
struct JackClientState; struct JackClientState;
struct JackServerState; 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 { struct JackPortState {
char* name; char* name;
char* fullname; 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. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/ */


// need to include this first
#include "libjack.hpp" #include "libjack.hpp"


CARLA_BACKEND_USE_NAMESPACE CARLA_BACKEND_USE_NAMESPACE
@@ -23,43 +22,90 @@ CARLA_BACKEND_USE_NAMESPACE
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


CARLA_EXPORT 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 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 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 CARLA_EXPORT
void jack_midi_reset_buffer(void*)
void jack_midi_reset_buffer(void* buf)
{ {
jack_midi_clear_buffer(buf);
} }


CARLA_EXPORT CARLA_EXPORT
size_t jack_midi_max_event_size(void*) size_t jack_midi_max_event_size(void*)
{ {
return 0;
return JackMidiPortBuffer::kMaxEventSize;
} }


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


Loading…
Cancel
Save