summaryrefslogtreecommitdiff
path: root/libs/ardour/lv2_plugin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/lv2_plugin.cc')
-rw-r--r--libs/ardour/lv2_plugin.cc84
1 files changed, 76 insertions, 8 deletions
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 91dd1578fb..556b8d4357 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -43,6 +43,7 @@
#include "ardour/debug.h"
#include "ardour/lv2_plugin.h"
#include "ardour/session.h"
+#include "ardour/worker.h"
#include "i18n.h"
#include <locale.h>
@@ -51,6 +52,7 @@
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/state/state.h"
+#include "lv2/lv2plug.in/ns/ext/worker/worker.h"
#include "lv2_evbuf.h"
@@ -113,20 +115,45 @@ public:
static LV2World _world;
+/** Called by the plugin to schedule non-RT work. */
+static LV2_Worker_Status
+work_schedule(LV2_Worker_Schedule_Handle handle,
+ uint32_t size,
+ const void* data)
+{
+ Worker* worker = (Worker*)handle;
+ return worker->schedule(size, data) ?
+ LV2_WORKER_SUCCESS : LV2_WORKER_ERR_UNKNOWN;
+}
+
+/** Called by the plugin to respond to non-RT work. */
+static LV2_Worker_Status
+work_respond(LV2_Worker_Respond_Handle handle,
+ uint32_t size,
+ const void* data)
+{
+ Worker* worker = (Worker*)handle;
+ return worker->respond(size, data) ?
+ LV2_WORKER_SUCCESS : LV2_WORKER_ERR_UNKNOWN;
+}
+
struct LV2Plugin::Impl {
Impl() : plugin(0), ui(0), ui_type(0), name(0), author(0), instance(0)
+ , worker(0), work_iface(0)
#ifdef HAVE_NEW_LILV
, state(0)
#endif
{}
- LilvPlugin* plugin;
- const LilvUI* ui;
- const LilvNode* ui_type;
- LilvNode* name;
- LilvNode* author;
- LilvInstance* instance;
+ LilvPlugin* plugin;
+ const LilvUI* ui;
+ const LilvNode* ui_type;
+ LilvNode* name;
+ LilvNode* author;
+ LilvInstance* instance;
+ Worker* worker;
+ LV2_Worker_Interface* work_iface;
#ifdef HAVE_NEW_LILV
- LilvState* state;
+ LilvState* state;
#endif
};
@@ -177,6 +204,7 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
_instance_access_feature.URI = "http://lv2plug.in/ns/ext/instance-access";
_data_access_feature.URI = "http://lv2plug.in/ns/ext/data-access";
_make_path_feature.URI = LV2_STATE__makePath;
+ _work_schedule_feature.URI = LV2_WORKER__schedule;
LilvPlugin* plugin = _impl->plugin;
@@ -192,7 +220,7 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
lilv_node_free(state_iface_uri);
#endif
- _features = (LV2_Feature**)malloc(sizeof(LV2_Feature*) * 7);
+ _features = (LV2_Feature**)malloc(sizeof(LV2_Feature*) * 8);
_features[0] = &_instance_access_feature;
_features[1] = &_data_access_feature;
_features[2] = &_make_path_feature;
@@ -200,6 +228,7 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
_features[4] = _uri_map.urid_map_feature();
_features[5] = _uri_map.urid_unmap_feature();
_features[6] = NULL;
+ _features[7] = NULL;
LV2_State_Make_Path* make_path = (LV2_State_Make_Path*)malloc(
sizeof(LV2_State_Make_Path));
@@ -207,6 +236,18 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
make_path->path = &lv2_state_make_path;
_make_path_feature.data = make_path;
+ LilvNode* worker_schedule = lilv_new_uri(_world.world, LV2_WORKER__schedule);
+ if (lilv_plugin_has_feature(plugin, worker_schedule)) {
+ LV2_Worker_Schedule* schedule = (LV2_Worker_Schedule*)malloc(
+ sizeof(LV2_Worker_Schedule));
+ _impl->worker = new Worker(this, 4096);
+ schedule->handle = _impl->worker;
+ schedule->schedule_work = work_schedule;
+ _work_schedule_feature.data = schedule;
+ _features[6] = &_work_schedule_feature;
+ }
+ lilv_node_free(worker_schedule);
+
_impl->instance = lilv_plugin_instantiate(plugin, rate, _features);
_impl->name = lilv_plugin_get_name(plugin);
_impl->author = lilv_plugin_get_author_name(plugin);
@@ -220,6 +261,8 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
_data_access_extension_data.extension_data = _impl->instance->lv2_descriptor->extension_data;
_data_access_feature.data = &_data_access_extension_data;
+ _impl->work_iface = (LV2_Worker_Interface*)extension_data(LV2_WORKER__interface);
+
if (lilv_plugin_has_feature(plugin, _world.lv2_inPlaceBroken)) {
error << string_compose(
_("LV2: \"%1\" cannot be used, since it cannot do inplace processing"),
@@ -369,6 +412,10 @@ LV2Plugin::~LV2Plugin ()
lilv_node_free(_impl->name);
lilv_node_free(_impl->author);
+ free(_features);
+ free(_make_path_feature.data);
+ free(_work_schedule_feature.data);
+
delete _to_ui;
delete _from_ui;
@@ -850,6 +897,7 @@ LV2Plugin::write_to_ui(uint32_t index,
uint32_t size,
uint8_t* body)
{
+ std::cerr << "WRITE TO UI" << std::endl;
write_to(_to_ui, index, protocol, size, body);
}
@@ -888,6 +936,19 @@ LV2Plugin::emit_to_ui(void* controller, UIMessageSink sink)
}
void
+LV2Plugin::work(uint32_t size, const void* data)
+{
+ _impl->work_iface->work(
+ _impl->instance->lv2_handle, work_respond, _impl->worker, size, data);
+}
+
+void
+LV2Plugin::work_response(uint32_t size, const void* data)
+{
+ _impl->work_iface->work_response(_impl->instance->lv2_handle, size, data);
+}
+
+void
LV2Plugin::set_insert_info(const PluginInsert* insert)
{
_insert_id = insert->id();
@@ -1297,6 +1358,13 @@ LV2Plugin::run(pframes_t nframes)
}
lilv_instance_run(_impl->instance, nframes);
+
+ if (_impl->work_iface) {
+ _impl->worker->emit_responses();
+ if (_impl->work_iface->end_run) {
+ _impl->work_iface->end_run(_impl->instance->lv2_handle);
+ }
+ }
}
void