enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / gtk2_ardour / lv2_plugin_ui.cc
index e2c446ef20555de5b9ee6d1a46e40e67a55f85ad..75b3ff0bb89f7823e97f855972335611b8513f80 100644 (file)
@@ -31,7 +31,7 @@
 #include <lilv/lilv.h>
 #include <suil/suil.h>
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace ARDOUR;
 using namespace Gtk;
@@ -55,11 +55,11 @@ LV2PluginUI::write_from_ui(void*       controller,
                }
 
                boost::shared_ptr<AutomationControl> ac = me->_controllables[port_index];
-               /* Cache our local copy of the last value received from the GUI */
-               me->_values[port_index] = *(const float*) buffer;
-               /* Now update the control itself */
+
+               me->_updates.insert (port_index);
+
                if (ac) {
-                       ac->set_value(*(const float*)buffer);
+                       ac->set_value(*(const float*)buffer, Controllable::NoGroup);
                }
        } else if (format == URIMap::instance().urids.atom_eventTransfer) {
 
@@ -128,7 +128,7 @@ void
 LV2PluginUI::control_changed (uint32_t port_index)
 {
        /* Must run in GUI thread because we modify _updates with no lock */
-       if (_lv2->get_parameter (port_index) != _values[port_index]) {
+       if (_lv2->get_parameter (port_index) != _values_last_sent_to_ui[port_index]) {
                /* current plugin parameter does not match last value received
                   from GUI, so queue an update to push it to the GUI during
                   our regular timeout.
@@ -140,11 +140,9 @@ LV2PluginUI::control_changed (uint32_t port_index)
 bool
 LV2PluginUI::start_updating(GdkEventAny*)
 {
-       if (!_output_ports.empty()) {
-               _screen_update_connection.disconnect();
-               _screen_update_connection = Timers::super_rapid_connect
-                       (sigc::mem_fun(*this, &LV2PluginUI::output_update));
-       }
+       _screen_update_connection.disconnect();
+       _screen_update_connection = Timers::super_rapid_connect
+               (sigc::mem_fun(*this, &LV2PluginUI::output_update));
        return false;
 }
 
@@ -152,11 +150,21 @@ bool
 LV2PluginUI::stop_updating(GdkEventAny*)
 {
        //cout << "stop_updating" << endl;
+       _screen_update_connection.disconnect();
+       return false;
+}
 
-       if (!_output_ports.empty()) {
-               _screen_update_connection.disconnect();
+void
+LV2PluginUI::queue_port_update()
+{
+       const uint32_t num_ports = _lv2->num_ports();
+       for (uint32_t i = 0; i < num_ports; ++i) {
+               bool     ok;
+               uint32_t port = _lv2->nth_parameter(i, ok);
+               if (ok) {
+                       _updates.insert (port);
+               }
        }
-       return false;
 }
 
 void
@@ -180,14 +188,37 @@ LV2PluginUI::output_update()
                }
        }
 
-       if (_inst) {
-               for (Updates::iterator i = _updates.begin(); i != _updates.end(); ++i) {
-                       float val = _lv2->get_parameter (*i);
-                       /* push current value to the GUI */
-                       suil_instance_port_event ((SuilInstance*)_inst, (*i), 4, 0, &val);
+       if (!_inst) {
+               return;
+       }
+
+       /* output ports (values set by DSP) need propagating to GUI */
+
+       uint32_t nports = _output_ports.size();
+       for (uint32_t i = 0; i < nports; ++i) {
+               uint32_t index = _output_ports[i];
+               float val = _lv2->get_parameter (index);
+
+               if (val != _values_last_sent_to_ui[index]) {
+                       /* Send to GUI */
+                       suil_instance_port_event ((SuilInstance*)_inst, index, 4, 0, &val);
+                       /* Cache current value */
+                       _values_last_sent_to_ui[index] = val;
                }
-               _updates.clear ();
        }
+
+       /* Input ports marked for update because the control value changed
+          since the last redisplay.
+       */
+
+       for (Updates::iterator i = _updates.begin(); i != _updates.end(); ++i) {
+               float val = _lv2->get_parameter (*i);
+               /* push current value to the GUI */
+               suil_instance_port_event ((SuilInstance*)_inst, (*i), 4, 0, &val);
+               _values_last_sent_to_ui[(*i)] = val;
+       }
+
+       _updates.clear ();
 }
 
 LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
@@ -196,7 +227,7 @@ LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
        , _pi(pi)
        , _lv2(lv2p)
        , _gui_widget(NULL)
-       , _values(NULL)
+       , _values_last_sent_to_ui(NULL)
        , _external_ui_ptr(NULL)
        , _inst(NULL)
 {
@@ -210,6 +241,8 @@ LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
        _ardour_buttons_box.pack_end (add_button, false, false);
        _ardour_buttons_box.pack_end (_preset_combo, false, false);
        _ardour_buttons_box.pack_end (_preset_modified, false, false);
+
+       plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&LV2PluginUI::queue_port_update, this), gui_context ());
 }
 
 void
@@ -350,21 +383,29 @@ LV2PluginUI::lv2ui_instantiate(const std::string& title)
                _external_ui_ptr = (struct lv2_external_ui*)GET_WIDGET(_inst);
        }
 
-       _values = new float[num_ports];
+       _values_last_sent_to_ui = new float[num_ports];
        _controllables.resize(num_ports);
+
        for (uint32_t i = 0; i < num_ports; ++i) {
                bool     ok;
                uint32_t port = _lv2->nth_parameter(i, ok);
                if (ok) {
+                       /* Cache initial value of the parameter, regardless of
+                          whether it is input or output
+                       */
+
+                       _values_last_sent_to_ui[port]        = _lv2->get_parameter(port);
                        _controllables[port] = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (
                                insert->control(Evoral::Parameter(PluginAutomation, 0, port)));
 
-                       /* FIXME only works with control output ports (which is all we support now anyway) */
-                       if (_controllables[port] && _lv2->parameter_is_control(port) && _lv2->parameter_is_input(port)) {
-                               _controllables[port]->Changed.connect (control_connections, invalidator (*this), boost::bind (&LV2PluginUI::control_changed, this, port), gui_context());
-                               /* queue for first update ("push") to GUI */
-                               _updates.insert (port);
+                       if (_lv2->parameter_is_control(port) && _lv2->parameter_is_input(port)) {
+                               if (_controllables[port]) {
+                                       _controllables[port]->Changed.connect (control_connections, invalidator (*this), boost::bind (&LV2PluginUI::control_changed, this, port), gui_context());
+                               }
                        }
+
+                       /* queue for first update ("push") to GUI */
+                       _updates.insert (port);
                }
        }
 
@@ -401,7 +442,7 @@ LV2PluginUI::lv2ui_free()
 
 LV2PluginUI::~LV2PluginUI ()
 {
-       delete [] _values;
+       delete [] _values_last_sent_to_ui;
 
        _message_update_connection.disconnect();
        _screen_update_connection.disconnect();