aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jalv.c101
-rw-r--r--src/jalv_internal.h3
-rw-r--r--src/worker.c110
-rw-r--r--src/worker.h40
4 files changed, 168 insertions, 86 deletions
diff --git a/src/jalv.c b/src/jalv.c
index 484ad4b..d01581d 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -47,6 +47,7 @@
#include "suil/suil.h"
#include "lv2_evbuf.h"
+#include "worker.h"
#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
#define NS_MIDI "http://lv2plug.in/ns/ext/midi#"
@@ -429,24 +430,11 @@ jack_process_cb(jack_nframes_t nframes, void* data)
lilv_instance_run(host->instance, nframes);
/* Process any replies from the worker. */
- if (host->worker.responses) {
- uint32_t read_space = jack_ringbuffer_read_space(host->worker.responses);
- while (read_space) {
- uint32_t size = 0;
- jack_ringbuffer_read(host->worker.responses, (char*)&size, sizeof(size));
+ jalv_worker_emit_responses(host, &host->worker);
- jack_ringbuffer_read(
- host->worker.responses, host->worker.response, size);
-
- host->worker.iface->work_response(
- host->instance->lv2_handle, size, host->worker.response);
-
- read_space -= sizeof(size) + size;
- }
-
- if (host->worker.iface->end_run) {
- host->worker.iface->end_run(host->instance->lv2_handle);
- }
+ /* Notify the plugin the run() cycle is finished */
+ if (host->worker.iface->end_run) {
+ host->worker.iface->end_run(host->instance->lv2_handle);
}
/* Check if it's time to send updates to the UI */
@@ -638,54 +626,6 @@ jalv_emit_ui_events(Jalv* host)
return true;
}
-LV2_Worker_Status
-schedule_work(LV2_Worker_Schedule_Handle handle,
- uint32_t size,
- const void* data)
-{
- Jalv* jalv = (Jalv*)handle;
- jack_ringbuffer_write(jalv->worker.requests, (const char*)&size, sizeof(size));
- jack_ringbuffer_write(jalv->worker.requests, data, size);
- zix_sem_post(&jalv->worker.sem);
- return LV2_WORKER_SUCCESS;
-}
-
-LV2_Worker_Status
-worker_respond(LV2_Worker_Respond_Handle handle,
- uint32_t size,
- const void* data)
-{
- Jalv* jalv = (Jalv*)handle;
- jack_ringbuffer_write(jalv->worker.responses, (const char*)&size, sizeof(size));
- jack_ringbuffer_write(jalv->worker.responses, data, size);
- return LV2_WORKER_SUCCESS;
-}
-
-void*
-worker(void* data)
-{
- Jalv* jalv = (Jalv*)data;
- void* buf = NULL;
- while (true) {
- zix_sem_wait(&jalv->worker.sem);
- if (jalv->exit) {
- break;
- }
-
- uint32_t size = 0;
- jack_ringbuffer_read(jalv->worker.requests, (char*)&size, sizeof(size));
-
- buf = realloc(buf, size);
- jack_ringbuffer_read(jalv->worker.requests, buf, size);
-
- jalv->worker.iface->work(
- jalv->instance->lv2_handle, worker_respond, jalv, size, buf);
- }
-
- free(buf);
- return NULL;
-}
-
static void
signal_handler(int ignored)
{
@@ -744,7 +684,7 @@ main(int argc, char** argv)
LV2_State_Make_Path make_path = { &host, jalv_make_path };
make_path_feature.data = &make_path;
- LV2_Worker_Schedule schedule = { &host, schedule_work };
+ LV2_Worker_Schedule schedule = { &host, jalv_worker_schedule };
schedule_feature.data = &schedule;
zix_sem_init(&exit_sem, 0);
@@ -774,9 +714,10 @@ main(int argc, char** argv)
host.midi_class = lilv_new_uri(world, LILV_URI_MIDI_EVENT);
host.preset_class = lilv_new_uri(world, NS_PSET "Preset");
host.label_pred = lilv_new_uri(world, LILV_NS_RDFS "label");
+ host.work_interface = lilv_new_uri(world, LV2_WORKER__interface);
host.work_schedule = lilv_new_uri(world, LV2_WORKER__schedule);
host.optional = lilv_new_uri(world, LILV_NS_LV2
- "connectionOptional");
+ "connectionOptional");
/* Get plugin URI from loaded state or command line */
LilvState* state = NULL;
@@ -903,15 +844,12 @@ main(int argc, char** argv)
}
/* Create thread and ringbuffers for worker if necessary */
- if (lilv_plugin_has_feature(host.plugin, host.work_schedule)) {
- host.worker.iface = lilv_instance_get_extension_data(
- host.instance, LV2_WORKER__Interface);
- zix_thread_create(&host.worker.thread, 4096, worker, &host);
- host.worker.requests = jack_ringbuffer_create(4096);
- host.worker.responses = jack_ringbuffer_create(4096);
- host.worker.response = malloc(4096);
- jack_ringbuffer_mlock(host.worker.requests);
- jack_ringbuffer_mlock(host.worker.responses);
+ if (lilv_plugin_has_feature(host.plugin, host.work_schedule)
+ && lilv_plugin_has_extension_data(host.plugin, host.work_interface)) {
+ jalv_worker_init(
+ &host, &host.worker,
+ (LV2_Worker_Interface*)lilv_instance_get_extension_data(
+ host.instance, LV2_WORKER__interface));
}
/* Apply loaded state to plugin instance if necessary */
@@ -984,10 +922,8 @@ main(int argc, char** argv)
fprintf(stderr, "Exiting...\n");
- if (host.worker.requests) {
- zix_sem_post(&host.worker.sem);
- zix_thread_join(host.worker.thread, NULL);
- }
+ /* Terminate the worker */
+ jalv_worker_finish(&host.worker);
/* Deactivate JACK */
jack_deactivate(host.jack_client);
@@ -1009,11 +945,6 @@ main(int argc, char** argv)
jack_ringbuffer_free(host.ui_events);
jack_ringbuffer_free(host.plugin_events);
}
- if (host.worker.requests) {
- jack_ringbuffer_free(host.worker.requests);
- jack_ringbuffer_free(host.worker.responses);
- free(host.worker.response);
- }
lilv_node_free(native_ui_type);
lilv_node_free(host.input_class);
lilv_node_free(host.output_class);
diff --git a/src/jalv_internal.h b/src/jalv_internal.h
index 50e15e2..6378ec0 100644
--- a/src/jalv_internal.h
+++ b/src/jalv_internal.h
@@ -156,7 +156,8 @@ typedef struct {
LilvNode* output_class; ///< Output port class (URI)
LilvNode* preset_class; ///< Preset class (URI)
LilvNode* seq_class; ///< Atom sequence class (URI)
- LilvNode* work_schedule; ///< lv2:connectionOptional port property
+ LilvNode* work_interface; ///< Worker interface (URI)
+ LilvNode* work_schedule; ///< Worker schedule feature (URI)
uint32_t midi_event_id; ///< MIDI event class ID in event context
bool buf_size_set; ///< True iff buffer size callback fired
bool exit; ///< True if execution is finished
diff --git a/src/worker.c b/src/worker.c
new file mode 100644
index 0000000..ad7bf91
--- /dev/null
+++ b/src/worker.c
@@ -0,0 +1,110 @@
+/*
+ Copyright 2007-2012 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include "worker.h"
+
+static void*
+worker_func(void* data)
+{
+ Jalv* jalv = (Jalv*)data;
+ void* buf = NULL;
+ while (true) {
+ zix_sem_wait(&jalv->worker.sem);
+ if (jalv->exit) {
+ break;
+ }
+
+ uint32_t size = 0;
+ jack_ringbuffer_read(jalv->worker.requests, (char*)&size, sizeof(size));
+
+ buf = realloc(buf, size);
+ jack_ringbuffer_read(jalv->worker.requests, buf, size);
+
+ jalv->worker.iface->work(
+ jalv->instance->lv2_handle, jalv_worker_respond, jalv, size, buf);
+ }
+
+ free(buf);
+ return NULL;
+}
+
+void
+jalv_worker_init(Jalv* jalv, JalvWorker* worker, LV2_Worker_Interface* iface)
+{
+ worker->iface = iface;
+ zix_thread_create(&worker->thread, 4096, worker_func, jalv);
+ worker->requests = jack_ringbuffer_create(4096);
+ worker->responses = jack_ringbuffer_create(4096);
+ worker->response = malloc(4096);
+ jack_ringbuffer_mlock(worker->requests);
+ jack_ringbuffer_mlock(worker->responses);
+}
+
+void
+jalv_worker_finish(JalvWorker* worker)
+{
+ if (worker->requests) {
+ zix_sem_post(&worker->sem);
+ zix_thread_join(worker->thread, NULL);
+ jack_ringbuffer_free(worker->requests);
+ jack_ringbuffer_free(worker->responses);
+ free(worker->response);
+ }
+}
+
+LV2_Worker_Status
+jalv_worker_schedule(LV2_Worker_Schedule_Handle handle,
+ uint32_t size,
+ const void* data)
+{
+ Jalv* jalv = (Jalv*)handle;
+ jack_ringbuffer_write(jalv->worker.requests, (const char*)&size, sizeof(size));
+ jack_ringbuffer_write(jalv->worker.requests, data, size);
+ zix_sem_post(&jalv->worker.sem);
+ return LV2_WORKER_SUCCESS;
+}
+
+LV2_Worker_Status
+jalv_worker_respond(LV2_Worker_Respond_Handle handle,
+ uint32_t size,
+ const void* data)
+{
+ Jalv* jalv = (Jalv*)handle;
+ jack_ringbuffer_write(jalv->worker.responses, (const char*)&size, sizeof(size));
+ jack_ringbuffer_write(jalv->worker.responses, data, size);
+ return LV2_WORKER_SUCCESS;
+}
+
+void
+jalv_worker_emit_responses(Jalv* jalv, JalvWorker* worker)
+{
+ if (worker->responses) {
+ uint32_t read_space = jack_ringbuffer_read_space(worker->responses);
+ while (read_space) {
+ uint32_t size = 0;
+ jack_ringbuffer_read(worker->responses, (char*)&size, sizeof(size));
+
+ jack_ringbuffer_read(
+ worker->responses, worker->response, size);
+
+ worker->iface->work_response(
+ jalv->instance->lv2_handle, size, worker->response);
+
+ read_space -= sizeof(size) + size;
+ }
+
+ }
+}
diff --git a/src/worker.h b/src/worker.h
new file mode 100644
index 0000000..08b84fa
--- /dev/null
+++ b/src/worker.h
@@ -0,0 +1,40 @@
+/*
+ Copyright 2007-2012 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include "lv2/lv2plug.in/ns/ext/worker/worker.h"
+
+#include "jalv_internal.h"
+
+void
+jalv_worker_init(Jalv* jalv,
+ JalvWorker* worker,
+ LV2_Worker_Interface* iface);
+
+void
+jalv_worker_finish(JalvWorker* worker);
+
+LV2_Worker_Status
+jalv_worker_schedule(LV2_Worker_Schedule_Handle handle,
+ uint32_t size,
+ const void* data);
+
+LV2_Worker_Status
+jalv_worker_respond(LV2_Worker_Respond_Handle handle,
+ uint32_t size,
+ const void* data);
+
+void
+jalv_worker_emit_responses(Jalv* jalv, JalvWorker* worker);