use XML state to store processors in mixer (strips) and fixup crash caused by missing...
[ardour.git] / gtk2_ardour / ladspa_pluginui.cc
index 22b860900a64bea666c94b0fec49cc01dba7e253..ad1f8fbc7e2035a00512d9ddf85a8c25dffee818 100644 (file)
@@ -35,9 +35,8 @@
 
 #include <midi++/manager.h>
 
-#include <ardour/audioengine.h>
 #include <ardour/plugin.h>
-#include <ardour/insert.h>
+#include <ardour/plugin_insert.h>
 #include <ardour/ladspa_plugin.h>
 
 #include <lrdf.h>
@@ -47,6 +46,7 @@
 #include "plugin_ui.h"
 #include "utils.h"
 #include "gui_thread.h"
+#include "automation_controller.h"
 
 #include "i18n.h"
 
@@ -57,9 +57,8 @@ using namespace Gtkmm2ext;
 using namespace Gtk;
 using namespace sigc;
 
-LadspaPluginUI::LadspaPluginUI (AudioEngine &engine, boost::shared_ptr<PluginInsert> pi, bool scrollable)
-       : PlugUIBase (pi),
-         engine(engine),
+LadspaPluginUI::LadspaPluginUI (boost::shared_ptr<PluginInsert> pi, nframes64_t sample_rate, nframes64_t period_size, bool scrollable)
+       : PlugUIBase (pi, sample_rate, period_size),
          button_table (initial_button_rows, initial_button_cols),
          output_table (initial_output_rows, initial_output_cols),
          hAdjustment(0.0, 0.0, 0.0),
@@ -79,7 +78,11 @@ LadspaPluginUI::LadspaPluginUI (AudioEngine &engine, boost::shared_ptr<PluginIns
        Label* combo_label = manage (new Label (_("<span size=\"large\">Presets</span>")));
        combo_label->set_use_markup (true);
 
-       smaller_hbox->pack_start (*combo_label, false, false, 10);
+       Label* latency_label = manage (new Label (_("<span size=\"large\">Latency</span>")));
+       latency_label->set_use_markup (true);
+
+       smaller_hbox->pack_start (*latency_label, false, false, 10);
+       smaller_hbox->pack_start (latency_gui, false, false, 10);
        smaller_hbox->pack_start (combo, false, false);
        smaller_hbox->pack_start (save_button, false, false);
 
@@ -105,10 +108,11 @@ LadspaPluginUI::LadspaPluginUI (AudioEngine &engine, boost::shared_ptr<PluginIns
                pack_start (hpacker, false, false);
        }
 
-       insert->active_changed.connect (mem_fun(*this, &LadspaPluginUI::redirect_active_changed));
-       bypass_button.set_active (!insert->active());
+       pi->ActiveChanged.connect (bind(mem_fun(*this, &LadspaPluginUI::processor_active_changed),
+                               boost::weak_ptr<Processor>(pi)));
+       bypass_button.set_active (!pi->active());
        
-       build (engine);
+       build ();
 }
 
 LadspaPluginUI::~LadspaPluginUI ()
@@ -119,7 +123,7 @@ LadspaPluginUI::~LadspaPluginUI ()
 }
 
 void
-LadspaPluginUI::build (AudioEngine &engine)
+LadspaPluginUI::build ()
 
 {
        guint32 i = 0;
@@ -131,7 +135,6 @@ LadspaPluginUI::build (AudioEngine &engine)
        int button_row, button_col;
        int output_rows, output_cols;
        int button_rows, button_cols;
-       guint32 n_ins=0, n_outs = 0;
 
        prefheight = 30;
        hpacker.set_spacing (10);
@@ -179,7 +182,7 @@ LadspaPluginUI::build (AudioEngine &engine)
                        
                        /* Don't show latency control ports */
 
-                       if (plugin->describe_parameter (i) == X_("latency")) {
+                       if (plugin->describe_parameter (Parameter(PluginAutomation, i)) == X_("latency")) {
                                continue;
                        }
 
@@ -199,11 +202,11 @@ LadspaPluginUI::build (AudioEngine &engine)
                                        frame->add (*box);
                                        hpacker.pack_start(*frame,true,true);
 
-                                       x = 0;
+                                       x = 1;
                                }
                        }
 
-                       if ((cui = build_control_ui (engine, i, plugin->get_nth_control (i))) == 0) {
+                       if ((cui = build_control_ui (i, insert->control(Parameter(PluginAutomation, i)))) == 0) {
                                error << string_compose(_("Plugin Editor: could not build control element for port %1"), i) << endmsg;
                                continue;
                        }
@@ -266,9 +269,6 @@ LadspaPluginUI::build (AudioEngine &engine)
                } 
        }
 
-       n_ins = plugin->get_info()->n_inputs;
-       n_outs = plugin->get_info()->n_outputs;
-
        if (box->children().empty()) {
                hpacker.remove (*frame);
        }
@@ -294,28 +294,24 @@ LadspaPluginUI::ControlUI::ControlUI ()
        : automate_button (X_("")) // force creation of a label 
 {
        automate_button.set_name ("PluginAutomateButton");
-       ARDOUR_UI::instance()->tooltips().set_tip (automate_button,
-                                                  _("Automation control"));
+       ARDOUR_UI::instance()->tooltips().set_tip (automate_button, _("Automation control"));
 
-       /* don't fix the height, it messes up the bar controllers */
+       /* XXX translators: use a string here that will be at least as long
+          as the longest automation label (see ::automation_state_changed()
+          below). be sure to include a descender.
+       */
 
-       set_size_request_to_display_given_text (automate_button, X_("lngnuf"), 2, 2);
+       set_size_request_to_display_given_text (*automate_button.get_child(), _("Mgnual"), 5, 5);
 
        ignore_change = 0;
        display = 0;
        button = 0;
-       control = 0;
        clickbox = 0;
-       adjustment = 0;
        meterinfo = 0;
 }
 
 LadspaPluginUI::ControlUI::~ControlUI() 
 {
-       if (adjustment) {
-               delete adjustment;
-       }
-
        if (meterinfo) {
                delete meterinfo->meter;
                delete meterinfo;
@@ -327,9 +323,12 @@ LadspaPluginUI::automation_state_changed (ControlUI* cui)
 {
        /* update button label */
 
-       switch (insert->get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) {
+       // don't lock to avoid deadlock because we're triggered by
+       // AutomationControl::Changed() while the automation lock is taken
+       switch (insert->get_parameter_automation_state (cui->parameter(), false)
+                       & (Off|Play|Touch|Write)) {
        case Off:
-               cui->automate_button.set_label (_("Off"));
+               cui->automate_button.set_label (_("Manual"));
                break;
        case Play:
                cui->automate_button.set_label (_("Play"));
@@ -359,8 +358,7 @@ LadspaPluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
 }
 
 LadspaPluginUI::ControlUI*
-LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Controllable* mcontrol)
-
+LadspaPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<AutomationControl> mcontrol)
 {
        ControlUI* control_ui;
        Plugin::ParameterDescriptor desc;
@@ -368,10 +366,9 @@ LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::
        plugin->get_parameter_descriptor (port_index, desc);
 
        control_ui = manage (new ControlUI ());
-       control_ui->adjustment = 0;
        control_ui->combo = 0;
        control_ui->combo_map = 0;
-       control_ui->port_index = port_index;
+       control_ui->control = mcontrol;
        control_ui->update_pending = false;
        control_ui->label.set_text (desc.label);
        control_ui->label.set_alignment (0.0, 0.5);
@@ -379,6 +376,8 @@ LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::
 
        control_ui->set_spacing (5);
 
+       Gtk::Requisition req (control_ui->automate_button.size_request());
+
        if (plugin->parameter_is_input (port_index)) {
 
                boost::shared_ptr<LadspaPlugin> lp;
@@ -393,7 +392,7 @@ LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::
                                //control_ui->combo->set_value_in_list(true, false);
                                set_popdown_strings (*control_ui->combo, setup_scale_values(port_index, control_ui));
                                control_ui->combo->signal_changed().connect (bind (mem_fun(*this, &LadspaPluginUI::control_combo_changed), control_ui));
-                               plugin->ParameterChanged.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
+                               mcontrol->Changed.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
                                control_ui->pack_start(control_ui->label, true, true);
                                control_ui->pack_start(*control_ui->combo, false, true);
                                
@@ -424,54 +423,57 @@ LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::
 
                        return control_ui;
                }
+
+               /* create the controller */
        
-               control_ui->adjustment = new Adjustment (0, 0, 0, 0, 0);
+               control_ui->controller = AutomationController::create(insert, mcontrol->list(), mcontrol);
 
                /* XXX this code is not right yet, because it doesn't handle
                   the absence of bounds in any sensible fashion.
                */
 
-               control_ui->adjustment->set_lower (desc.lower);
-               control_ui->adjustment->set_upper (desc.upper);
+#if 0
+               control_ui->controller->adjustment()->set_lower (desc.lower);
+               control_ui->controller->adjustment()->set_upper (desc.upper);
 
                control_ui->logarithmic = desc.logarithmic;
                if (control_ui->logarithmic) {
-                       if (control_ui->adjustment->get_lower() == 0.0) {
-                               control_ui->adjustment->set_lower (control_ui->adjustment->get_upper()/10000);
+                       if (control_ui->controller->adjustment()->get_lower() == 0.0) {
+                               control_ui->controller->adjustment()->set_lower (control_ui->controller->adjustment()->get_upper()/10000);
                        }
-                       control_ui->adjustment->set_upper (log(control_ui->adjustment->get_upper()));
-                       control_ui->adjustment->set_lower (log(control_ui->adjustment->get_lower()));
+                       control_ui->controller->adjustment()->set_upper (log(control_ui->controller->adjustment()->get_upper()));
+                       control_ui->controller->adjustment()->set_lower (log(control_ui->controller->adjustment()->get_lower()));
                }
+               
        
                float delta = desc.upper - desc.lower;
 
-               control_ui->adjustment->set_page_size (delta/100.0);
-               control_ui->adjustment->set_step_increment (desc.step);
-               control_ui->adjustment->set_page_increment (desc.largestep);
+               control_ui->controller->adjustment()->set_page_size (delta/100.0);
+               control_ui->controller->adjustment()->set_step_increment (desc.step);
+               control_ui->controller->adjustment()->set_page_increment (desc.largestep);
+#endif
 
                if (desc.integer_step) {
-                       control_ui->clickbox = new ClickBox (control_ui->adjustment, "PluginUIClickBox");
+                       control_ui->clickbox = new ClickBox (control_ui->controller->adjustment(), "PluginUIClickBox");
                        Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2);
                        control_ui->clickbox->set_print_func (integer_printer, 0);
                } else {
-                       sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &LadspaPluginUI::print_parameter), (uint32_t) port_index);
+                       //sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &LadspaPluginUI::print_parameter), (uint32_t) port_index);
 
-                       control_ui->control = new BarController (*control_ui->adjustment, *mcontrol, pslot);
-                       // should really match the height of the text in the automation button+label
-                       control_ui->control->set_size_request (200, 22);
-                       control_ui->control->set_name (X_("PluginSlider"));
-                       control_ui->control->set_style (BarController::LeftToRight);
-                       control_ui->control->set_use_parent (true);
+                       control_ui->controller->set_size_request (200, req.height);
+                       control_ui->controller->set_name (X_("PluginSlider"));
+                       control_ui->controller->set_style (BarController::LeftToRight);
+                       control_ui->controller->set_use_parent (true);
 
-                       control_ui->control->StartGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::start_touch), control_ui));
-                       control_ui->control->StopGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::stop_touch), control_ui));
+                       control_ui->controller->StartGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::start_touch), control_ui));
+                       control_ui->controller->StopGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::stop_touch), control_ui));
                        
                }
 
                if (control_ui->logarithmic) {
-                       control_ui->adjustment->set_value(log(plugin->get_parameter(port_index)));
+                       control_ui->controller->adjustment()->set_value(log(plugin->get_parameter(port_index)));
                } else{
-                       control_ui->adjustment->set_value(plugin->get_parameter(port_index));
+                       control_ui->controller->adjustment()->set_value(plugin->get_parameter(port_index));
                }
 
                /* XXX memory leak: SliderController not destroyed by ControlUI
@@ -483,17 +485,16 @@ LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::
                if (desc.integer_step) {
                        control_ui->pack_start (*control_ui->clickbox, false, false);
                } else {
-                       control_ui->pack_start (*control_ui->control, false, false);
+                       control_ui->pack_start (*control_ui->controller, false, false);
                }
 
                control_ui->pack_start (control_ui->automate_button, false, false);
-               control_ui->adjustment->signal_value_changed().connect (bind (mem_fun(*this, &LadspaPluginUI::control_adjustment_changed), control_ui));
                control_ui->automate_button.signal_clicked().connect (bind (mem_fun(*this, &LadspaPluginUI::astate_clicked), control_ui, (uint32_t) port_index));
 
                automation_state_changed (control_ui);
 
-               plugin->ParameterChanged.connect (bind (mem_fun(*this, &LadspaPluginUI::parameter_changed), control_ui));
-               insert->automation_list (port_index).automation_state_changed.connect 
+               mcontrol->Changed.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
+               mcontrol->list()->automation_state_changed.connect 
                        (bind (mem_fun(*this, &LadspaPluginUI::automation_state_changed), control_ui));
 
        } else if (plugin->parameter_is_output (port_index)) {
@@ -543,20 +544,21 @@ LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::
                output_controls.push_back (control_ui);
        }
        
-       plugin->ParameterChanged.connect (bind (mem_fun(*this, &LadspaPluginUI::parameter_changed), control_ui));
+       mcontrol->Changed.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
+       
        return control_ui;
 }
 
 void
 LadspaPluginUI::start_touch (LadspaPluginUI::ControlUI* cui)
 {
-       insert->automation_list (cui->port_index).start_touch ();
+       cui->control->list()->start_touch ();
 }
 
 void
 LadspaPluginUI::stop_touch (LadspaPluginUI::ControlUI* cui)
 {
-       insert->automation_list (cui->port_index).stop_touch ();
+       cui->control->list()->stop_touch ();
 }
 
 void
@@ -572,7 +574,7 @@ LadspaPluginUI::astate_clicked (ControlUI* cui, uint32_t port)
        MenuList& items (automation_menu->items());
 
        items.clear ();
-       items.push_back (MenuElem (_("Off"), 
+       items.push_back (MenuElem (_("Manual"), 
                                   bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Off, cui)));
        items.push_back (MenuElem (_("Play"),
                                   bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Play, cui)));
@@ -581,39 +583,21 @@ LadspaPluginUI::astate_clicked (ControlUI* cui, uint32_t port)
        items.push_back (MenuElem (_("Touch"),
                                   bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Touch, cui)));
 
-       automation_menu->popup (1, 0);
+       automation_menu->popup (1, gtk_get_current_event_time());
 }
 
 void
 LadspaPluginUI::set_automation_state (AutoState state, ControlUI* cui)
 {
-       insert->set_port_automation_state (cui->port_index, state);
+       insert->set_parameter_automation_state (cui->parameter(), state);
 }
 
 void
-LadspaPluginUI::control_adjustment_changed (ControlUI* cui)
+LadspaPluginUI::parameter_changed (ControlUI* cui)
 {
-       if (cui->ignore_change) {
-               return;
-       }
-
-       double value = cui->adjustment->get_value();
-
-       if (cui->logarithmic) {
-               value = exp(value);
-       }
-
-       insert->set_parameter (cui->port_index, (float) value);
-}
-
-void
-LadspaPluginUI::parameter_changed (uint32_t abs_port_id, float val, ControlUI* cui)
-{
-       if (cui->port_index == abs_port_id) {
-               if (!cui->update_pending) {
-                       cui->update_pending = true;
-                       Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &LadspaPluginUI::update_control_display), cui));
-               }
+       if (!cui->update_pending) {
+               cui->update_pending = true;
+               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &LadspaPluginUI::update_control_display), cui));
        }
 }
 
@@ -624,7 +608,7 @@ LadspaPluginUI::update_control_display (ControlUI* cui)
        
        cui->update_pending = false;
 
-       float val = plugin->get_parameter (cui->port_index);
+       float val = cui->control->get_value();
 
        cui->ignore_change++;
        if (cui->combo) {
@@ -635,22 +619,26 @@ LadspaPluginUI::update_control_display (ControlUI* cui)
                                break;
                        }
                }
-       } else if (cui->adjustment == 0) {
+       } else if (cui->button) {
 
                if (val > 0.5) {
                        cui->button->set_active (true);
                } else {
                        cui->button->set_active (false);
                }
+       }
+
+       cui->controller->display_effective_value();
+
 
-       } else {
+       /*} else {
                if (cui->logarithmic) {
                        val = log(val);
                }
                if (val != cui->adjustment->get_value()) {
                        cui->adjustment->set_value (val);
                }
-       }
+       }*/
        cui->ignore_change--;
 }
 
@@ -658,7 +646,7 @@ void
 LadspaPluginUI::control_port_toggled (ControlUI* cui)
 {
        if (!cui->ignore_change) {
-               insert->set_parameter (cui->port_index, cui->button->get_active());
+               insert->set_parameter (cui->parameter(), cui->button->get_active());
        }
 }
 
@@ -668,17 +656,19 @@ LadspaPluginUI::control_combo_changed (ControlUI* cui)
        if (!cui->ignore_change) {
                string value = cui->combo->get_active_text();
                std::map<string,float> mapping = *cui->combo_map;
-               insert->set_parameter (cui->port_index, mapping[value]);
+               insert->set_parameter (cui->parameter(), mapping[value]);
        }
 
 }
 
 void
-LadspaPluginUI::redirect_active_changed (Redirect* r, void* src)
+LadspaPluginUI::processor_active_changed (boost::weak_ptr<Processor> weak_processor)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &LadspaPluginUI::redirect_active_changed), r, src));
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &LadspaPluginUI::processor_active_changed), weak_processor));
        
-       bypass_button.set_active (!r->active());
+       boost::shared_ptr<Processor> processor = weak_processor.lock();
+
+       bypass_button.set_active (!processor || !processor->active());
 }
 
 bool
@@ -705,7 +695,7 @@ void
 LadspaPluginUI::output_update ()
 {
        for (vector<ControlUI*>::iterator i = output_controls.begin(); i != output_controls.end(); ++i) {
-               float val = plugin->get_parameter ((*i)->port_index);
+               float val = plugin->get_parameter ((*i)->parameter().id());
                char buf[32];
                snprintf (buf, sizeof(buf), "%.2f", val);
                (*i)->display_label->set_text (buf);
@@ -757,3 +747,4 @@ LadspaPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
 
        return enums;
 }
+