diff options
-rw-r--r-- | src/jalv.c | 101 | ||||
-rw-r--r-- | src/jalv_internal.h | 3 | ||||
-rw-r--r-- | src/worker.c | 110 | ||||
-rw-r--r-- | src/worker.h | 40 | ||||
-rw-r--r-- | wscript | 2 |
5 files changed, 169 insertions, 87 deletions
@@ -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); @@ -71,7 +71,7 @@ def configure(conf): def build(bld): libs = 'LILV SUIL JACK SERD SRATOM LV2' - source = 'src/jalv.c src/symap.c src/state.c src/lv2_evbuf.c' + source = 'src/jalv.c src/symap.c src/state.c src/lv2_evbuf.c src/worker.c' # Non-GUI version obj = bld(features = 'c cprogram', |