Merge branch 'master' into windows
[ardour.git] / libs / ardour / lv2_plugin.cc
index 95a29b7c8f517e49c7f436fc59ca415c59b077b8..6288616824c2b70c7c8689117059e7b5f57717eb 100644 (file)
@@ -25,6 +25,7 @@
 #include <cstdlib>
 #include <cstring>
 
+#include <glib/gstdio.h>
 #include <giomm/file.h>
 #include <glib/gprintf.h>
 #include <glibmm.h>
@@ -142,6 +143,7 @@ public:
        LilvNode* time_Position;
        LilvNode* ui_GtkUI;
        LilvNode* ui_external;
+       LilvNode* ui_externalkx;
 
 private:
        bool _bundle_checked;
@@ -561,11 +563,15 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
                if (!_impl->ui) {
                        LILV_FOREACH(uis, i, uis) {
                                const LilvUI* ui = lilv_uis_get(uis, i);
-                               if (lilv_ui_is_a(ui, _world.ui_external)) {
+                               if (lilv_ui_is_a(ui, _world.ui_externalkx)) {
                                        _impl->ui      = ui;
                                        _impl->ui_type = _world.ui_external;
                                        break;
                                }
+                               if (lilv_ui_is_a(ui, _world.ui_external)) {
+                                       _impl->ui      = ui;
+                                       _impl->ui_type = _world.ui_external;
+                               }
                        }
                }
        }
@@ -613,7 +619,16 @@ LV2Plugin::is_external_ui() const
        if (!_impl->ui) {
                return false;
        }
-       return lilv_ui_is_a(_impl->ui, _world.ui_external);
+       return lilv_ui_is_a(_impl->ui, _world.ui_external) || lilv_ui_is_a(_impl->ui, _world.ui_externalkx);
+}
+
+bool
+LV2Plugin::is_external_kx() const
+{
+       if (!_impl->ui) {
+               return false;
+       }
+       return lilv_ui_is_a(_impl->ui, _world.ui_externalkx);
 }
 
 bool
@@ -1090,7 +1105,7 @@ LV2Plugin::do_remove_preset(string name)
                        name + ".ttl"
                )
        );
-       unlink(preset_file.c_str());
+       ::g_unlink(preset_file.c_str());
 }
 
 bool
@@ -1118,16 +1133,16 @@ LV2Plugin::write_to(RingBuffer<uint8_t>* dest,
                     uint32_t             size,
                     const uint8_t*       body)
 {
-       const uint32_t buf_size = sizeof(UIMessage) + size;
-       uint8_t        buf[buf_size];
+       const uint32_t  buf_size = sizeof(UIMessage) + size;
+       vector<uint8_t> buf(buf_size);
 
-       UIMessage* msg = (UIMessage*)buf;
+       UIMessage* msg = (UIMessage*)&buf[0];
        msg->index    = index;
        msg->protocol = protocol;
        msg->size     = size;
        memcpy(msg + 1, body, size);
 
-       return (dest->write(buf, buf_size) == buf_size);
+       return (dest->write(&buf[0], buf_size) == buf_size);
 }
 
 bool
@@ -1137,8 +1152,20 @@ LV2Plugin::write_from_ui(uint32_t       index,
                          const uint8_t* body)
 {
        if (!_from_ui) {
-               _from_ui = new RingBuffer<uint8_t>(
-                       _session.engine().raw_buffer_size(DataType::MIDI) * NBUFS);
+               size_t rbs = _session.engine().raw_buffer_size(DataType::MIDI) * NBUFS;
+               /* buffer data communication from plugin UI to plugin instance.
+                * this buffer needs to potentially hold
+                *   (port's minimumSize) * (audio-periods) / (UI-periods)
+                * bytes.
+                *
+                *  e.g 48kSPS / 128fpp -> audio-periods = 375 Hz
+                *  ui-periods = 25 Hz (SuperRapidScreenUpdate)
+                *  default minimumSize = 32K (see LV2Plugin::allocate_atom_event_buffers()
+                *  -> 15 * 32K
+                * it is safe to overflow (but the plugin state may be inconsistent).
+                */
+               rbs = max((size_t) 32768 * 6, rbs);
+               _from_ui = new RingBuffer<uint8_t>(rbs);
        }
 
        if (!write_to(_from_ui, index, protocol, size, body)) {
@@ -1165,8 +1192,10 @@ void
 LV2Plugin::enable_ui_emmission()
 {
        if (!_to_ui) {
-               _to_ui = new RingBuffer<uint8_t>(
-                       _session.engine().raw_buffer_size(DataType::MIDI) * NBUFS);
+               /* see note in LV2Plugin::write_from_ui() */
+               size_t rbs = _session.engine().raw_buffer_size(DataType::MIDI) * NBUFS;
+               rbs = max((size_t) 32768 * 8, rbs);
+               _to_ui = new RingBuffer<uint8_t>(rbs);
        }
 }
 
@@ -1184,13 +1213,13 @@ LV2Plugin::emit_to_ui(void* controller, UIMessageSink sink)
                        error << "Error reading from Plugin=>UI RingBuffer" << endmsg;
                        break;
                }
-               uint8_t body[msg.size];
-               if (_to_ui->read(body, msg.size) != msg.size) {
+               vector<uint8_t> body(msg.size);
+               if (_to_ui->read(&body[0], msg.size) != msg.size) {
                        error << "Error reading from Plugin=>UI RingBuffer" << endmsg;
                        break;
                }
 
-               sink(controller, msg.index, msg.size, msg.protocol, body);
+               sink(controller, msg.index, msg.size, msg.protocol, &body[0]);
 
                read_space -= sizeof(msg) + msg.size;
        }
@@ -1353,11 +1382,6 @@ LV2Plugin::describe_parameter(Evoral::Parameter which)
                        return X_("hidden");
                }
 
-               if (lilv_port_has_property(_impl->plugin,
-                                       lilv_plugin_get_port_by_index(_impl->plugin, which.id()), _world.lv2_sampleRate)) {
-                       return X_("hidden");
-               }
-
                if (lilv_port_has_property(_impl->plugin,
                                        lilv_plugin_get_port_by_index(_impl->plugin, which.id()), _world.lv2_reportsLatency)) {
                        return X_("latency");
@@ -1670,15 +1694,15 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
                                error << "Error reading from UI=>Plugin RingBuffer" << endmsg;
                                break;
                        }
-                       uint8_t body[msg.size];
-                       if (_from_ui->read(body, msg.size) != msg.size) {
+                       vector<uint8_t> body(msg.size);
+                       if (_from_ui->read(&body[0], msg.size) != msg.size) {
                                error << "Error reading from UI=>Plugin RingBuffer" << endmsg;
                                break;
                        }
                        if (msg.protocol == urids.atom_eventTransfer) {
                                LV2_Evbuf*            buf  = _ev_buffers[msg.index];
                                LV2_Evbuf_Iterator    i    = lv2_evbuf_end(buf);
-                               const LV2_Atom* const atom = (const LV2_Atom*)body;
+                               const LV2_Atom* const atom = (const LV2_Atom*)&body[0];
                                if (!lv2_evbuf_write(&i, nframes, 0, atom->type, atom->size,
                                                (const uint8_t*)(atom + 1))) {
                                        error << "Failed to write data to LV2 event buffer\n";
@@ -1941,10 +1965,12 @@ LV2World::LV2World()
        time_Position      = lilv_new_uri(world, LV2_TIME__Position);
        ui_GtkUI           = lilv_new_uri(world, LV2_UI__GtkUI);
        ui_external        = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/ui#external");
+       ui_externalkx      = lilv_new_uri(world, "http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget");
 }
 
 LV2World::~LV2World()
 {
+       lilv_node_free(ui_externalkx);
        lilv_node_free(ui_external);
        lilv_node_free(ui_GtkUI);
        lilv_node_free(time_Position);
@@ -1982,7 +2008,7 @@ LV2World::load_bundled_plugins()
                vector<string *> *plugin_objects = scanner (ARDOUR::lv2_bundled_search_path().to_string(), lv2_filter, 0, true, true);
                if (plugin_objects) {
                        for ( vector<string *>::iterator x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
-#ifdef WINDOWS
+#ifdef PLATFORM_WINDOWS
                                string uri = "file:///" + **x + "/";
 #else
                                string uri = "file://" + **x + "/";