Browse Source

carla-lv2: Pass midi events from plugin directly to host

tags/1.9.7
falkTX 10 years ago
parent
commit
27d697f454
1 changed files with 91 additions and 94 deletions
  1. +91
    -94
      source/plugin/carla-lv2.cpp

+ 91
- 94
source/plugin/carla-lv2.cpp View File

@@ -195,7 +195,7 @@ public:
fHandle = fDescriptor->instantiate(&fHost);
CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);

carla_zeroStructs(fMidiEvents, kMaxMidiEvents*2);
carla_zeroStructs(fMidiEvents, kMaxMidiEvents);
carla_zeroStruct(fTimeInfo);

// hosts may not send all values, resulting on some invalid data
@@ -259,34 +259,13 @@ public:
fIsOffline = (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f);

if (frames == 0)
{
updateParameterOutputs();
return;
}

// Check for updated parameters
float curValue;
return updateParameterOutputs();

for (uint32_t i=0; i < fPorts.paramCount; ++i)
{
if (fPorts.paramsOut[i])
continue;

CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr)

curValue = *fPorts.paramsPtr[i];

if (carla_isEqual(fPorts.paramsLast[i], curValue))
continue;

fPorts.paramsLast[i] = curValue;
fDescriptor->set_parameter_value(fHandle, i, curValue);
}

if (fDescriptor->midiIns > 0 || fDescriptor->midiOuts > 0 || (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) != 0)
// cache midi events and time information
if (fDescriptor->midiIns > 0 || (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) != 0)
{
fMidiEventCount = 0;
carla_zeroStructs(fMidiEvents, kMaxMidiEvents*2);
carla_zeroStructs(fMidiEvents, kMaxMidiEvents);

if (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME)
{
@@ -490,24 +469,59 @@ public:
continue;
if (event->time.frames >= frames)
break;
if (fMidiEventCount >= kMaxMidiEvents*2)
if (fMidiEventCount >= kMaxMidiEvents)
break;

const uint8_t* const data((const uint8_t*)(event + 1));

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.port = (uint8_t)i;
nativeEvent.size = (uint8_t)event->body.size;
nativeEvent.time = (uint32_t)event->time.frames;

for (uint32_t j=0; j < event->body.size; ++j)
uint32_t j=0;
for (uint32_t size=event->body.size; j<size; ++j)
nativeEvent.data[j] = data[j];
for (; j<4; ++j)
nativeEvent.data[j] = 0;
}
}
}

// init midi out data
if (fDescriptor->midiOuts > 0)
{
for (uint32_t i=0, size=fDescriptor->midiOuts; i<size; ++i)
{
LV2_Atom_Sequence* const seq(fPorts.midiOuts[i]);
CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr);

Ports::MidiOutData& mData(fPorts.midiOutData[i]);
mData.capacity = seq->atom.size;
mData.offset = 0;
}
}

// Check for updated parameters
float curValue;

for (uint32_t i=0; i < fPorts.paramCount; ++i)
{
if (fPorts.paramsOut[i])
continue;

CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr)

curValue = *fPorts.paramsPtr[i];

if (carla_isEqual(fPorts.paramsLast[i], curValue))
continue;

fPorts.paramsLast[i] = curValue;
fDescriptor->set_parameter_value(fHandle, i, curValue);
}

// FIXME
fDescriptor->process(fHandle, const_cast<float**>(fPorts.audioIns), fPorts.audioOuts, frames, fMidiEvents, fMidiEventCount);

@@ -566,60 +580,6 @@ public:
}

updateParameterOutputs();

if (fDescriptor->midiOuts > 0)
{
uint32_t capacities[fDescriptor->midiOuts];
uint32_t offsets [fDescriptor->midiOuts];

for (uint32_t i=0, size=fDescriptor->midiOuts; i<size; ++i)
{
LV2_Atom_Sequence* const seq(fPorts.midiOuts[i]);
CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr);

capacities[i] = seq->atom.size;
offsets [i] = 0;
}

LV2_Atom_Event* aev;
uint32_t size;

// reverse lookup MIDI events
for (uint32_t i = (kMaxMidiEvents*2)-1; i >= fMidiEventCount; --i)
{
if (fMidiEvents[i].data[0] == 0)
break;

NativeMidiEvent& nativeEvent(fMidiEvents[i]);

const uint8_t port(nativeEvent.port);
CARLA_SAFE_ASSERT_CONTINUE(nativeEvent.port < fDescriptor->midiOuts);

LV2_Atom_Sequence* const seq(fPorts.midiOuts[port]);
CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr);

if (sizeof(LV2_Atom_Event) + nativeEvent.size > capacities[port] - offsets[port])
continue;

if (offsets[port] == 0)
{
seq->atom.size = 0;
seq->atom.type = fURIs.atomSequence;
seq->body.unit = 0;
seq->body.pad = 0;
}

aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq) + offsets[port]);
aev->time.frames = nativeEvent.time;
aev->body.size = nativeEvent.size;
aev->body.type = fURIs.midiEvent;
std::memcpy(LV2_ATOM_BODY(&aev->body), nativeEvent.data, nativeEvent.size);

size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + nativeEvent.size);
offsets[port] += size;
seq->atom.size += size;
}
}
}

// -------------------------------------------------------------------
@@ -936,20 +896,39 @@ protected:
{
CARLA_SAFE_ASSERT_RETURN(fDescriptor->midiOuts > 0, false);
CARLA_SAFE_ASSERT_RETURN(event != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false);
CARLA_SAFE_ASSERT_RETURN(event->size > 0, false);

// reverse-find first free event, and put it there
for (uint32_t i=(kMaxMidiEvents*2)-1; i > fMidiEventCount; --i)
{
if (fMidiEvents[i].data[0] != 0)
continue;
const uint8_t port(event->port);
CARLA_SAFE_ASSERT_RETURN(port < fDescriptor->midiOuts, false);

std::memcpy(&fMidiEvents[i], event, sizeof(NativeMidiEvent));
return true;
LV2_Atom_Sequence* const seq(fPorts.midiOuts[port]);
CARLA_SAFE_ASSERT_RETURN(seq != nullptr, false);

Ports::MidiOutData& mData(fPorts.midiOutData[port]);

if (sizeof(LV2_Atom_Event) + event->size > mData.capacity - mData.offset)
return false;

if (mData.offset == 0)
{
seq->atom.size = 0;
seq->atom.type = fURIs.atomSequence;
seq->body.unit = 0;
seq->body.pad = 0;
}

carla_stdout("NativePlugin::handleWriteMidiEvent(%p) - buffer full", event);
return false;
LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq) + mData.offset);

aev->time.frames = event->time;
aev->body.size = event->size;
aev->body.type = fURIs.midiEvent;
std::memcpy(LV2_ATOM_BODY(&aev->body), event->data, event->size);

const uint32_t size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + event->size);
mData.offset += size;
seq->atom.size += size;

return true;
}

void handleUiParameterChanged(const uint32_t index, const float value) const
@@ -1041,7 +1020,7 @@ private:
LV2_Program_Descriptor fProgramDesc;

uint32_t fMidiEventCount;
NativeMidiEvent fMidiEvents[kMaxMidiEvents*2];
NativeMidiEvent fMidiEvents[kMaxMidiEvents];
NativeTimeInfo fTimeInfo;

// Lv2 host data
@@ -1157,8 +1136,19 @@ private:
} fUI;

struct Ports {
// need to save current state
struct MidiOutData {
uint32_t capacity;
uint32_t offset;

MidiOutData()
: capacity(0),
offset(0) {}
};

const LV2_Atom_Sequence** eventsIn;
/* */ LV2_Atom_Sequence** midiOuts;
/* */ MidiOutData* midiOutData;
const float** audioIns;
/* */ float** audioOuts;
float* freewheel;
@@ -1192,6 +1182,12 @@ private:
midiOuts = nullptr;
}

if (midiOutData != nullptr)
{
delete[] midiOutData;
midiOutData = nullptr;
}

if (audioIns != nullptr)
{
delete[] audioIns;
@@ -1243,6 +1239,7 @@ private:
if (desc->midiOuts > 0)
{
midiOuts = new LV2_Atom_Sequence*[desc->midiOuts];
midiOutData = new MidiOutData[desc->midiOuts];

for (uint32_t i=0; i < desc->midiOuts; ++i)
midiOuts[i] = nullptr;


Loading…
Cancel
Save