Browse Source

Carla: some LV2 worker support (need proper plugins to test this)

tags/v0.9.0
falkTX 13 years ago
parent
commit
5a9d254b3a
2 changed files with 104 additions and 69 deletions
  1. +25
    -3
      c++/carla-backend/carla_plugin.h
  2. +79
    -66
      c++/carla-backend/lv2.cpp

+ 25
- 3
c++/carla-backend/carla_plugin.h View File

@@ -86,7 +86,8 @@ enum PluginPostEventType {
PluginPostEventProgramChange, // index
PluginPostEventMidiProgramChange, // index
PluginPostEventNoteOn, // channel, note, velo
PluginPostEventNoteOff // channel, note
PluginPostEventNoteOff, // channel, note
PluginPostEventCustom
};

struct PluginAudioData {
@@ -151,12 +152,14 @@ struct PluginPostEvent {
int32_t value1;
int32_t value2;
double value3;
const void* cdata;

PluginPostEvent()
: type(PluginPostEventNull),
value1(-1),
value2(-1),
value3(0.0) {}
value3(0.0),
cdata(nullptr) {}
};

struct ExternalMidiNote {
@@ -1703,7 +1706,7 @@ public:
* Post pone an event of type \a type.\n
* The event will be processed later, but as soon as possible.
*/
void postponeEvent(const PluginPostEventType type, const int32_t value1, const int32_t value2, const double value3)
void postponeEvent(const PluginPostEventType type, const int32_t value1, const int32_t value2, const double value3, const void* const cdata = nullptr)
{
postEvents.mutex.lock();
for (unsigned short i=0; i < MAX_POST_EVENTS; i++)
@@ -1714,6 +1717,7 @@ public:
postEvents.data[i].value1 = value1;
postEvents.data[i].value2 = value2;
postEvents.data[i].value3 = value3;
postEvents.data[i].cdata = cdata;
break;
}
}
@@ -1822,10 +1826,28 @@ public:
// Update Host
x_engine->callback(CALLBACK_NOTE_OFF, m_id, event->value1, event->value2, 0.0);
break;

case PluginPostEventCustom:
// Handle custom event
postEventHandleCustom(event->value1, event->value2, event->value3, event->cdata);
break;
}
}
}


/*!
* Handle custom post event.\n
* Implementation depends on plugin type.
*/
virtual void postEventHandleCustom(const int32_t value1, const int32_t value2, const double value3, const void* const cdata)
{
Q_UNUSED(value1);
Q_UNUSED(value2);
Q_UNUSED(value3);
Q_UNUSED(cdata);
}

/*!
* Tell the UI a parameter has changed.
*/


+ 79
- 66
c++/carla-backend/lv2.cpp View File

@@ -44,7 +44,6 @@ CARLA_BACKEND_START_NAMESPACE

// static max values
const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000
//const unsigned int MAX_EVENT_BUFFER = (sizeof(LV2_Atom_Event) + 4) * MAX_MIDI_EVENTS;

/*!
* @defgroup PluginHints Plugin Hints
@@ -123,20 +122,31 @@ const uint32_t CARLA_URI_MAP_ID_ATOM_INT = 3;
const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 4;
const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 5;
const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 6;
const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 7;
const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 8;
const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 9;
const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 10;
const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 11;
const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 12;
const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 13;
const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 14;
const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 15;
const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 16;
const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 17;
const uint32_t CARLA_URI_MAP_ID_COUNT = 18;
const uint32_t CARLA_URI_MAP_ID_ATOM_WORKER = 7;
const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 8;
const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 9;
const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 10;
const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 11;
const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 12;
const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 13;
const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 14;
const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 15;
const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 16;
const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 17;
const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 18;
const uint32_t CARLA_URI_MAP_ID_COUNT = 19;
/**@}*/

struct LV2_Atom_Worker_Body {
uint32_t size;
const void* data;
};

struct LV2_Atom_Worker {
LV2_Atom atom;
LV2_Atom_Worker_Body body;
};

struct Lv2EventData {
uint32_t type;
uint32_t rindex;
@@ -189,6 +199,8 @@ const char* lv2bridge2str(const LV2_Property type)
#ifndef BUILD_BRIDGE
case LV2_UI_GTK2:
return carlaOptions.bridge_lv2gtk2;
case LV2_UI_GTK3:
return carlaOptions.bridge_lv2gtk3;
case LV2_UI_QT4:
return carlaOptions.bridge_lv2qt4;
case LV2_UI_COCOA:
@@ -270,8 +282,8 @@ public:

void put(const uint32_t portIndex, const LV2_Atom* const atom, const bool lock = true)
{
qDebug("Lv2AtomQueue::put(%i, %p, %s)", portIndex, atom, bool2str(lock));
Q_ASSERT(atom->size > 0);
qDebug("Lv2AtomQueue::put(%i, size:%i, type:%i, %s)", portIndex, atom->size, atom->type, bool2str(lock));
Q_ASSERT(atom && atom->size > 0);
Q_ASSERT(indexPool + atom->size < MAX_POOL_SIZE); // overflow

if (full || atom->size == 0 || indexPool + atom->size >= MAX_POOL_SIZE)
@@ -288,7 +300,7 @@ public:
data[i].size = atom->size;
data[i].type = atom->type;
data[i].poolOffset = indexPool;
memcpy(dataPool + indexPool, (const unsigned char*)LV2_ATOM_BODY_CONST(&atom), atom->size);
memcpy(dataPool + indexPool, (const unsigned char*)LV2_ATOM_BODY_CONST(atom), atom->size);
empty = false;
full = (i == MAX_SIZE-1);
indexPool += atom->size;
@@ -369,8 +381,7 @@ private:
unsigned char data[MAX_POOL_SIZE];
} retAtom;

unsigned short index;
uint32_t indexPool;
unsigned short index, indexPool;
bool empty, full;

QMutex mutex;
@@ -1195,7 +1206,7 @@ public:
if (haveUI)
{
// Update event ports
if (! atomQueueIn.isEmpty())
if (! atomQueueOut.isEmpty())
{
static Lv2AtomQueue queue;
queue.copyDataFrom(&atomQueueOut);
@@ -1205,7 +1216,6 @@ public:

while (queue.get(&portIndex, &atom, false))
{
qDebug("idle Got atom, size: %i, content: %s", atom->size, (char*)LV2_ATOM_BODY(atom));
#ifndef BUILD_BRIDGE
if (gui.type == GUI_EXTERNAL_OSC)
{
@@ -2447,7 +2457,12 @@ public:

while (atomQueueIn.get(&portIndex, &atom, false))
{
qDebug("proc, in, send, Got atom, size: %i, content: %s", atom->size, (unsigned char*)LV2_ATOM_BODY(atom));
if (atom->type == CARLA_URI_MAP_ID_ATOM_WORKER)
{
const LV2_Atom_Worker* const atomWorker = (const LV2_Atom_Worker*)atom;
ext.worker->work_response(handle, atomWorker->body.size, atomWorker->body.data);
continue;
}

LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]);
aev->time.frames = framesOffset;
@@ -2620,16 +2635,10 @@ public:
descriptor->run(handle, frames);
if (h2) descriptor->run(h2, frames);

if (ext.worker)
if (ext.worker && ext.worker->end_run)
{
// TODO
//ext.worker->work_response();

if (ext.worker->end_run)
{
ext.worker->end_run(handle);
if (h2) ext.worker->end_run(h2);
}
ext.worker->end_run(handle);
if (h2) ext.worker->end_run(h2);
}
}
else
@@ -2765,16 +2774,19 @@ public:

if (evOut.data[i].type & CARLA_EVENT_DATA_ATOM)
{
uint32_t size = evOut.data[i].atom->atom.size - sizeof(LV2_Atom_Sequence_Body);
uint32_t offset = 0;
int32_t size = evOut.data[i].atom->atom.size - sizeof(LV2_Atom_Sequence_Body);
int32_t offset = 0;

while (offset < size)
{
qDebug("output event??, offset:%i, size:%i", offset, size);
const LV2_Atom_Event* const aev = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, evOut.data[i].atom) + offset);

if ((! aev) || aev->body.type == CARLA_URI_MAP_ID_NULL)
break;

qDebug("output event ------------------------------ YES!");

if (aev->body.type == CARLA_URI_MAP_ID_MIDI_EVENT)
{
const unsigned char* const data = (unsigned char*)LV2_ATOM_BODY(&aev->body);
@@ -2848,6 +2860,15 @@ public:
// -------------------------------------------------------------------
// Post-poned events

void postEventHandleCustom(const int32_t size, const int32_t, const double, const void* const data)
{
qDebug("Lv2Plugin::postEventHandleCustom(%i, %p)", size, data);
Q_ASSERT(ext.worker && ext.worker->work);

if (ext.worker && ext.worker->work)
ext.worker->work(handle, carla_lv2_worker_respond, this, size, data);
}

void uiParameterChange(const uint32_t index, const double value)
{
Q_ASSERT(index < param.count);
@@ -3094,7 +3115,7 @@ public:
Q_ASSERT(atom);

// FIXME - is this correct?
//atomQueueIn.put(portIndex, atom->type, atom);
//atomQueueIn.put(portIndex, atom);
}

void handleTransferEvent(const uint32_t portIndex, const LV2_Atom* const atom)
@@ -3261,19 +3282,33 @@ public:
return nullptr;
}

LV2_Worker_Status handleWorkerSchedule(const uint32_t /*size*/, const void* const /*data*/)
LV2_Worker_Status handleWorkerSchedule(const uint32_t size, const void* const data)
{
// TODO
if (! ext.worker)
{
qWarning("Lv2Plugin::handleWorkerSchedule(%i, %p) - plugin has no worker", size, data);
return LV2_WORKER_ERR_UNKNOWN;
}

if (x_engine->isOffline())
ext.worker->work(handle, carla_lv2_worker_respond, this, size, data);
else
postponeEvent(PluginPostEventCustom, size, 0, 0.0, data);

return LV2_WORKER_SUCCESS;
}

LV2_Worker_Status handleWorkerRespond(const uint32_t /*size*/, const void* const /*data*/)
LV2_Worker_Status handleWorkerRespond(const uint32_t size, const void* const data)
{
// TODO
if (ext.worker)
return LV2_WORKER_SUCCESS;
LV2_Atom_Worker workerAtom;
workerAtom.atom.type = CARLA_URI_MAP_ID_ATOM_WORKER;
workerAtom.atom.size = sizeof(LV2_Atom_Worker_Body);
workerAtom.body.size = size;
workerAtom.body.data = data;

return LV2_WORKER_ERR_UNKNOWN;
atomQueueIn.put(0, (const LV2_Atom*)&workerAtom);

return LV2_WORKER_SUCCESS;
}

void handleExternalUiClosed()
@@ -3337,9 +3372,6 @@ public:

const LV2_Atom* const atom = (const LV2_Atom*)buffer;
handleTransferAtom(rindex, atom);

//if (ui.handle && ui.descriptor && ui.descriptor->port_event)
// ui.descriptor->port_event(ui.handle, 0, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, atom);
}
else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
{
@@ -3347,9 +3379,6 @@ public:

const LV2_Atom* const atom = (const LV2_Atom*)buffer;
handleTransferEvent(rindex, atom);

//if (ui.handle && ui.descriptor && ui.descriptor->port_event)
// ui.descriptor->port_event(ui.handle, 0, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
}
}

@@ -3464,8 +3493,6 @@ public:

void updateUi()
{
qDebug("Lv2Plugin::updateUi()");

ext.uiprograms = nullptr;

if (ui.handle && ui.descriptor)
@@ -3484,19 +3511,12 @@ public:

if (ui.descriptor->port_event)
{
// get&store custom data to be sent to the UI
//prepareForSave();

// update state (custom data)
//for (size_t i=0; i < custom.size(); i++)
// uiTransferEvent(&custom[i]);

// update control ports
float valueF;
for (uint32_t i=0; i < param.count; i++)
{
valueF = getParameterValue(i);
ui.descriptor->port_event(ui.handle, param.data[i].rindex, sizeof(float), 0, &valueF);
ui.descriptor->port_event(ui.handle, param.data[i].rindex, sizeof(float), CARLA_URI_MAP_ID_NULL, &valueF);
}
}
}
@@ -3752,6 +3772,8 @@ public:
return LV2_ATOM__Sequence;
if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
return LV2_ATOM__String;
if (urid == CARLA_URI_MAP_ID_ATOM_WORKER)
return nullptr; // not a valid URID, only used internally
if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
return LV2_ATOM__atomTransfer;
if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
@@ -3839,7 +3861,7 @@ public:
if (! handle)
return 1;

Lv2Plugin* const plugin = (Lv2Plugin*)handle;
Lv2Plugin* const plugin = (Lv2Plugin*)handle;
return plugin->handleUiResize(width, height);
}

@@ -4153,8 +4175,6 @@ public:
// ---------------------------------------------------------------
// gui stuff

qDebug("LV2 UI ----------------------------------------------------- 001");

if (rdf_descriptor->UICount == 0)
return true;

@@ -4164,7 +4184,6 @@ public:
int eQt4, eCocoa, eHWND, eX11, eGtk2, eGtk3, iCocoa, iHWND, iX11, iQt4, iExt, iSuil, iFinal;
eQt4 = eCocoa = eHWND = eX11 = eGtk2 = eGtk3 = iQt4 = iCocoa = iHWND = iX11 = iExt = iSuil = iFinal = -1;

qDebug("LV2 UI ----------------------------------------------------- 002");
for (i=0; i < rdf_descriptor->UICount; i++)
{
switch (rdf_descriptor->UIs[i].Type)
@@ -4271,7 +4290,6 @@ public:
qWarning("Failed to find an appropriate LV2 UI for this plugin");
return true;
}
qDebug("LV2 UI ----------------------------------------------------- 003");

ui.rdf_descriptor = &rdf_descriptor->UIs[iFinal];

@@ -4295,14 +4313,12 @@ public:
ui.rdf_descriptor = nullptr;
return true;
}
qDebug("LV2 UI ----------------------------------------------------- 004");

#ifdef HAVE_SUIL
if (isSuil)
{
// -------------------------------------------------------
// init suil host
qDebug("LV2 UI ----------------------------------------------------- 005a");

suil.host = suil_host_new(carla_lv2_ui_write_function, carla_lv2_ui_port_map, nullptr, nullptr);
}
@@ -4311,7 +4327,6 @@ public:
{
// -------------------------------------------------------
// open DLL
qDebug("LV2 UI ----------------------------------------------------- 005b");

if (! uiLibOpen(ui.rdf_descriptor->Binary))
{
@@ -4354,7 +4369,6 @@ public:
}
}

qDebug("LV2 UI ----------------------------------------------------- 006");
// -----------------------------------------------------------
// initialize ui according to type

@@ -4376,7 +4390,6 @@ public:
else
#endif
{
qDebug("LV2 UI ----------------------------------------------------- 007b");
// -------------------------------------------------------
// initialize ui features



Loading…
Cancel
Save