first compilable version of tabbable design.
[ardour.git] / gtk2_ardour / plugin_ui.cc
index 440dc805316c713cb15c8f1340d81bed6dc27a49..833055eff7aa80a4c7c6eaad9655757688524083 100644 (file)
@@ -58,7 +58,6 @@
 #endif
 
 #include "ardour_window.h"
-#include "ardour_ui.h"
 #include "prompter.h"
 #include "plugin_ui.h"
 #include "utils.h"
@@ -68,6 +67,7 @@
 #include "latency_gui.h"
 #include "plugin_eq_gui.h"
 #include "new_plugin_preset_dialog.h"
+#include "tooltips.h"
 
 #include "i18n.h"
 
@@ -100,7 +100,7 @@ PluginUIWindow::PluginUIWindow (
                case ARDOUR::Windows_VST:
                        have_gui = create_windows_vst_editor (insert);
                        break;
-                       
+
                case ARDOUR::LXVST:
                        have_gui = create_lxvst_editor (insert);
                        break;
@@ -178,9 +178,9 @@ PluginUIWindow::on_show ()
 
        if (_pluginui) {
 #if defined (HAVE_AUDIOUNITS) && defined(GTKOSX)
-                if (pre_deactivate_x >= 0) {                                                                             
+                if (pre_deactivate_x >= 0) {
                         move (pre_deactivate_x, pre_deactivate_y);
-                }                                                      
+                }
 #endif
 
                if (_pluginui->on_window_show (_title)) {
@@ -193,7 +193,7 @@ void
 PluginUIWindow::on_hide ()
 {
 #if defined (HAVE_AUDIOUNITS) && defined(GTKOSX)
-        get_position (pre_deactivate_x, pre_deactivate_y);                                                               
+        get_position (pre_deactivate_x, pre_deactivate_y);
 #endif
 
        Window::on_hide ();
@@ -333,6 +333,7 @@ PluginUIWindow::create_lv2_editor(boost::shared_ptr<PluginInsert> insert)
                _pluginui = lpu;
                add (*lpu);
                lpu->package (*this);
+               _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
        }
 
        return true;
@@ -352,10 +353,11 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
 {
        if (_keyboard_focused) {
                if (_pluginui) {
+                       _pluginui->grab_focus();
                        if (_pluginui->non_gtk_gui()) {
                                _pluginui->forward_key_event (event);
                        } else {
-                               return relay_key_press (event, this);
+                                       return relay_key_press (event, this);
                        }
                }
                return true;
@@ -365,13 +367,14 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
                */
 
                if (_pluginui) {
+                       _pluginui->grab_focus();
                        if (_pluginui->non_gtk_gui()) {
                                /* pass editor window as the window for the event
                                   to be handled in, not this one, because there are
                                   no widgets in this window that we want to have
                                   key focus.
                                */
-                               return relay_key_press (event, &PublicEditor::instance());
+                               return relay_key_press (event, 0);
                        } else {
                                return relay_key_press (event, this);
                        }
@@ -415,6 +418,7 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
        , add_button (_("Add"))
        , save_button (_("Save"))
        , delete_button (_("Delete"))
+       , reset_button (_("Reset"))
        , bypass_button (ArdourButton::led_default_elements)
        , description_expander (_("Description"))
        , plugin_analysis_expander (_("Plugin analysis"))
@@ -423,32 +427,37 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
        , eqgui (0)
 {
        _preset_modified.set_size_request (16, -1);
-       _preset_combo.signal_changed().connect(sigc::mem_fun(*this, &PlugUIBase::preset_selected));
-       ARDOUR_UI::instance()->set_tip (_preset_combo, _("Presets (if any) for this plugin\n(Both factory and user-created)"));
-       ARDOUR_UI::instance()->set_tip (add_button, _("Save a new preset"));
-       ARDOUR_UI::instance()->set_tip (save_button, _("Save the current preset"));
-       ARDOUR_UI::instance()->set_tip (delete_button, _("Delete the current preset"));
-       ARDOUR_UI::instance()->set_tip (bypass_button, _("Disable signal processing by the plugin"));
+       _preset_combo.set_text("(default)");
+       set_tooltip (_preset_combo, _("Presets (if any) for this plugin\n(Both factory and user-created)"));
+       set_tooltip (add_button, _("Save a new preset"));
+       set_tooltip (save_button, _("Save the current preset"));
+       set_tooltip (delete_button, _("Delete the current preset"));
+       set_tooltip (reset_button, _("Reset parameters to default (if no parameters are in automation play mode)"));
+       set_tooltip (bypass_button, _("Disable signal processing by the plugin"));
        _no_load_preset = 0;
 
        update_preset_list ();
        update_preset ();
 
-       add_button.set_name ("PluginAddButton");
-       add_button.signal_clicked().connect (sigc::mem_fun (*this, &PlugUIBase::add_plugin_setting));
+       add_button.set_name ("generic button");
+       add_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::add_plugin_setting));
+
+       save_button.set_name ("generic button");
+       save_button.signal_clicked.connect(sigc::mem_fun(*this, &PlugUIBase::save_plugin_setting));
+
+       delete_button.set_name ("generic button");
+       delete_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::delete_plugin_setting));
 
-       save_button.set_name ("PluginSaveButton");
-       save_button.signal_clicked().connect(sigc::mem_fun(*this, &PlugUIBase::save_plugin_setting));
+       reset_button.set_name ("generic button");
+       reset_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::reset_plugin_parameters));
 
-       delete_button.set_name ("PluginDeleteButton");
-       delete_button.signal_clicked().connect (sigc::mem_fun (*this, &PlugUIBase::delete_plugin_setting));
 
        insert->ActiveChanged.connect (active_connection, invalidator (*this), boost::bind (&PlugUIBase::processor_active_changed, this,  boost::weak_ptr<Processor>(insert)), gui_context());
 
        bypass_button.set_name ("plugin bypass button");
        bypass_button.set_text (_("Bypass"));
        bypass_button.set_active (!pi->active());
-       bypass_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PlugUIBase::bypass_button_release));
+       bypass_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PlugUIBase::bypass_button_release), false);
        focus_button.add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
 
        focus_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PlugUIBase::focus_toggled));
@@ -461,8 +470,8 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
 
        focus_button.add (*focus_out_image);
 
-       ARDOUR_UI::instance()->set_tip (focus_button, string_compose (_("Click to allow the plugin to receive keyboard events that %1 would normally use as a shortcut"), PROGRAM_NAME));
-       ARDOUR_UI::instance()->set_tip (bypass_button, _("Click to enable/disable this plugin"));
+       set_tooltip (focus_button, string_compose (_("Click to allow the plugin to receive keyboard events that %1 would normally use as a shortcut"), PROGRAM_NAME));
+       set_tooltip (bypass_button, _("Click to enable/disable this plugin"));
 
        description_expander.property_expanded().signal_changed().connect( sigc::mem_fun(*this, &PlugUIBase::toggle_description));
        description_expander.set_expanded(false);
@@ -475,7 +484,11 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
        plugin->PresetAdded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
        plugin->PresetRemoved.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
        plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset, this), gui_context ());
-       plugin->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::parameter_changed, this, _1, _2), gui_context ());
+       plugin->PresetDirty.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset_modified, this), gui_context ());
+
+       insert->AutomationStateChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::automation_state_changed, this), gui_context());
+
+       automation_state_changed();
 }
 
 PlugUIBase::~PlugUIBase()
@@ -506,7 +519,7 @@ PlugUIBase::set_latency_label ()
                t = string_compose (_("latency (%1 ms)"), (float) l / ((float) sr / 1000.0f));
        }
 
-       latency_label.set_text (t);
+       latency_button.set_text (t);
 }
 
 void
@@ -542,20 +555,13 @@ PlugUIBase::processor_active_changed (boost::weak_ptr<Processor> weak_p)
 }
 
 void
-PlugUIBase::preset_selected ()
+PlugUIBase::preset_selected (Plugin::PresetRecord preset)
 {
        if (_no_load_preset) {
                return;
        }
-
-       if (_preset_combo.get_active_text().length() > 0) {
-               const Plugin::PresetRecord* pr = plugin->preset_by_label (_preset_combo.get_active_text());
-               if (pr) {
-                       plugin->load_preset (*pr);
-               } else {
-                       warning << string_compose(_("Plugin preset %1 not found"),
-                                                 _preset_combo.get_active_text()) << endmsg;
-               }
+       if (!preset.label.empty()) {
+               plugin->load_preset (preset);
        } else {
                // blank selected = no preset
                plugin->clear_preset();
@@ -564,13 +570,26 @@ PlugUIBase::preset_selected ()
 
 #ifdef NO_PLUGIN_STATE
 static bool seen_saving_message = false;
+
+static void show_no_plugin_message()
+{
+       info << string_compose (_("Plugin presets are not supported in this build of %1. Consider paying for a full version"),
+                       PROGRAM_NAME)
+            << endmsg;
+       info << _("To get full access to updates without this limitation\n"
+                 "consider becoming a subscriber for a low cost every month.")
+            << endmsg;
+       info << X_("https://community.ardour.org/s/subscribe")
+            << endmsg;
+       ARDOUR_UI::instance()->popup_error(_("Plugin presets are not supported in this build, see the Log window for more information."));
+}
 #endif
 
 void
 PlugUIBase::add_plugin_setting ()
 {
 #ifndef NO_PLUGIN_STATE
-       NewPluginPresetDialog d (plugin);
+       NewPluginPresetDialog d (plugin, _("New Preset"));
 
        switch (d.run ()) {
        case Gtk::RESPONSE_ACCEPT:
@@ -588,12 +607,10 @@ PlugUIBase::add_plugin_setting ()
                }
                break;
        }
-#else 
+#else
        if (!seen_saving_message) {
-               info << string_compose (_("Plugin presets are not supported in this build of %1. Consider paying for a full version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
                seen_saving_message = true;
+               show_no_plugin_message();
        }
 #endif
 }
@@ -602,18 +619,16 @@ void
 PlugUIBase::save_plugin_setting ()
 {
 #ifndef NO_PLUGIN_STATE
-       string const name = _preset_combo.get_active_text ();
+       string const name = _preset_combo.get_text ();
        plugin->remove_preset (name);
        Plugin::PresetRecord const r = plugin->save_preset (name);
        if (!r.uri.empty ()) {
                plugin->load_preset (r);
        }
-#else 
+#else
        if (!seen_saving_message) {
-               info << string_compose (_("Plugin presets are not supported in this build of %1. Consider paying for a newer version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
                seen_saving_message = true;
+               show_no_plugin_message();
        }
 #endif
 }
@@ -622,22 +637,32 @@ void
 PlugUIBase::delete_plugin_setting ()
 {
 #ifndef NO_PLUGIN_STATE
-       plugin->remove_preset (_preset_combo.get_active_text ());
+       plugin->remove_preset (_preset_combo.get_text ());
 #else
        if (!seen_saving_message) {
-               info << string_compose (_("Plugin presets are not supported in this build of %1. Consider paying for a newer version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
                seen_saving_message = true;
+               show_no_plugin_message();
        }
 #endif
 }
 
+void
+PlugUIBase::automation_state_changed ()
+{
+       reset_button.set_sensitive (insert->can_reset_all_parameters());
+}
+
+void
+PlugUIBase::reset_plugin_parameters ()
+{
+       insert->reset_parameters_to_default ();
+}
+
 bool
 PlugUIBase::bypass_button_release (GdkEventButton*)
 {
        bool view_says_bypassed = (bypass_button.active_state() != 0);
-       
+
        if (view_says_bypassed != insert->active()) {
                if (view_says_bypassed) {
                        insert->activate ();
@@ -657,14 +682,14 @@ PlugUIBase::focus_toggled (GdkEventButton*)
                focus_button.remove ();
                focus_button.add (*focus_out_image);
                focus_out_image->show ();
-               ARDOUR_UI::instance()->set_tip (focus_button, string_compose (_("Click to allow the plugin to receive keyboard events that %1 would normally use as a shortcut"), PROGRAM_NAME));
+               set_tooltip (focus_button, string_compose (_("Click to allow the plugin to receive keyboard events that %1 would normally use as a shortcut"), PROGRAM_NAME));
                KeyboardFocused (false);
        } else {
                Keyboard::the_keyboard().magic_widget_grab_focus();
                focus_button.remove ();
                focus_button.add (*focus_in_image);
                focus_in_image->show ();
-               ARDOUR_UI::instance()->set_tip (focus_button, string_compose (_("Click to allow normal use of %1 keyboard shortcuts"), PROGRAM_NAME));
+               set_tooltip (focus_button, string_compose (_("Click to allow normal use of %1 keyboard shortcuts"), PROGRAM_NAME));
                KeyboardFocused (true);
        }
 
@@ -687,7 +712,7 @@ PlugUIBase::toggle_description()
                description_expander.add(*label);
                description_expander.show_all();
        }
-       
+
        if (!description_expander.get_expanded()) {
                description_expander.remove();
        }
@@ -733,18 +758,23 @@ PlugUIBase::toggle_plugin_analysis()
 void
 PlugUIBase::update_preset_list ()
 {
-       vector<string> preset_labels;
+       using namespace Menu_Helpers;
+
        vector<ARDOUR::Plugin::PresetRecord> presets = plugin->get_presets();
 
        ++_no_load_preset;
 
+       // Add a menu entry for each preset
+       _preset_combo.clear_items();
        for (vector<ARDOUR::Plugin::PresetRecord>::const_iterator i = presets.begin(); i != presets.end(); ++i) {
-               preset_labels.push_back (i->label);
+               _preset_combo.AddMenuElem(
+                       MenuElem(i->label, sigc::bind(sigc::mem_fun(*this, &PlugUIBase::preset_selected), *i)));
        }
 
-       preset_labels.push_back("");
-
-       set_popdown_strings (_preset_combo, preset_labels);
+       // Add an empty entry for un-setting current preset (see preset_selected)
+       Plugin::PresetRecord no_preset;
+       _preset_combo.AddMenuElem(
+               MenuElem("", sigc::bind(sigc::mem_fun(*this, &PlugUIBase::preset_selected), no_preset)));
 
        --_no_load_preset;
 }
@@ -755,7 +785,11 @@ PlugUIBase::update_preset ()
        Plugin::PresetRecord p = plugin->last_preset();
 
        ++_no_load_preset;
-       _preset_combo.set_active_text (p.label);
+       if (p.uri.empty()) {
+               _preset_combo.set_text (_("(none)"));
+       } else {
+               _preset_combo.set_text (p.label);
+       }
        --_no_load_preset;
 
        save_button.set_sensitive (!p.uri.empty() && p.user);
@@ -779,12 +813,6 @@ PlugUIBase::update_preset_modified ()
        }
 }
 
-void
-PlugUIBase::parameter_changed (uint32_t, float)
-{
-       update_preset_modified ();
-}
-
 void
 PlugUIBase::preset_added_or_removed ()
 {