diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jalv.c | 93 | ||||
-rw-r--r-- | src/jalv_gtk2.c | 13 | ||||
-rw-r--r-- | src/jalv_internal.h | 14 | ||||
-rw-r--r-- | src/jalv_qt4.cpp | 16 |
4 files changed, 101 insertions, 35 deletions
@@ -216,17 +216,27 @@ jack_process_cb(jack_nframes_t nframes, void* data) } /* Read and apply control change events from UI */ - ControlChange ev; - size_t ev_read_size = jack_ringbuffer_read_space(host->events); - for (size_t i = 0; i < ev_read_size; i += sizeof(ev)) { - jack_ringbuffer_read(host->events, (char*)&ev, sizeof(ev)); - host->ports[ev.index].control = ev.value; + if (host->ui) { + ControlChange ev; + size_t ev_read_size = jack_ringbuffer_read_space(host->ui_events); + for (size_t i = 0; i < ev_read_size; i += sizeof(ev)) { + jack_ringbuffer_read(host->ui_events, (char*)&ev, sizeof(ev)); + host->ports[ev.index].control = ev.value; + } } /* Run plugin for this cycle */ lilv_instance_run(host->instance, nframes); - /* Deliver MIDI output */ + /* Check if it's time to send updates to the UI */ + host->event_delta_t += nframes; + bool send_ui_updates = false; + if (host->ui && (host->event_delta_t > host->sample_rate / JALV_UI_UPDATE_HZ)) { + send_ui_updates = true; + host->event_delta_t = 0; + } + + /* Deliver MIDI output and UI events */ for (uint32_t p = 0; p < host->num_ports; ++p) { if (host->ports[p].jack_port && !host->ports[p].is_input @@ -246,6 +256,11 @@ jack_process_cb(jack_nframes_t nframes, void* data) jack_midi_event_write(buf, ev->frames, data, ev->size); lv2_event_increment(&iter); } + } else if (send_ui_updates + && !host->ports[p].is_input + && host->ports[p].type == CONTROL) { + const ControlChange ev = { p, host->ports[p].control }; + jack_ringbuffer_write(host->plugin_events, (const char*)&ev, sizeof(ev)); } } @@ -287,12 +302,28 @@ lv2_ui_write(SuilController controller, uint32_t format, const void* buffer) { + if (format != 0) { + return; + } Jalv* host = (Jalv*)controller; - // FIXME: not guaranteed to be a float change... const ControlChange ev = { port_index, *(float*)buffer }; - jack_ringbuffer_write(host->events, (const char*)&ev, sizeof(ev)); + jack_ringbuffer_write(host->ui_events, (const char*)&ev, sizeof(ev)); +} + +bool +jalv_emit_ui_events(Jalv* host) +{ + ControlChange ev; + size_t ev_read_size = jack_ringbuffer_read_space(host->plugin_events); + for (size_t i = 0; i < ev_read_size; i += sizeof(ev)) { + jack_ringbuffer_read(host->plugin_events, (char*)&ev, sizeof(ev)); + suil_instance_port_event(host->ui_instance, ev.index, + sizeof(float), 0, &ev.value); + } + + return true; } static void @@ -307,9 +338,12 @@ main(int argc, char** argv) jalv_init(&argc, &argv); Jalv host; - host.jack_client = NULL; - host.num_ports = 0; - host.ports = NULL; + host.jack_client = NULL; + host.num_ports = 0; + host.ports = NULL; + host.ui_events = NULL; + host.plugin_events = NULL; + host.event_delta_t = 0; host.symap = symap_new(); uri_map.callback_data = &host; @@ -317,9 +351,6 @@ main(int argc, char** argv) "http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/ext/midi#MidiEvent"); - host.events = jack_ringbuffer_create(4096); - jack_ringbuffer_mlock(host.events); - sem_init(&exit_sem, 0, 0); host.done = &exit_sem; @@ -369,8 +400,8 @@ main(int argc, char** argv) /* Get a plugin UI */ LilvNode* native_ui_type = jalv_native_ui_type(&host); - const LilvUI* ui = NULL; const LilvNode* ui_type = NULL; + host.ui = NULL; if (native_ui_type) { LilvUIs* uis = lilv_plugin_get_uis(host.plugin); // FIXME: leak LILV_FOREACH(uis, u, uis) { @@ -380,15 +411,20 @@ main(int argc, char** argv) native_ui_type, &ui_type)) { // TODO: Multiple UI support - ui = this_ui; + host.ui = this_ui; break; } } } - if (ui) { + if (host.ui) { fprintf(stderr, "UI: %s\n", - lilv_node_as_uri(lilv_ui_get_uri(ui))); + lilv_node_as_uri(lilv_ui_get_uri(host.ui))); + + host.ui_events = jack_ringbuffer_create(4096); + host.plugin_events = jack_ringbuffer_create(4096); + jack_ringbuffer_mlock(host.ui_events); + jack_ringbuffer_mlock(host.plugin_events); } else { fprintf(stderr, "No appropriate UI found\n"); } @@ -456,27 +492,27 @@ main(int argc, char** argv) /* Activate plugin and JACK */ lilv_instance_activate(host.instance); jack_activate(host.jack_client); + host.sample_rate = jack_get_sample_rate(host.jack_client); - SuilHost* ui_host = NULL; - SuilInstance* ui_instance = NULL; - if (ui) { + SuilHost* ui_host = NULL; + if (host.ui) { /* Instantiate UI */ ui_host = suil_host_new(lv2_ui_write, NULL, NULL, NULL); - ui_instance = suil_instance_new( + host.ui_instance = suil_instance_new( ui_host, &host, lilv_node_as_uri(native_ui_type), lilv_node_as_uri(lilv_plugin_get_uri(host.plugin)), - lilv_node_as_uri(lilv_ui_get_uri(ui)), + lilv_node_as_uri(lilv_ui_get_uri(host.ui)), lilv_node_as_uri(ui_type), - lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(ui))), - lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(ui))), + lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(host.ui))), + lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(host.ui))), features); } /* Run UI (or prompt at console) */ - jalv_open_ui(&host, ui_instance); + jalv_open_ui(&host, host.ui_instance); /* Wait for finish signal from UI or signal handler */ sem_wait(&exit_sem); @@ -498,7 +534,8 @@ main(int argc, char** argv) /* Clean up */ free(host.ports); - jack_ringbuffer_free(host.events); + jack_ringbuffer_free(host.ui_events); + jack_ringbuffer_free(host.plugin_events); lilv_node_free(native_ui_type); lilv_node_free(host.input_class); lilv_node_free(host.output_class); @@ -508,7 +545,7 @@ main(int argc, char** argv) lilv_node_free(host.midi_class); lilv_node_free(host.optional); symap_free(host.symap); - suil_instance_free(ui_instance); + suil_instance_free(host.ui_instance); suil_host_free(ui_host); lilv_world_free(world); diff --git a/src/jalv_gtk2.c b/src/jalv_gtk2.c index 72c8a1a..59e9772 100644 --- a/src/jalv_gtk2.c +++ b/src/jalv_gtk2.c @@ -46,10 +46,10 @@ jalv_open_ui(Jalv* jalv, SuilInstance* instance) { GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - + g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL); - + gtk_container_set_border_width(GTK_CONTAINER(window), 8); if (instance) { @@ -57,11 +57,11 @@ jalv_open_ui(Jalv* jalv, gtk_container_add(GTK_CONTAINER(window), widget); } else { GtkWidget* button = gtk_button_new_with_label("Close"); - + g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), window); - + gtk_container_add(GTK_CONTAINER(window), button); } @@ -69,7 +69,10 @@ jalv_open_ui(Jalv* jalv, gtk_window_set_resizable(GTK_WINDOW(window), false); gtk_widget_show_all(window); - + + g_timeout_add(1000 / JALV_UI_UPDATE_HZ, + (GSourceFunc)jalv_emit_ui_events, jalv); + gtk_main(); sem_post(jalv->done); return 0; diff --git a/src/jalv_internal.h b/src/jalv_internal.h index 5ee7755..950d1b7 100644 --- a/src/jalv_internal.h +++ b/src/jalv_internal.h @@ -32,16 +32,23 @@ extern "C" { #endif +#define JALV_UI_UPDATE_HZ 15 + typedef struct { LilvWorld* world; /**< Lilv World */ Symap* symap; /**< Symbol (URI) map */ jack_client_t* jack_client; /**< Jack client */ - jack_ringbuffer_t* events; /**< Control change events */ + jack_ringbuffer_t* ui_events; /**< Port events from UI */ + jack_ringbuffer_t* plugin_events; /**< Port events from plugin */ sem_t* done; /**< Exit semaphore */ const LilvPlugin* plugin; /**< Plugin class (RDF data) */ + const LilvUI* ui; /**< Plugin UI (RDF data) */ LilvInstance* instance; /**< Plugin instance (shared library) */ - uint32_t num_ports; /**< Size of the two following arrays: */ + SuilInstance* ui_instance; /**< Plugin UI instance (shared library) */ struct Port* ports; /**< Port array of size num_ports */ + uint32_t num_ports; /**< Size of the two following arrays: */ + jack_nframes_t sample_rate; /**< Sample rate */ + jack_nframes_t event_delta_t; /**< Frames since last update sent to UI */ LilvNode* input_class; /**< Input port class (URI) */ LilvNode* output_class; /**< Output port class (URI) */ LilvNode* control_class; /**< Control port class (URI) */ @@ -62,6 +69,9 @@ int jalv_open_ui(Jalv* jalv, SuilInstance* instance); +bool +jalv_emit_ui_events(Jalv* jalv); + #ifdef __cplusplus } // extern "C" diff --git a/src/jalv_qt4.cpp b/src/jalv_qt4.cpp index 79cf985..eac67ec 100644 --- a/src/jalv_qt4.cpp +++ b/src/jalv_qt4.cpp @@ -19,6 +19,7 @@ #include <QApplication> #include <QPushButton> #include <QMainWindow> +#include <QTimer> static QApplication* app = NULL; @@ -37,6 +38,18 @@ jalv_native_ui_type(Jalv* jalv) "http://lv2plug.in/ns/extensions/ui#Qt4UI"); } +class Timer : public QTimer { +public: + Timer(Jalv* j) : jalv(j) {} + + void timerEvent(QTimerEvent* e) { + jalv_emit_ui_events(jalv); + } + +private: + Jalv* jalv; +}; + int jalv_open_ui(Jalv* jalv, SuilInstance* instance) @@ -51,6 +64,9 @@ jalv_open_ui(Jalv* jalv, } app->connect(app, SIGNAL(lastWindowClosed()), app, SLOT(quit())); + Timer* timer = new Timer(jalv); + timer->start(1000 / JALV_UI_UPDATE_HZ); + int ret = app->exec(); sem_post(jalv->done); return ret; |