Browse Source

Initial LV2 worker code, still incomplete

tags/1.9.4
falkTX 11 years ago
parent
commit
692dff2ee7
5 changed files with 142 additions and 49 deletions
  1. +2
    -2
      source/backend/engine/CarlaEngineOsc.cpp
  2. +1
    -0
      source/backend/plugin/CarlaPlugin.pro
  3. +129
    -34
      source/backend/plugin/Lv2Plugin.cpp
  4. +1
    -1
      source/backend/plugin/Makefile
  5. +9
    -12
      source/utils/Lv2AtomQueue.hpp

+ 2
- 2
source/backend/engine/CarlaEngineOsc.cpp View File

@@ -370,8 +370,8 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons
} }
#endif #endif


// Plugin-specific methods, FIXME
#if 0 //def WANT_LV2
// Plugin-specific methods
#ifdef WANT_LV2
if (std::strcmp(method, "lv2_atom_transfer") == 0) if (std::strcmp(method, "lv2_atom_transfer") == 0)
return handleMsgLv2AtomTransfer(plugin, argc, argv, types); return handleMsgLv2AtomTransfer(plugin, argc, argv, types);
if (std::strcmp(method, "lv2_event_transfer") == 0) if (std::strcmp(method, "lv2_event_transfer") == 0)


+ 1
- 0
source/backend/plugin/CarlaPlugin.pro View File

@@ -78,6 +78,7 @@ HEADERS += \
../../utils/CarlaString.hpp ../../utils/CarlaString.hpp


INCLUDEPATH = . .. \ INCLUDEPATH = . .. \
../engine \
../../includes \ ../../includes \
../../libs \ ../../libs \
../../utils ../../utils


+ 129
- 34
source/backend/plugin/Lv2Plugin.cpp View File

@@ -22,6 +22,9 @@
#include "CarlaPluginGui.hpp" #include "CarlaPluginGui.hpp"
#include "CarlaLv2Utils.hpp" #include "CarlaLv2Utils.hpp"


#include "CarlaEngineOsc.hpp"
#include "Lv2AtomQueue.hpp"

#include <QtCore/QDir> #include <QtCore/QDir>


extern "C" { extern "C" {
@@ -121,7 +124,6 @@ const uint32_t kFeatureIdStrictBounds = 10;
const uint32_t kFeatureIdUriMap = 11; const uint32_t kFeatureIdUriMap = 11;
const uint32_t kFeatureIdUridMap = 12; const uint32_t kFeatureIdUridMap = 12;
const uint32_t kFeatureIdUridUnmap = 13; const uint32_t kFeatureIdUridUnmap = 13;
#if 0
const uint32_t kFeatureIdWorker = 14; const uint32_t kFeatureIdWorker = 14;
const uint32_t kFeatureIdUiDataAccess = 15; const uint32_t kFeatureIdUiDataAccess = 15;
const uint32_t kFeatureIdUiInstanceAccess = 16; const uint32_t kFeatureIdUiInstanceAccess = 16;
@@ -131,16 +133,6 @@ const uint32_t kFeatureIdUiResize = 19;
const uint32_t kFeatureIdExternalUi = 20; const uint32_t kFeatureIdExternalUi = 20;
const uint32_t kFeatureIdExternalUiOld = 21; const uint32_t kFeatureIdExternalUiOld = 21;
const uint32_t kFeatureCount = 22; const uint32_t kFeatureCount = 22;
#else
const uint32_t kFeatureIdUiDataAccess = 14;
const uint32_t kFeatureIdUiInstanceAccess = 15;
const uint32_t kFeatureIdUiParent = 16;
const uint32_t kFeatureIdUiPortMap = 17;
const uint32_t kFeatureIdUiResize = 18;
const uint32_t kFeatureIdExternalUi = 19;
const uint32_t kFeatureIdExternalUiOld = 20;
const uint32_t kFeatureCount = 21;
#endif
/**@}*/ /**@}*/


const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000 const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000
@@ -485,10 +477,8 @@ public:
if (fFeatures[kFeatureIdUridUnmap] != nullptr && fFeatures[kFeatureIdUridUnmap]->data != nullptr) if (fFeatures[kFeatureIdUridUnmap] != nullptr && fFeatures[kFeatureIdUridUnmap]->data != nullptr)
delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data; delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;


#if 0
if (fFeatures[kFeatureIdWorker] != nullptr && fFeatures[kFeatureIdWorker]->data != nullptr) if (fFeatures[kFeatureIdWorker] != nullptr && fFeatures[kFeatureIdWorker]->data != nullptr)
delete (LV2_Worker_Schedule*)fFeatures[kFeatureIdWorker]->data; delete (LV2_Worker_Schedule*)fFeatures[kFeatureIdWorker]->data;
#endif


for (uint32_t i=0; i < kFeatureCount; ++i) for (uint32_t i=0; i < kFeatureCount; ++i)
{ {
@@ -2314,6 +2304,46 @@ public:


if (fEventsIn.ctrl != nullptr && fEventsIn.ctrl->port != nullptr) if (fEventsIn.ctrl != nullptr && fEventsIn.ctrl->port != nullptr)
{ {
// ----------------------------------------------------------------------------------------------------
// Message Input

if (fAtomQueueIn.tryLock())
{
if (! fAtomQueueIn.isEmpty())
{
uint32_t portIndex;
const LV2_Atom* atom;

k = fEventsIn.ctrlIndex;

while (fAtomQueueIn.get(&portIndex, &atom))
{
const uint32_t evInPadSize(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + atom->size));

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

//if (atom->type == CARLA_URI_MAP_ID_ATOM_WORKER)
//{
// const LV2_Atom_Worker* const atomWorker = (const LV2_Atom_Worker*)atom;
// fExt.worker->work_response(fHandle, atomWorker->body.size, atomWorker->body.data);
// continue;
//}

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

evInAtomOffsets[k] += evInPadSize;
fEventsIn.ctrl->atom->atom.size = evInAtomOffsets[k];
}
}

fAtomQueueIn.unlock();
}

// ---------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------
// MIDI Input (External) // MIDI Input (External)


@@ -2340,7 +2370,7 @@ public:
const uint32_t evInPadSize(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + 3)); const uint32_t evInPadSize(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + 3));


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


LV2_Atom_Event* const aev = getLv2AtomEvent(fEventsIn.ctrl->atom, evInAtomOffsets[k]); LV2_Atom_Event* const aev = getLv2AtomEvent(fEventsIn.ctrl->atom, evInAtomOffsets[k]);
aev->time.frames = 0; aev->time.frames = 0;
@@ -3334,23 +3364,22 @@ protected:
} }
} }


#if 0
// ------------------------------------------------------------------- // -------------------------------------------------------------------


LV2_Worker_Status handleWorkerSchedule(const uint32_t size, const void* const data) LV2_Worker_Status handleWorkerSchedule(const uint32_t size, const void* const data)
{ {
carla_stdout("Lv2Plugin::handleWorkerSchedule(%i, %p)", size, data); carla_stdout("Lv2Plugin::handleWorkerSchedule(%i, %p)", size, data);


if (! ext.worker)
if (fExt.worker == nullptr || fExt.worker->work == nullptr)
{ {
carla_stderr("Lv2Plugin::handleWorkerSchedule(%i, %p) - plugin has no worker", size, data); carla_stderr("Lv2Plugin::handleWorkerSchedule(%i, %p) - plugin has no worker", size, data);
return LV2_WORKER_ERR_UNKNOWN; 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);
//if (kData->engine->isOffline())
fExt.worker->work(fHandle, carla_lv2_worker_respond, this, size, data);
//else
// postponeEvent(PluginPostEventCustom, size, 0, 0.0, data);


return LV2_WORKER_SUCCESS; return LV2_WORKER_SUCCESS;
} }
@@ -3359,6 +3388,7 @@ protected:
{ {
carla_stdout("Lv2Plugin::handleWorkerRespond(%i, %p)", size, data); carla_stdout("Lv2Plugin::handleWorkerRespond(%i, %p)", size, data);


#if 0
LV2_Atom_Worker workerAtom; LV2_Atom_Worker workerAtom;
workerAtom.atom.type = CARLA_URI_MAP_ID_ATOM_WORKER; workerAtom.atom.type = CARLA_URI_MAP_ID_ATOM_WORKER;
workerAtom.atom.size = sizeof(LV2_Atom_Worker_Body); workerAtom.atom.size = sizeof(LV2_Atom_Worker_Body);
@@ -3366,10 +3396,10 @@ protected:
workerAtom.body.data = data; workerAtom.body.data = data;


atomQueueIn.put(0, (const LV2_Atom*)&workerAtom); atomQueueIn.put(0, (const LV2_Atom*)&workerAtom);
#endif


return LV2_WORKER_SUCCESS; return LV2_WORKER_SUCCESS;
} }
#endif


// ------------------------------------------------------------------- // -------------------------------------------------------------------


@@ -3381,7 +3411,7 @@ protected:
fUi.descriptor->cleanup(fUi.handle); fUi.descriptor->cleanup(fUi.handle);


fUi.handle = nullptr; fUi.handle = nullptr;
kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0, nullptr);
kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
} }


uint32_t handleUiPortMap(const char* const symbol) uint32_t handleUiPortMap(const char* const symbol)
@@ -3444,8 +3474,8 @@ protected:
if (buffer == nullptr) if (buffer == nullptr)
return; return;


//const LV2_Atom* const atom = (const LV2_Atom*)buffer;
//handleTransferAtom(rindex, atom);
const LV2_Atom* const atom = (const LV2_Atom*)buffer;
fAtomQueueIn.put(rindex, atom);
} }
else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT) else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
{ {
@@ -3454,8 +3484,8 @@ protected:
if (buffer == nullptr) if (buffer == nullptr)
return; return;


//const LV2_Atom* const atom = (const LV2_Atom*)buffer;
//handleTransferEvent(rindex, atom);
const LV2_Atom* const atom = (const LV2_Atom*)buffer;
fAtomQueueIn.put(rindex, atom);
} }
} }


@@ -3666,11 +3696,9 @@ public:
uridUnmapFt->handle = this; uridUnmapFt->handle = this;
uridUnmapFt->unmap = carla_lv2_urid_unmap; uridUnmapFt->unmap = carla_lv2_urid_unmap;


#if 0
LV2_Worker_Schedule* const workerFt = new LV2_Worker_Schedule; LV2_Worker_Schedule* const workerFt = new LV2_Worker_Schedule;
workerFt->handle = this; workerFt->handle = this;
workerFt->schedule_work = carla_lv2_worker_schedule; workerFt->schedule_work = carla_lv2_worker_schedule;
#endif


// --------------------------------------------------------------- // ---------------------------------------------------------------
// initialize features (part 2) // initialize features (part 2)
@@ -3731,11 +3759,9 @@ public:
fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap; fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt; fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;


#if 0
fFeatures[kFeatureIdWorker] = new LV2_Feature; fFeatures[kFeatureIdWorker] = new LV2_Feature;
fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule; fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule;
fFeatures[kFeatureIdWorker]->data = workerFt; fFeatures[kFeatureIdWorker]->data = workerFt;
#endif


if (! needsFixedBuffer()) if (! needsFixedBuffer())
fFeatures[kFeatureIdBufSizeFixed]->URI = LV2_BUF_SIZE__boundedBlockLength; fFeatures[kFeatureIdBufSizeFixed]->URI = LV2_BUF_SIZE__boundedBlockLength;
@@ -4244,6 +4270,34 @@ public:
return true; return true;
} }


// -------------------------------------------------------------------

void handleTransferAtom(const int32_t portIndex, const char* const typeStr, LV2_Atom* const atom)
{
CARLA_ASSERT(portIndex >= 0);
CARLA_ASSERT(atom != nullptr);
CARLA_ASSERT(typeStr != nullptr);
carla_debug("Lv2Plugin::handleTransferAtom(%i, %s, %p)", portIndex, typeStr, atom);

atom->type = carla_lv2_urid_map(this, typeStr);

fAtomQueueIn.put(portIndex, atom);
}

void handleTransferEvent(const int32_t portIndex, const char* const typeStr, LV2_Atom* const atom)
{
CARLA_ASSERT(portIndex >= 0);
CARLA_ASSERT(atom != nullptr);
CARLA_ASSERT(typeStr != nullptr);
carla_debug("Lv2Plugin::handleTransferEvent(%i, %s, %p)", portIndex, typeStr, atom);

atom->type = carla_lv2_urid_map(this, typeStr);

fAtomQueueIn.put(portIndex, atom);
}

// -------------------------------------------------------------------

private: private:
LV2_Handle fHandle; LV2_Handle fHandle;
LV2_Handle fHandle2; LV2_Handle fHandle2;
@@ -4255,6 +4309,9 @@ private:
float** fAudioOutBuffers; float** fAudioOutBuffers;
float* fParamBuffers; float* fParamBuffers;


Lv2AtomQueue fAtomQueueIn;
Lv2AtomQueue fAtomQueueOut;

Lv2PluginEventData fEventsIn; Lv2PluginEventData fEventsIn;
Lv2PluginEventData fEventsOut; Lv2PluginEventData fEventsOut;
Lv2PluginOptions fLv2Options; Lv2PluginOptions fLv2Options;
@@ -4609,14 +4666,13 @@ private:
return ((Lv2Plugin*)handle)->getCustomURIString(urid); return ((Lv2Plugin*)handle)->getCustomURIString(urid);
} }


#if 0
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Worker Feature // Worker Feature


static LV2_Worker_Status carla_lv2_worker_schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data) static LV2_Worker_Status carla_lv2_worker_schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data)
{ {
carla_debug("carla_lv2_worker_schedule(%p, %i, %p)", handle, size, data);
CARLA_ASSERT(handle != nullptr); CARLA_ASSERT(handle != nullptr);
carla_debug("carla_lv2_worker_schedule(%p, %i, %p)", handle, size, data);


if (handle == nullptr) if (handle == nullptr)
return LV2_WORKER_ERR_UNKNOWN; return LV2_WORKER_ERR_UNKNOWN;
@@ -4626,15 +4682,14 @@ private:


static LV2_Worker_Status carla_lv2_worker_respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void* data) static LV2_Worker_Status carla_lv2_worker_respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void* data)
{ {
carla_debug("carla_lv2_worker_respond(%p, %i, %p)", handle, size, data);
CARLA_ASSERT(handle != nullptr); CARLA_ASSERT(handle != nullptr);
carla_debug("carla_lv2_worker_respond(%p, %i, %p)", handle, size, data);


if (handle == nullptr) if (handle == nullptr)
return LV2_WORKER_ERR_UNKNOWN; return LV2_WORKER_ERR_UNKNOWN;


return ((Lv2Plugin*)handle)->handleWorkerRespond(size, data); return ((Lv2Plugin*)handle)->handleWorkerRespond(size, data);
} }
#endif


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// UI Port-Map Feature // UI Port-Map Feature
@@ -4697,6 +4752,46 @@ private:
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Lv2Plugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Lv2Plugin)
}; };


// -------------------------------------------------------------------------------------------------------------------

int CarlaEngineOsc::handleMsgLv2AtomTransfer(CARLA_ENGINE_OSC_HANDLE_ARGS2)
{
carla_debug("CarlaOsc::handleMsgLv2AtomTransfer()");
CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iss");

const int32_t portIndex = argv[0]->i;
const char* const typeStr = (const char*)&argv[1]->s;
const char* const atomBuf = (const char*)&argv[2]->s;

QByteArray chunk;
chunk = QByteArray::fromBase64(atomBuf);

LV2_Atom* const atom = (LV2_Atom*)chunk.data();

((Lv2Plugin*)plugin)->handleTransferAtom(portIndex, typeStr, atom);

return 0;
}

int CarlaEngineOsc::handleMsgLv2EventTransfer(CARLA_ENGINE_OSC_HANDLE_ARGS2)
{
carla_debug("CarlaOsc::handleMsgLv2EventTransfer()");
CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iss");

const int32_t portIndex = argv[0]->i;
const char* const typeStr = (const char*)&argv[1]->s;
const char* const atomBuf = (const char*)&argv[2]->s;

QByteArray chunk;
chunk = QByteArray::fromBase64(atomBuf);

LV2_Atom* const atom = (LV2_Atom*)chunk.data();

((Lv2Plugin*)plugin)->handleTransferEvent(portIndex, typeStr, atom);

return 0;
}

CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


#else // WANT_VST #else // WANT_VST


+ 1
- 1
source/backend/plugin/Makefile View File

@@ -8,7 +8,7 @@ include ../Makefile.mk


# -------------------------------------------------------------- # --------------------------------------------------------------


BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo)
BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo) -I../engine


ifeq ($(HAVE_QT5),true) ifeq ($(HAVE_QT5),true)
BUILD_CXX_FLAGS += $(shell pkg-config --cflags Qt5Core Qt5Xml Qt5Widgets) BUILD_CXX_FLAGS += $(shell pkg-config --cflags Qt5Core Qt5Xml Qt5Widgets)


+ 9
- 12
source/utils/Lv2AtomQueue.hpp View File

@@ -18,7 +18,7 @@
#ifndef __LV2_ATOM_QUEUE_HPP__ #ifndef __LV2_ATOM_QUEUE_HPP__
#define __LV2_ATOM_QUEUE_HPP__ #define __LV2_ATOM_QUEUE_HPP__


#include "CarlaUtils.hpp"
#include "CarlaMutex.hpp"


#include <cstring> // memcpy, memset #include <cstring> // memcpy, memset
#include "lv2/atom.h" #include "lv2/atom.h"
@@ -32,7 +32,7 @@ public:
empty = true; empty = true;
full = false; full = false;


::memset(dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
std::memset(dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
} }


void copyDataFrom(Lv2AtomQueue* const queue) void copyDataFrom(Lv2AtomQueue* const queue)
@@ -42,8 +42,8 @@ public:
lock(); lock();


// copy data from queue // copy data from queue
::memcpy(data, queue->data, sizeof(datatype)*MAX_SIZE);
::memcpy(dataPool, queue->dataPool, sizeof(unsigned char)*MAX_POOL_SIZE);
std::memcpy(data, queue->data, sizeof(datatype)*MAX_SIZE);
std::memcpy(dataPool, queue->dataPool, sizeof(unsigned char)*MAX_POOL_SIZE);
index = queue->index; index = queue->index;
indexPool = queue->indexPool; indexPool = queue->indexPool;
empty = queue->empty; empty = queue->empty;
@@ -53,8 +53,8 @@ public:
unlock(); unlock();


// reset queque // reset queque
::memset(queue->data, 0, sizeof(datatype)*MAX_SIZE);
::memset(queue->dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
std::memset(queue->data, 0, sizeof(datatype)*MAX_SIZE);
std::memset(queue->dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
queue->index = queue->indexPool = 0; queue->index = queue->indexPool = 0;
queue->empty = true; queue->empty = true;
queue->full = false; queue->full = false;
@@ -106,7 +106,7 @@ public:
data[i].size = atom->size; data[i].size = atom->size;
data[i].type = atom->type; data[i].type = atom->type;
data[i].poolOffset = indexPool; data[i].poolOffset = indexPool;
::memcpy(dataPool + indexPool, (const unsigned char*)LV2_ATOM_BODY_CONST(atom), atom->size);
std::memcpy(dataPool + indexPool, (const unsigned char*)LV2_ATOM_BODY_CONST(atom), atom->size);
empty = false; empty = false;
full = (i == MAX_SIZE-1); full = (i == MAX_SIZE-1);
indexPool += atom->size; indexPool += atom->size;
@@ -117,6 +117,7 @@ public:
unlock(); unlock();
} }


// needs to be locked first!
bool get(uint32_t* const portIndex, const LV2_Atom** const atom) bool get(uint32_t* const portIndex, const LV2_Atom** const atom)
{ {
CARLA_ASSERT(portIndex && atom); CARLA_ASSERT(portIndex && atom);
@@ -124,9 +125,6 @@ public:
if (empty || ! (portIndex && atom)) if (empty || ! (portIndex && atom))
return false; return false;


if (! tryLock())
return false;

full = false; full = false;


if (data[index].size == 0) if (data[index].size == 0)
@@ -140,7 +138,7 @@ public:


retAtom.atom.size = data[index].size; retAtom.atom.size = data[index].size;
retAtom.atom.type = data[index].type; retAtom.atom.type = data[index].type;
::memcpy(retAtom.data, dataPool + data[index].poolOffset, data[index].size);
std::memcpy(retAtom.data, dataPool + data[index].poolOffset, data[index].size);


*portIndex = data[index].portIndex; *portIndex = data[index].portIndex;
*atom = (LV2_Atom*)&retAtom; *atom = (LV2_Atom*)&retAtom;
@@ -152,7 +150,6 @@ public:
index++; index++;
empty = false; empty = false;


unlock();
return true; return true;
} }




Loading…
Cancel
Save