connect lv2 output controls
authorGood Guy <[email protected]>
Sun, 27 May 2018 02:38:09 +0000 (20:38 -0600)
committerGood Guy <[email protected]>
Sun, 27 May 2018 02:38:09 +0000 (20:38 -0600)
cinelerra-5.1/cinelerra/pluginlv2.C
cinelerra-5.1/cinelerra/pluginlv2.h
cinelerra-5.1/cinelerra/pluginlv2client.C
cinelerra-5.1/cinelerra/pluginlv2config.C
cinelerra-5.1/cinelerra/pluginlv2config.h
cinelerra-5.1/cinelerra/pluginlv2gui.C
cinelerra-5.1/cinelerra/pluginlv2ui.C
cinelerra-5.1/cinelerra/pluginlv2ui.h

index 698be88ed605e45beee5fddca05b655f1dd7c1aa..bbfd76eaae7e3771cc6ca68fdb9806b180184f31 100644 (file)
@@ -53,11 +53,11 @@ void PluginLV2::reset_lv2()
        lilv_instance_free(inst);             inst = 0;
        lilv_uis_free(lilv_uis);              lilv_uis = 0;
 
-        lilv_node_free(lv2_InputPort);        lv2_InputPort = 0;
-        lilv_node_free(lv2_OutputPort);       lv2_OutputPort = 0;
+       lilv_node_free(lv2_InputPort);        lv2_InputPort = 0;
+       lilv_node_free(lv2_OutputPort);       lv2_OutputPort = 0;
        lilv_node_free(lv2_AudioPort);        lv2_AudioPort = 0;
        lilv_node_free(lv2_ControlPort);      lv2_ControlPort = 0;
-        lilv_node_free(lv2_CVPort);           lv2_CVPort = 0;
+       lilv_node_free(lv2_CVPort);           lv2_CVPort = 0;
 
        lilv_node_free(lv2_Optional);         lv2_Optional = 0;
        lilv_node_free(atom_AtomPort);        atom_AtomPort = 0;
@@ -124,7 +124,7 @@ int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate)
        boundedBlockLength  = lilv_new_uri(world, LV2_BUF_SIZE__boundedBlockLength);
        seq_out = (LV2_Atom_Sequence *) new char[sizeof(LV2_Atom_Sequence) + LV2_SEQ_SIZE];
 
-       conf.init_lv2(lilv);
+       conf.init_lv2(lilv, this);
        nb_inputs = nb_outputs = 0;
 
        for( int i=0; i<conf.nb_ports; ++i ) {
@@ -184,35 +184,33 @@ const char *PluginLV2::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid
        return ((PluginLV2UriTable *)handle)->unmap(urid);
 }
 
-void PluginLV2::connect_ports(PluginLV2ClientConfig &conf, int typ)
+void PluginLV2::connect_ports(PluginLV2ClientConfig &conf, int ports)
 {
        int ich = 0, och = 0;
        for( int i=0; i<conf.nb_ports; ++i ) {
                const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
                if( !lp ) continue;
-               if( (typ & TYP_CONTROL) &&
-                   lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
+               int port = conf.ports[i];
+               if( !(port & ports) ) continue;
+               if( (port & PORTS_CONTROL) ) {
                        lilv_instance_connect_port(inst, i, &conf.ctls[i]);
                        continue;
                }
-               if( (typ & TYP_AUDIO) &&
-                   ( lilv_port_is_a(lilv, lp, lv2_AudioPort) ||
-                     lilv_port_is_a(lilv, lp, lv2_CVPort) ) ) {
-                       if( lilv_port_is_a(lilv, lp, lv2_InputPort) ) {
-                               lilv_instance_connect_port(inst, iport[ich]=i, in_buffers[ich]);
-                               ++ich;
+               if( (port & PORTS_AUDIO) ) {
+                       if( (port & PORTS_INPUT) ) {
+                               lilv_instance_connect_port(inst, i, in_buffers[ich]);
+                               iport[ich++] = i;
                        }
-                       else if( lilv_port_is_a(lilv, lp, lv2_OutputPort)) {
-                               lilv_instance_connect_port(inst, oport[och]=i, out_buffers[och]);
-                               ++och;
+                       else if( (port & PORTS_OUTPUT) ) {
+                               lilv_instance_connect_port(inst, i, out_buffers[och]);
+                               oport[och++] = i;
                        }
                        continue;
                }
-               if( (typ & TYP_ATOM) &&
-                   lilv_port_is_a(lilv, lp, atom_AtomPort) ) {
-                       if( lilv_port_is_a(lilv, lp, lv2_InputPort) )
+               if( (port & PORTS_ATOM) ) {
+                       if( (port & PORTS_INPUT) )
                                lilv_instance_connect_port(inst, i, &seq_in);
-                       else
+                       else if( (port & PORTS_OUTPUT) )
                                lilv_instance_connect_port(inst, i, seq_out);
                        continue;
                }
@@ -373,12 +371,12 @@ PluginLV2UI::PluginLV2UI()
        lilv_type = 0;
        uri_map = 0;
 
-       done = 0;
+       done = -1;
        running = 0;
-       redraw = 0;
-       host_updates = updates = 0;
-       host_hidden = hidden = 1;
+       updates = 0;
+       hidden = 1;
        title[0] = 0;
+       child = 0;
 
 // only gtk-2
        gtk_type = "http://lv2plug.in/ns/extensions/ui#GtkUI";
index 9b449b48ab44e3d9f324fbd1457043f7cc79bcaf..01fc461f94baa8f61f9d701c05dd2602b3cf5a42 100644 (file)
@@ -15,10 +15,13 @@ typedef struct {
        int nb_inputs, nb_outputs;
 } shm_bfr_t;
 
-#define TYP_AUDIO   1
-#define TYP_CONTROL 2
-#define TYP_ATOM    4
-#define TYP_ALL    ~0
+#define PORTS_AUDIO   0x01
+#define PORTS_CONTROL 0x02
+#define PORTS_ATOM    0x04
+#define PORTS_ALL (PORTS_AUDIO | PORTS_CONTROL | PORTS_ATOM)
+#define PORTS_INPUT   0x08
+#define PORTS_OUTPUT  0x10
+#define PORTS_UPDATE  0x20
 
 class PluginLV2
 {
@@ -39,7 +42,7 @@ public:
 
        static LV2_URID uri_table_map(LV2_URID_Map_Handle handle, const char *uri);
        static const char *uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid);
-       void connect_ports(PluginLV2ClientConfig &conf, int typ=TYP_ALL);
+       void connect_ports(PluginLV2ClientConfig &conf, int ports);
        void del_buffer();
        void new_buffer(int64_t sz);
        shm_bfr_t *shm_buffer(int shmid);
@@ -77,7 +80,6 @@ public:
 };
 
 typedef struct { int sample_rate;  char path[1]; } open_bfr_t;
-typedef struct { int idx;  float value; } control_bfr_t;
 
 enum { NO_COMMAND,
        LV2_OPEN,
@@ -85,7 +87,6 @@ enum { NO_COMMAND,
        LV2_UPDATE,
        LV2_SHOW,
        LV2_HIDE,
-       LV2_SET,
        LV2_SHMID,
        NB_COMMANDS };
 
index 50df5ae664b7b49f22fa4758fb618ff103ba1f32..f327da81a533711c864c846eb0c84727a30c6308 100644 (file)
@@ -392,15 +392,11 @@ int PluginLV2ParentUI::handle_parent()
        case LV2_SHOW: {
                hidden = 0;
                break; }
-       case LV2_SET: {
-               if( !gui ) break;
-               control_bfr_t *ctl = (control_bfr_t *)parent_data;
-               gui->lv2_set(ctl->idx, ctl->value);
-               break; }
        case LV2_SHMID: {
                output_bfr->unlock();
                break; }
        case EXIT_CODE: {
+               hidden = 1;
                output_bfr->unlock();
                result = -1;
                break; }
index 66c9a498b8e17811d6d1314b81b6fd42debe4266..f104be00a1312abd29ec5a60c9e567363fc2edba 100644 (file)
@@ -23,6 +23,7 @@
 #include "arraylist.h"
 #include "cstrdup.h"
 #include "language.h"
+#include "pluginlv2.h"
 #include "pluginlv2config.h"
 
 #include <ctype.h>
@@ -127,6 +128,7 @@ PluginLV2ClientConfig::PluginLV2ClientConfig()
        mins = 0;
        maxs = 0;
        ctls = 0;
+       ports = 0;
        nb_ports = 0;
 }
 
@@ -142,10 +144,11 @@ void PluginLV2ClientConfig::reset()
                delete [] names[i];
                delete [] syms[i];
        }
-       delete [] names; names = 0;
-       delete [] mins;  mins = 0;
-       delete [] maxs;  maxs = 0;
-       delete [] ctls;  ctls = 0;
+       delete [] names;  names = 0;
+       delete [] mins;   mins = 0;
+       delete [] maxs;   maxs = 0;
+       delete [] ctls;   ctls = 0;
+       delete [] ports;  ports = 0;
        nb_ports = 0;
 }
 
@@ -171,6 +174,7 @@ void PluginLV2ClientConfig::copy_from(PluginLV2ClientConfig &that)
                mins  = new float[nb_ports];
                maxs  = new float[nb_ports];
                ctls  = new float[nb_ports];
+               ports = new int[nb_ports];
        }
        for( int i=0; i<nb_ports; ++i ) {
                delete [] names[i];  names[i] = cstrdup(that.names[i]);
@@ -178,6 +182,7 @@ void PluginLV2ClientConfig::copy_from(PluginLV2ClientConfig &that)
                mins[i] = that.mins[i];
                maxs[i] = that.maxs[i];
                ctls[i] = that.ctls[i];
+               ports[i] = ports[i];
        }
        remove_all_objects();
        for( int i=0; i<that.size(); ++i ) {
@@ -191,7 +196,7 @@ void PluginLV2ClientConfig::interpolate(PluginLV2ClientConfig &prev, PluginLV2Cl
        copy_from(prev);
 }
 
-void PluginLV2ClientConfig::init_lv2(const LilvPlugin *lilv)
+void PluginLV2ClientConfig::init_lv2(const LilvPlugin *lilv, PluginLV2 *lv2)
 {
        reset();
        nb_ports = lilv_plugin_get_num_ports(lilv);
@@ -200,6 +205,7 @@ void PluginLV2ClientConfig::init_lv2(const LilvPlugin *lilv)
        mins  = new float[nb_ports];
        maxs  = new float[nb_ports];
        ctls  = new float[nb_ports];
+       ports = new int[nb_ports];
        lilv_plugin_get_port_ranges_float(lilv, mins, maxs, ctls);
        for( int i=0; i<nb_ports; ++i ) {
                const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
@@ -208,6 +214,13 @@ void PluginLV2ClientConfig::init_lv2(const LilvPlugin *lilv)
                lilv_node_free(pnm);
                const LilvNode *sym = lilv_port_get_symbol(lilv, lp);
                syms[i] = cstrdup(lilv_node_as_string(sym));
+               int port = 0;
+               if( lilv_port_is_a(lilv, lp, lv2->lv2_AudioPort) )   port |= PORTS_AUDIO;
+               if( lilv_port_is_a(lilv, lp, lv2->lv2_ControlPort) ) port |= PORTS_CONTROL;
+               if( lilv_port_is_a(lilv, lp, lv2->lv2_InputPort) )   port |= PORTS_INPUT;
+               if( lilv_port_is_a(lilv, lp, lv2->lv2_OutputPort) )  port |= PORTS_OUTPUT;
+               if( lilv_port_is_a(lilv, lp, lv2->atom_AtomPort) )   port |= PORTS_ATOM;
+               ports[i] = port;
        }
 }
 
index c9b8b0661a5745fe231dfdf666ac1aa139babd9c..7f18461bdf20ded9418594c6e75eb457a6efb2a8 100644 (file)
@@ -27,6 +27,7 @@
 #include "guicast.h"
 #include "mutex.h"
 #include "pluginaclient.h"
+#include "pluginlv2.inc"
 #include "pluginlv2config.inc"
 #include "samples.inc"
 
@@ -123,11 +124,11 @@ public:
        void interpolate(PluginLV2ClientConfig &prev, PluginLV2ClientConfig &next,
                int64_t prev_frame, int64_t next_frame, int64_t current_frame);
        void reset();
-       void init_lv2(const LilvPlugin *lilv);
+       void init_lv2(const LilvPlugin *lilv, PluginLV2 *lv2);
        int update();
        void dump(FILE *fp);
 
-       int nb_ports;
+       int nb_ports, *ports;
        const char **names, **syms;
        float *mins, *maxs, *ctls;
 };
index 9e17f9cd8e5da8bb57f7e3865cefb2656021097d..e8c4edb3832ebbfda43a7315b24ace86a7b84a5e 100644 (file)
@@ -68,7 +68,7 @@ PluginLV2ClientReset::
 int PluginLV2ClientReset::handle_event()
 {
        PluginLV2Client *client = gui->client;
-       client->config.init_lv2(client->lilv);
+       client->config.init_lv2(client->lilv, client);
        client->config.update();
        client->update_lv2();
        gui->update(0);
@@ -271,10 +271,8 @@ void PluginLV2ClientWindow::update_selected()
        if( !selected ) return;
        PluginLV2ParentUI *ui = find_ui();
        if( !ui ) return;
-       control_bfr_t ctl_bfr;
-       ctl_bfr.idx = selected->idx;
-       ctl_bfr.value = selected->get_value();
-       ui->send_child(LV2_SET, &ctl_bfr, sizeof(ctl_bfr));
+       PluginLV2ClientConfig &conf = client->config;
+       ui->send_child(LV2_UPDATE, conf.ctls, sizeof(float)*conf.nb_ports);
 }
 
 int PluginLV2ClientWindow::scalar(float f, char *rp)
index 904f9549ddbbc55d10a29470c9c65a344f877f06..3e1c3ee9553ad354cc571b29cf42773d9c5829aa 100644 (file)
@@ -50,8 +50,7 @@ void PluginLV2UI::update_value(int idx, uint32_t bfrsz, uint32_t typ, const void
                PluginLV2Client_Opt *opt = config[i];
                if( opt->idx == idx ) {
                        opt->set_value(*(const float*)bfr);
-//printf("set %s = %f\n", opt->get_symbol(), opt->get_value());
-                       ++updates;
+                       updates = UPDATE_HOST;
                        break;
                }
        }
@@ -159,31 +158,46 @@ bool PluginLV2UI::lv2ui_resizable()
        return !fs_matches && !nrs_matches;
 }
 
-int PluginLV2UI::update_lv2(float *vals, int force)
+int PluginLV2UI::send_host(int64_t token, const void *data, int bytes)
+{
+       return !child ? 0 : child->send_parent(token, data, bytes);
+}
+
+int PluginLV2UI::update_lv2_input(float *vals, int force)
 {
        int ret = 0;
-       float *ctls = (float *)config.ctls;
+       float *ctls = config.ctls;
        for( int i=0; i<config.size(); ++i ) {
                int idx = config[i]->idx;
                float val = vals[idx];
                if( !force && ctls[idx] == val ) continue;
-               update_control(idx, sizeof(val), 0, &val);
+               ctls[idx] = val;
+               update_control(idx, sizeof(ctls[idx]), 0, &ctls[idx]);
                ++ret;
        }
-       for( int i=0; i<config.nb_ports; ++i ) ctls[i] = vals[i];
        return ret;
 }
 
+void PluginLV2UI::update_lv2_output()
+{
+       int *ports = config.ports;
+       float *ctls = config.ctls;
+       for( int i=0; i<config.nb_ports; ++i ) {
+               if( !(ports[i] & PORTS_UPDATE) ) continue;
+               ports[i] &= ~PORTS_UPDATE;
+               update_control(i, sizeof(ctls[i]), 0, &ctls[i]);
+       }
+}
+
 static void lilv_destroy(GtkWidget* widget, gpointer data)
 {
        PluginLV2UI *the = (PluginLV2UI*)data;
-       the->hidden = 1;
        the->top_level = 0;
-       ++the->updates;
 }
 
 void PluginLV2UI::start_gui()
 {
+       if( !hidden ) return;
        top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(top_level, "destroy", G_CALLBACK(lilv_destroy), this);
        gtk_window_set_title(GTK_WINDOW(top_level), title);
@@ -201,30 +215,25 @@ void PluginLV2UI::start_gui()
        gtk_window_set_resizable(GTK_WINDOW(top_level), lv2ui_resizable());
        gtk_widget_show_all(vbox);
        gtk_widget_grab_focus(widget);
-       float *ctls = (float *)config.ctls;
-       update_lv2(ctls, 1);
-       connect_ports(config, TYP_CONTROL);
-       lilv_instance_run(inst, 0);
+       update_lv2_input(config.ctls, 1);
+       connect_ports(config, PORTS_CONTROL);
+       updates = 0;
+       run_lilv(0);
        gtk_window_present(GTK_WINDOW(top_level));
+       send_host(LV2_SHOW, 0, 0);
+       hidden = 0;
 }
 
-
-void PluginLV2UI::host_update(PluginLV2ChildUI *child)
+void PluginLV2UI::update_host()
 {
-//printf("update\n");
-       host_updates = updates;
-       if( !child ) return;
-       if( host_hidden != hidden ) {
-               host_hidden = hidden;
-               if( hidden ) reset_gui();
-               child->send_parent(hidden ? LV2_HIDE : LV2_SHOW, 0, 0);
-       }
+// ignore update
        if( running < 0 ) { running = 1;  return; }
-       child->send_parent(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports);
+       send_host(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports);
 }
 
 void PluginLV2UI::reset_gui()
 {
+       if( hidden ) return;
        if( sinst )     { suil_instance_free(sinst);  sinst = 0; }
        if( ui_host )   { suil_host_free(ui_host);    ui_host = 0; }
        if( top_level ) { gtk_widget_destroy(top_level); top_level = 0; }
@@ -232,23 +241,29 @@ void PluginLV2UI::reset_gui()
        while( features.size() > ui_features ) features.remove_object();
        features.append(0);
        hidden = 1;
+       send_host(LV2_HIDE, 0, 0);
 }
 
 
 // child main
 int PluginLV2UI::run_ui(PluginLV2ChildUI *child)
 {
+       this->child = child;
        running = 1;
+       done = 0;
        while( !done ) {
                if( gtk_events_pending() ) {
                        gtk_main_iteration();
                        continue;
                }
-               if( running && host_updates != updates )
-                       host_update(child);
-               if( redraw ) {
-                       redraw = 0;
-                       update_lv2(config.ctls, 1);
+               if( !top_level && !hidden )
+                       reset_gui();
+               if( updates ) {
+                       if( (updates & UPDATE_PORTS) )
+                               update_lv2_output();
+                       if( (updates & UPDATE_HOST) )
+                               update_host();
+                       updates = 0;
                }
                if( !child ) usleep(10000);
                else if( child->child_iteration() < 0 )
@@ -258,13 +273,28 @@ int PluginLV2UI::run_ui(PluginLV2ChildUI *child)
        return 0;
 }
 
-void PluginLV2UI::run_buffer(int shmid)
+void PluginLV2UI::run_lilv(int samples)
+{
+       float ctls[config.nb_ports];
+       for( int i=0; i<config.nb_ports; ++i ) ctls[i] = config.ctls[i];
+
+       lilv_instance_run(inst, samples);
+
+       for( int i=0; i<config.nb_ports; ++i ) {
+               if( !(config.ports[i] & PORTS_OUTPUT) ) continue;
+               if( !(config.ports[i] & PORTS_CONTROL) ) continue;
+               if( config.ctls[i] == ctls[i] ) continue;
+               config.ports[i] |= PORTS_UPDATE;
+               updates |= UPDATE_PORTS;
+       }
+}
+
+void PluginLV2ChildUI::run_buffer(int shmid)
 {
        if( !shm_buffer(shmid) ) return;
        map_buffer();
-       int samples = shm_bfr->samples;
-       connect_ports(config);
-       lilv_instance_run(inst, samples);
+       connect_ports(config, PORTS_ALL);
+       run_lilv(shm_bfr->samples);
        shm_bfr->done = 1;
 }
 
@@ -276,25 +306,18 @@ int PluginLV2ChildUI::handle_child()
                if( init_ui(open_bfr->path, open_bfr->sample_rate) ) exit(1);
                break; }
        case LV2_LOAD: {
-               float *ctls = (float *)child_data;
-               update_lv2(ctls, 1);
+               float *vals = (float *)child_data;
+               update_lv2_input(vals, 1);
                break; }
        case LV2_UPDATE: {
-               float *ctls = (float *)child_data;
-               if( update_lv2(ctls, 0) > 0 )
-                       ++updates;
+               float *vals = (float *)child_data;
+               update_lv2_input(vals, 0);
                break; }
        case LV2_SHOW: {
                start_gui();
-               hidden = 0;  ++updates;
                break; }
        case LV2_HIDE: {
-               hidden = 1;  ++updates;
-               break; }
-       case LV2_SET: {
-               control_bfr_t *ctl_bfr = (control_bfr_t *)child_data;
-               config.ctls[ctl_bfr->idx] = ctl_bfr->value;
-               redraw = 1;
+               reset_gui();
                break; }
        case LV2_SHMID: {
                int shmid = *(int *)child_data;
index 75fe8262972c3928361f0f8c990f902add3b89dd..63a401027fe0df64849dd6cac675b13e538bc579 100644 (file)
@@ -32,6 +32,9 @@
 
 typedef struct _GtkWidget GtkWidget;
 
+#define UPDATE_HOST 1
+#define UPDATE_PORTS 2
+
 class PluginLV2UI : public PluginLV2
 {
 public:
@@ -49,19 +52,21 @@ public:
 
        char title[BCSTRLEN];
        PluginLV2ClientConfig config;
-       uint32_t host_updates, updates;
-       int host_hidden, hidden;
+       int updates, hidden;
        int done, running;
        const char *gtk_type;
        GtkWidget *top_level;
+       PluginLV2ChildUI *child;
 
        void reset_gui();
        int init_ui(const char *path, int sample_rate);
        void start();
        void stop();
-       int update_lv2(float *vals, int force);
-       int redraw;
+       int send_host(int64_t token, const void *data, int bytes);
+       int update_lv2_input(float *vals, int force);
+       void update_lv2_output();
 
+       void run_lilv(int samples);
        void update_value(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr);
        void update_control(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr);
        static void write_from_ui(void *the, uint32_t idx,
@@ -76,8 +81,7 @@ public:
        bool lv2ui_resizable();
        void start_gui();
        int run_ui(PluginLV2ChildUI *child=0);
-       void run_buffer(int shmid);
-       void host_update(PluginLV2ChildUI *child);
+       void update_host();
        int run(int ac, char **av);
 };
 
@@ -87,6 +91,7 @@ public:
        PluginLV2ChildUI();
        ~PluginLV2ChildUI();
        void run();
+       void run_buffer(int shmid);
 
        int handle_child();
        int run(int ac, char **av);