Browse Source

More LV2 work, instruments working

tags/1.9.4
falkTX 11 years ago
parent
commit
82eed066be
5 changed files with 678 additions and 49 deletions
  1. +3
    -1
      source/backend/plugin/DssiPlugin.cpp
  2. +2
    -0
      source/backend/plugin/LadspaPlugin.cpp
  3. +667
    -44
      source/backend/plugin/Lv2Plugin.cpp
  4. +2
    -0
      source/backend/plugin/NativePlugin.cpp
  5. +4
    -4
      source/backend/plugin/VstPlugin.cpp

+ 3
- 1
source/backend/plugin/DssiPlugin.cpp View File

@@ -864,7 +864,7 @@ public:
// Update data
for (i=0; i < count; ++i)
{
const DSSI_Program_Descriptor* const pdesc = fDssiDescriptor->get_program(fHandle, i);
const DSSI_Program_Descriptor* const pdesc(fDssiDescriptor->get_program(fHandle, i));
CARLA_ASSERT(pdesc != nullptr);
CARLA_ASSERT(pdesc->Name != nullptr);

@@ -938,6 +938,7 @@ public:
void activate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->activate != nullptr)
{
@@ -951,6 +952,7 @@ public:
void deactivate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->deactivate != nullptr)
{


+ 2
- 0
source/backend/plugin/LadspaPlugin.cpp View File

@@ -818,6 +818,7 @@ public:
void activate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->activate != nullptr)
{
@@ -831,6 +832,7 @@ public:
void deactivate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->deactivate != nullptr)
{


+ 667
- 44
source/backend/plugin/Lv2Plugin.cpp View File

@@ -45,10 +45,10 @@ CARLA_BACKEND_START_NAMESPACE
* @defgroup PluginHints Plugin Hints
* @{
*/
const unsigned int PLUGIN_HAS_EXTENSION_OPTIONS = 0x1000; //!< LV2 Plugin has Options extension
const unsigned int PLUGIN_HAS_EXTENSION_PROGRAMS = 0x2000; //!< LV2 Plugin has Programs extension
const unsigned int PLUGIN_HAS_EXTENSION_STATE = 0x4000; //!< LV2 Plugin has State extension
const unsigned int PLUGIN_HAS_EXTENSION_WORKER = 0x8000; //!< LV2 Plugin has Worker extension
const unsigned int PLUGIN_HAS_EXTENSION_OPTIONS = 0x100; //!< LV2 Plugin has Options extension
const unsigned int PLUGIN_HAS_EXTENSION_PROGRAMS = 0x200; //!< LV2 Plugin has Programs extension
const unsigned int PLUGIN_HAS_EXTENSION_STATE = 0x400; //!< LV2 Plugin has State extension
const unsigned int PLUGIN_HAS_EXTENSION_WORKER = 0x800; //!< LV2 Plugin has Worker extension
/**@}*/

/*!
@@ -134,6 +134,14 @@ const uint32_t kFeatureCount = 22;

const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000

enum Lv2PluginGuiType {
PLUGIN_UI_NULL,
PLUGIN_UI_OSC,
PLUGIN_UI_QT,
PLUGIN_UI_PARENT,
PLUGIN_UI_EXTERNAL
};

struct Lv2EventData {
uint32_t type;
uint32_t rindex;
@@ -332,11 +340,11 @@ public:
carla_debug("Lv2Plugin::~Lv2Plugin()");

// close UI
if (fHints & PLUGIN_HAS_GUI)
if (fUi.type != PLUGIN_UI_NULL)
{
showGui(false);

//if (fGui.isOsc)
if (fUi.type == PLUGIN_UI_OSC)
{
// Wait a bit first, then force kill
if (kData->osc.thread.isRunning() && ! kData->osc.thread.wait(kData->engine->getOptions().oscUiTimeout))
@@ -448,7 +456,7 @@ public:
const char* const uri(*it);

if (uri != nullptr)
delete uri;
delete[] uri;
}

fCustomURIDs.clear();
@@ -870,7 +878,7 @@ public:

status = fExt.state->restore(fHandle, carla_lv2_state_retrieve, this, 0, fFeatures);

if (fHandle2)
if (fHandle2 != nullptr)
fExt.state->restore(fHandle, carla_lv2_state_retrieve, this, 0, fFeatures);
}

@@ -939,7 +947,10 @@ public:

void showGui(const bool yesNo) override
{
if (true)
if (fUi.type == PLUGIN_UI_NULL)
return;

if (fUi.type == PLUGIN_UI_OSC)
{
if (yesNo)
{
@@ -957,8 +968,73 @@ public:
if (kData->osc.thread.isRunning() && ! kData->osc.thread.wait(kData->engine->getOptions().oscUiTimeout))
kData->osc.thread.terminate();
}

return;
}

// take some precautions
CARLA_ASSERT(fUi.descriptor != nullptr);
CARLA_ASSERT(fUi.rdfDescriptor == nullptr);

if (fUi.descriptor == nullptr)
return;
if (fUi.rdfDescriptor == nullptr)
return;

if (yesNo)
{
CARLA_ASSERT(fUi.descriptor->instantiate != nullptr);

if (fUi.descriptor->instantiate == nullptr)
return;
}
else
{
CARLA_ASSERT(fUi.handle != nullptr);
CARLA_ASSERT(fUi.descriptor->cleanup != nullptr);

if (fUi.handle == nullptr)
return;
if (fUi.descriptor->cleanup == nullptr)
return;
}

if (fUi.type == PLUGIN_UI_EXTERNAL)
{
if (yesNo)
{
fUi.widget = nullptr;

if (fUi.handle == nullptr)
fUi.handle = fUi.descriptor->instantiate(fUi.descriptor, fRdfDescriptor->URI, fUi.rdfDescriptor->Bundle,
carla_lv2_ui_write_function, this, &fUi.widget, fFeatures);

CARLA_ASSERT(fUi.handle != nullptr);
CARLA_ASSERT(fUi.widget != nullptr);

if (fUi.handle == nullptr || fUi.widget == nullptr)
{
fUi.handle = nullptr;
fUi.widget = nullptr;
kData->engine->callback(CALLBACK_ERROR, fId, 0, 0, 0.0f, "Plugin refused to open its own UI");
kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
return;
}

LV2_EXTERNAL_UI_SHOW((LV2_External_UI_Widget*)fUi.widget);
}
else
{
CARLA_ASSERT(fUi.widget != nullptr);

if (fUi.widget != nullptr)
LV2_EXTERNAL_UI_HIDE((LV2_External_UI_Widget*)fUi.widget);

fUi.descriptor->cleanup(fUi.handle);
fUi.handle = nullptr;
}
}
else // means PLUGIN_UI_PARENT || PLUGIN_UI_QT
{
if (yesNo)
{
@@ -966,37 +1042,48 @@ public:
{
// TODO
CarlaPluginGui::Options guiOptions;
guiOptions.parented = false;
guiOptions.parented = (fUi.type == PLUGIN_UI_PARENT);
guiOptions.resizable = true;

kData->gui = new CarlaPluginGui(kData->engine, this, guiOptions);
}

//void* const ptr = kData->gui->getContainerWinId();

// open
if (true)
if (fUi.type == PLUGIN_UI_PARENT)
{
kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName).toUtf8().constData());
kData->gui->show();
fFeatures[kFeatureIdUiParent]->data = kData->gui->getContainerWinId();
fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
}
else

fUi.widget = nullptr;

if (fUi.handle == nullptr)
fUi.handle = fUi.descriptor->instantiate(fUi.descriptor, fRdfDescriptor->URI, fUi.rdfDescriptor->Bundle,
carla_lv2_ui_write_function, this, &fUi.widget, fFeatures);

CARLA_ASSERT(fUi.handle != nullptr);
CARLA_ASSERT(fUi.widget != nullptr);

if (fUi.handle == nullptr || fUi.widget == nullptr)
{
if (kData->gui != nullptr)
{
kData->gui->close();
delete kData->gui;
kData->gui = nullptr;
}
fUi.handle = nullptr;
fUi.widget = nullptr;
kData->gui->close();
delete kData->gui;
kData->gui = nullptr;

kData->engine->callback(CALLBACK_ERROR, fId, 0, 0, 0.0f, "Plugin refused to open its own UI");
kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
kData->engine->callback(CALLBACK_SHOW_GUI, fId, -1, 0, 0.0f, nullptr);
return;
}

kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName));
kData->gui->show();
}
else
{
// close here
fUi.descriptor->cleanup(fUi.handle);
fUi.handle = nullptr;

if (kData->gui != nullptr)
{
@@ -1006,12 +1093,25 @@ public:
}
}
}

//fGui.isVisible = yesNo;
}

void idleGui() override
{
if (fUi.handle != nullptr && fUi.descriptor != nullptr)
{
if (fUi.type == PLUGIN_UI_EXTERNAL && fUi.widget != nullptr)
LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUi.widget);

if (fExt.uiidle != nullptr)
{
if (fExt.uiidle->idle(fUi.handle) != 0)
{
showGui(false);
kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
}
}
}

CarlaPlugin::idleGui();
}

@@ -1182,7 +1282,7 @@ public:
{
fEventsIn.data[j].type = CARLA_EVENT_DATA_ATOM;
fEventsIn.data[j].atom = (LV2_Atom_Sequence*)std::malloc(sizeof(LV2_Atom_Sequence) + MAX_EVENT_BUFFER);
fEventsIn.data[j].atom->atom.size = sizeof(LV2_Atom_Sequence_Body);
fEventsIn.data[j].atom->atom.size = 0;
fEventsIn.data[j].atom->atom.type = CARLA_URI_MAP_ID_ATOM_SEQUENCE;
fEventsIn.data[j].atom->body.unit = CARLA_URI_MAP_ID_NULL;
fEventsIn.data[j].atom->body.pad = 0;
@@ -1216,7 +1316,7 @@ public:
{
fEventsOut.data[j].type = CARLA_EVENT_DATA_ATOM;
fEventsOut.data[j].atom = (LV2_Atom_Sequence*)std::malloc(sizeof(LV2_Atom_Sequence) + MAX_EVENT_BUFFER);
fEventsOut.data[j].atom->atom.size = sizeof(LV2_Atom_Sequence_Body);
fEventsOut.data[j].atom->atom.size = 0;
fEventsOut.data[j].atom->atom.type = CARLA_URI_MAP_ID_ATOM_SEQUENCE;
fEventsOut.data[j].atom->body.unit = CARLA_URI_MAP_ID_NULL;
fEventsOut.data[j].atom->body.pad = 0;
@@ -1683,7 +1783,7 @@ public:

fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]);

if (fHandle2)
if (fHandle2 != nullptr)
fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]);
}
else
@@ -1691,7 +1791,7 @@ public:
// Port Type not supported, but it's optional anyway
fDescriptor->connect_port(fHandle, i, nullptr);

if (fHandle2)
if (fHandle2 != nullptr)
fDescriptor->connect_port(fHandle2, i, nullptr);
}
}
@@ -1774,12 +1874,105 @@ public:
carla_debug("Lv2Plugin::reload() - end");
}

void reloadPrograms(const bool init) override
{
carla_debug("DssiPlugin::reloadPrograms(%s)", bool2str(init));
uint32_t i, oldCount = kData->midiprog.count;
const int32_t current = kData->midiprog.current;

// Delete old programs
kData->midiprog.clear();

// Query new programs
uint32_t count = 0;
if (fExt.programs != nullptr && fExt.programs->get_program != nullptr && fExt.programs->select_program != nullptr)
{
while (fExt.programs->get_program(fHandle, count))
count++;
}

if (count > 0)
{
kData->midiprog.createNew(count);

// Update data
for (i=0; i < count; ++i)
{
const LV2_Program_Descriptor* const pdesc(fExt.programs->get_program(fHandle, i));
CARLA_ASSERT(pdesc != nullptr);
CARLA_ASSERT(pdesc->name != nullptr);

kData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->bank);
kData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->program);
kData->midiprog.data[i].name = carla_strdup(pdesc->name);
}
}

#ifndef BUILD_BRIDGE
// Update OSC Names
if (kData->engine->isOscControlRegistered())
{
kData->engine->osc_send_control_set_midi_program_count(fId, count);

for (i=0; i < count; ++i)
kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
}
#endif

if (init)
{
if (count > 0)
setMidiProgram(0, false, false, false);
}
else
{
// Check if current program is invalid
bool programChanged = false;

if (count == oldCount+1)
{
// one midi program added, probably created by user
kData->midiprog.current = oldCount;
programChanged = true;
}
else if (current < 0 && count > 0)
{
// programs exist now, but not before
kData->midiprog.current = 0;
programChanged = true;
}
else if (current >= 0 && count == 0)
{
// programs existed before, but not anymore
kData->midiprog.current = -1;
programChanged = true;
}
else if (current >= static_cast<int32_t>(count))
{
// current midi program > count
kData->midiprog.current = 0;
programChanged = true;
}
else
{
// no change
kData->midiprog.current = current;
}

if (programChanged)
setMidiProgram(kData->midiprog.current, true, true, true);

kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
}
}

// -------------------------------------------------------------------
// Plugin processing

void activate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->activate != nullptr)
{
@@ -1793,6 +1986,7 @@ public:
void deactivate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->deactivate != nullptr)
{
@@ -1936,7 +2130,6 @@ public:
case LV2_PORT_DESIGNATION_TIME_SPEED:
setParameterValue(k, timeInfo.playing ? 1.0f : 0.0f, false, false, false);
break;

// BBT
case LV2_PORT_DESIGNATION_TIME_BAR:
if (timeInfo.valid & EngineTimeInfo::ValidBBT)
@@ -1970,31 +2163,436 @@ public:
// --------------------------------------------------------------------------------------------------------
// Event Input and Processing

//if (kData->event.portIn != nullptr)
if (kData->event.portIn != nullptr)
{
}
// ----------------------------------------------------------------------------------------------------
// MIDI Input (External)

if (kData->extNotes.mutex.tryLock())
{
while (midiEventCount < MAX_MIDI_EVENTS && ! kData->extNotes.data.isEmpty())
{
const ExternalMidiNote& note(kData->extNotes.data.getFirst(true));

CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);

uint8_t midiEvent[3] = { 0 };
midiEvent[0] = (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
midiEvent[0] += note.channel;
midiEvent[1] = note.note;
midiEvent[2] = note.velo;

// send to first midi input
for (k=0; k < fEventsIn.count; ++k)
{
if (fEventsIn.data[k].type & CARLA_EVENT_TYPE_MIDI)
{
if (fEventsIn.data[k].type & CARLA_EVENT_DATA_ATOM)
{
const uint32_t evInPadSize(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + 3));

if (evInAtomOffsets[k] + evInPadSize >= MAX_EVENT_BUFFER)
continue;

LV2_Atom_Event* const aev = getLv2AtomEvent(fEventsIn.data[k].atom, evInAtomOffsets[k]);
aev->time.frames = 0;
aev->body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
aev->body.size = 3;
std::memcpy(LV2_ATOM_BODY(&aev->body), midiEvent, 3);

evInAtomOffsets[k] += evInPadSize;
fEventsIn.data[k].atom->atom.size = evInAtomOffsets[k];
}
else if (fEventsIn.data[k].type & CARLA_EVENT_DATA_EVENT)
{
lv2_event_write(&evInEventIters[k], 0, 0, CARLA_URI_MAP_ID_MIDI_EVENT, 3, midiEvent);
}
else if (fEventsIn.data[k].type & CARLA_EVENT_DATA_MIDI_LL)
{
lv2midi_put_event(&evInMidiStates[k], 0, 3, midiEvent);
}

break;
}
}

midiEventCount += 1;
}

kData->extNotes.mutex.unlock();

} // End of MIDI Input (External)

// ----------------------------------------------------------------------------------------------------
// Event Input (System)

bool allNotesOffSent = false;
bool sampleAccurate = (fOptions & PLUGIN_OPTION_FIXED_BUFFER) == 0;

uint32_t time, nEvents = kData->event.portIn->getEventCount();
uint32_t startTime = 0;
uint32_t timeOffset = 0;

uint32_t nextBankId = 0;
if (kData->midiprog.current >= 0 && kData->midiprog.count > 0)
nextBankId = kData->midiprog.data[kData->midiprog.current].bank;

for (i=0; i < nEvents; ++i)
{
const EngineEvent& event = kData->event.portIn->getEvent(i);

time = event.time;

if (time >= frames)
continue;

CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset);

if (time > timeOffset && sampleAccurate)
{
if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset))
{
startTime = 0;
timeOffset = time;
midiEventCount = 0;

if (kData->midiprog.current >= 0 && kData->midiprog.count > 0)
nextBankId = kData->midiprog.data[kData->midiprog.current].bank;
else
nextBankId = 0;

// reset iters
for (i=0; i < fEventsIn.count; ++i)
{
if (fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM)
{
evInAtomOffsets[i] = 0;
fEventsIn.data[i].atom->atom.size = 0;
}
else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_EVENT)
{
lv2_event_buffer_reset(fEventsIn.data[i].event, LV2_EVENT_AUDIO_STAMP, (uint8_t*)(fEventsIn.data[i].event + 1));
lv2_event_begin(&evInEventIters[i], fEventsIn.data[i].event);
}
else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
{
evInMidiStates[i].position = 0;
evInMidiStates[i].midi->event_count = 0;
evInMidiStates[i].midi->size = 0;
}
}
}
else
startTime += timeOffset;
}

// Control change
switch (event.type)
{
case kEngineEventTypeNull:
break;

case kEngineEventTypeControl:
{
const EngineControlEvent& ctrlEvent = event.ctrl;

switch (ctrlEvent.type)
{
case kEngineControlEventTypeNull:
break;

case kEngineControlEventTypeParameter:
{
// Control backend stuff
if (event.channel == kData->ctrlChannel)
{
float value;

if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0)
{
value = ctrlEvent.value;
setDryWet(value, false, false);
postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
continue;
}

if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0)
{
value = ctrlEvent.value*127.0f/100.0f;
setVolume(value, false, false);
postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
continue;
}

if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0)
{
float left, right;
value = ctrlEvent.value/0.5f - 1.0f;

if (value < 0.0f)
{
left = -1.0f;
right = (value*2.0f)+1.0f;
}
else if (value > 0.0f)
{
left = (value*2.0f)-1.0f;
right = 1.0f;
}
else
{
left = -1.0f;
right = 1.0f;
}

setBalanceLeft(left, false, false);
setBalanceRight(right, false, false);
postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
continue;
}
}

// Control plugin parameters
for (k=0; k < kData->param.count; ++k)
{
if (kData->param.data[k].midiChannel != event.channel)
continue;
if (kData->param.data[k].midiCC != ctrlEvent.param)
continue;
if (kData->param.data[k].type != PARAMETER_INPUT)
continue;
if ((kData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
continue;

float value;

if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
{
value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max;
}
else
{
value = kData->param.ranges[i].unnormalizeValue(ctrlEvent.value);

if (kData->param.data[k].hints & PARAMETER_IS_INTEGER)
value = std::rint(value);
}

setParameterValue(k, value, false, false, false);
postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
}

break;
}

case kEngineControlEventTypeMidiBank:
if (event.channel == kData->ctrlChannel && (fOptions & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
nextBankId = ctrlEvent.param;
break;

case kEngineControlEventTypeMidiProgram:
if (event.channel == kData->ctrlChannel && (fOptions & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
{
const uint32_t nextProgramId = ctrlEvent.param;

for (k=0; k < kData->midiprog.count; ++k)
{
if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId)
{
setMidiProgram(k, false, false, false);
postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0f);
break;
}
}
}
break;

case kEngineControlEventTypeAllSoundOff:
if (event.channel == kData->ctrlChannel)
{
if (! allNotesOffSent)
{
sendMidiAllNotesOff();
allNotesOffSent = true;
}

postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0f);
postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0f);
}

if (midiEventCount >= MAX_MIDI_EVENTS)
continue;

if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
{
// TODO

midiEventCount += 1;
}

break;

case kEngineControlEventTypeAllNotesOff:
if (event.channel == kData->ctrlChannel)
{
if (! allNotesOffSent)
{
allNotesOffSent = true;
sendMidiAllNotesOff();
}
}

if (midiEventCount >= MAX_MIDI_EVENTS)
continue;

if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
{
// TODO

midiEventCount += 1;
}

break;
}

break;
}

case kEngineEventTypeMidi:
{
if (midiEventCount >= MAX_MIDI_EVENTS)
continue;

const EngineMidiEvent& midiEvent = event.midi;

uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
uint8_t channel = event.channel;
uint32_t time = sampleAccurate ? startTime : time;

if (MIDI_IS_STATUS_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
continue;
if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
continue;
if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
continue;
if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (fOptions & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
continue;

// Fix bad note-off
if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
status -= 0x10;

for (k=0; k < fEventsIn.count; ++k)
{
if (midiEvent.port != k)
continue;

if (fEventsIn.data[k].type & CARLA_EVENT_TYPE_MIDI)
{
if (fEventsIn.data[k].type & CARLA_EVENT_DATA_ATOM)
{
const uint32_t evInPadSize(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + midiEvent.size));

if (evInAtomOffsets[k] + evInPadSize >= MAX_EVENT_BUFFER)
continue;

LV2_Atom_Event* const aev = getLv2AtomEvent(fEventsIn.data[k].atom, evInAtomOffsets[k]);
aev->time.frames = time;
aev->body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
aev->body.size = midiEvent.size;
std::memcpy(LV2_ATOM_BODY(&aev->body), midiEvent.data, midiEvent.size);

evInAtomOffsets[k] += evInPadSize;
fEventsIn.data[k].atom->atom.size = evInAtomOffsets[k];
}
else if (fEventsIn.data[k].type & CARLA_EVENT_DATA_EVENT)
{
lv2_event_write(&evInEventIters[k], time, 0, CARLA_URI_MAP_ID_MIDI_EVENT, midiEvent.size, midiEvent.data);
}
else if (fEventsIn.data[k].type & CARLA_EVENT_DATA_MIDI_LL)
{
lv2midi_put_event(&evInMidiStates[k], time, midiEvent.size, midiEvent.data);
}

break;
}
}

midiEventCount += 1;

if (status == MIDI_STATUS_NOTE_ON)
postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]);
else if (status == MIDI_STATUS_NOTE_OFF)
postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f);

break;
}
}
}

kData->postRtEvents.trySplice();

if (frames > timeOffset)
processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset);

} // End of Event Input and Processing

// --------------------------------------------------------------------------------------------------------
// Plugin processing (no events)

//else
else
{
processSingle(inBuffer, outBuffer, frames, 0, midiEventCount);
processSingle(inBuffer, outBuffer, frames, 0);

} // End of Plugin processing (no events)

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Control Output

if (kData->event.portOut != nullptr)
{
uint8_t channel;
uint16_t param;
float value;

for (k=0; k < kData->param.count; ++k)
{
if (kData->param.data[k].type != PARAMETER_OUTPUT)
continue;

kData->param.ranges[k].fixValue(fParamBuffers[k]);

if (kData->param.data[k].midiCC > 0)
{
channel = kData->param.data[k].midiChannel;
param = static_cast<uint16_t>(kData->param.data[k].midiCC);
value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]);
kData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
}
}

} // End of Control Output

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Final work

if (fExt.worker != nullptr && fExt.worker->end_run != nullptr)
{
fExt.worker->end_run(fHandle);

if (fHandle2)
if (fHandle2 != nullptr)
fExt.worker->end_run(fHandle2);
}

// --------------------------------------------------------------------------------------------------------
}

bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset, const unsigned long midiEventCount)
bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset)
{
CARLA_ASSERT(frames > 0);

@@ -2044,7 +2642,7 @@ public:

fDescriptor->run(fHandle, frames);

if (fHandle2)
if (fHandle2 != nullptr)
fDescriptor->run(fHandle2, frames);

// --------------------------------------------------------------------------------------------------------
@@ -2185,6 +2783,20 @@ public:
}
}

if (fLv2Options.maxBufferSize != static_cast<int>(newBufferSize) || (fLv2Options.minBufferSize > 1 && fLv2Options.minBufferSize != static_cast<int>(newBufferSize)))
{
fLv2Options.maxBufferSize = newBufferSize;

if (fLv2Options.minBufferSize > 1)
fLv2Options.minBufferSize = newBufferSize;

if (fExt.options != nullptr && fExt.options->set != nullptr)
{
fExt.options->set(fHandle, &fLv2Options.optMinBlockLenth);
fExt.options->set(fHandle, &fLv2Options.optMaxBlockLenth);
}
}

carla_debug("Lv2Plugin::bufferSizeChanged(%i) - end", newBufferSize);
}

@@ -2193,8 +2805,13 @@ public:
CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
carla_debug("Lv2Plugin::sampleRateChanged(%g) - start", newSampleRate);

// TODO
(void)newSampleRate;
if (fLv2Options.sampleRate != newSampleRate)
{
fLv2Options.sampleRate = newSampleRate;

if (fExt.options != nullptr && fExt.options->set != nullptr)
fExt.options->set(fHandle, &fLv2Options.optSampleRate);
}

carla_debug("Lv2Plugin::sampleRateChanged(%g) - end", newSampleRate);
}
@@ -2294,7 +2911,7 @@ protected:

const char* getCustomURIString(const LV2_URID urid)
{
CARLA_ASSERT(urid > CARLA_URI_MAP_ID_NULL);
CARLA_ASSERT(urid != CARLA_URI_MAP_ID_NULL);
carla_debug("Lv2Plugin::getCustomURIString(%i)", urid);

if (urid == CARLA_URI_MAP_ID_NULL)
@@ -2340,6 +2957,7 @@ protected:
{
CARLA_ASSERT(key != CARLA_URI_MAP_ID_NULL);
CARLA_ASSERT(value != nullptr);
CARLA_ASSERT(size > 0);

// basic checks
if (key == CARLA_URI_MAP_ID_NULL)
@@ -2456,7 +3074,6 @@ protected:
return nullptr;
}

*size = 0;
*type = key;
*flags = LV2_STATE_IS_POD;

@@ -2478,6 +3095,8 @@ protected:

void handleExternalUiClosed()
{
CARLA_ASSERT(fUi.type == PLUGIN_UI_EXTERNAL);

if (fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->cleanup != nullptr)
fUi.descriptor->cleanup(fUi.handle);

@@ -2883,6 +3502,7 @@ private:
const LV2_State_Interface* state;
const LV2_Worker_Interface* worker;
const LV2_Programs_Interface* programs;
const LV2UI_Idle_Interface* uiidle;
const LV2_Programs_UI_Interface* uiprograms;

Extensions()
@@ -2890,17 +3510,20 @@ private:
state(nullptr),
worker(nullptr),
programs(nullptr),
uiidle(nullptr),
uiprograms(nullptr) {}
} fExt;

struct UI {
Lv2PluginGuiType type;
LV2UI_Handle handle;
LV2UI_Widget widget;
const LV2UI_Descriptor* descriptor;
const LV2_RDF_UI* rdfDescriptor;

UI()
: handle(nullptr),
: type(PLUGIN_UI_NULL),
handle(nullptr),
widget(nullptr),
descriptor(nullptr),
rdfDescriptor(nullptr) {}


+ 2
- 0
source/backend/plugin/NativePlugin.cpp View File

@@ -1146,6 +1146,7 @@ public:
void activate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->activate != nullptr)
{
@@ -1159,6 +1160,7 @@ public:
void deactivate() override
{
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->deactivate != nullptr)
{


+ 4
- 4
source/backend/plugin/VstPlugin.cpp View File

@@ -409,14 +409,14 @@ public:

if (vstRect != nullptr)
{
const int16_t width = vstRect->right - vstRect->left;
const int16_t height = vstRect->bottom - vstRect->top;
const int16_t width(vstRect->right - vstRect->left);
const int16_t height(vstRect->bottom - vstRect->top);

if (width > 0 && height > 0)
kData->gui->setSize(width, height);
}

kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName).toUtf8().constData());
kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName));
kData->gui->show();
}
else
@@ -429,7 +429,7 @@ public:
}

kData->engine->callback(CALLBACK_ERROR, fId, 0, 0, 0.0f, "Plugin refused to open its own UI");
kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
kData->engine->callback(CALLBACK_SHOW_GUI, fId, -1, 0, 0.0f, nullptr);
return;
}
}


Loading…
Cancel
Save