Fix horizontal positioning of PC flags.
[ardour.git] / gtk2_ardour / plugin_ui.cc
index 7f2955dfda62434035c4124021aad36287c6efb7..eae0d91388c866b1b2c0c81bd7eb79359dd19fb6 100644 (file)
@@ -27,6 +27,7 @@
 #include <pbd/failed_constructor.h>
 
 #include <gtkmm/widget.h>
+#include <gtkmm/box.h>
 #include <gtkmm2ext/click_box.h>
 #include <gtkmm2ext/fastmeter.h>
 #include <gtkmm2ext/barcontroller.h>
 #ifdef VST_SUPPORT
 #include <ardour/vst_plugin.h>
 #endif
+#ifdef HAVE_LV2
+#include <ardour/lv2_plugin.h>
+#include "lv2_plugin_ui.h"
+#endif
 
 #include <lrdf.h>
 
@@ -51,6 +56,7 @@
 #include "utils.h"
 #include "gui_thread.h"
 #include "public_editor.h"
+#include "keyboard.h"
 
 #include "i18n.h"
 
@@ -61,10 +67,12 @@ using namespace Gtkmm2ext;
 using namespace Gtk;
 using namespace sigc;
 
-PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, nframes64_t sr, nframes64_t period, bool scrollable)
+PluginUIWindow::PluginUIWindow (Gtk::Window* win, boost::shared_ptr<PluginInsert> insert, bool scrollable)
+       : parent (win)
 {
        bool have_gui = false;
        non_gtk_gui = false;
+       was_visible = false;
 
        Label* label = manage (new Label());
        label->set_markup ("<b>THIS IS THE PLUGIN UI</b>");
@@ -83,6 +91,10 @@ PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, nframes6
                        error << _("Eh? LADSPA plugins don't have editors!") << endmsg;
                        break;
 
+               case ARDOUR::LV2:
+                       have_gui = create_lv2_editor (insert);
+                       break;
+
                default:
 #ifndef VST_SUPPORT
                        error << _("unknown type of editor-supplying plugin (note: no VST support in this version of ardour)")
@@ -101,8 +113,17 @@ PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, nframes6
                GenericPluginUI*  pu  = new GenericPluginUI (insert, scrollable);
                
                _pluginui = pu;
-               add (*pu);
+               add( *pu );
+
+               /*
+               Gtk::HBox *hbox = new Gtk::HBox();
+               hbox->pack_start( *pu);
+               // TODO: this should be nicer
+               hbox->pack_start( eqgui_bin );
                
+               add (*manage(hbox));
+               */
+
                set_wmclass (X_("ardour_plugin_editor"), "Ardour");
 
                signal_map_event().connect (mem_fun (*pu, &GenericPluginUI::start_updating));
@@ -135,18 +156,66 @@ PluginUIWindow::~PluginUIWindow ()
 {
 }
 
+void
+PluginUIWindow::set_parent (Gtk::Window* win)
+{
+       parent = win;
+}
+
+void
+PluginUIWindow::on_map ()
+{
+       Window::on_map ();
+       set_keep_above (true);
+}
+
+bool
+PluginUIWindow::on_enter_notify_event (GdkEventCrossing *ev)
+{
+       Keyboard::the_keyboard().enter_window (ev, this);
+       return false;
+}
+
+bool
+PluginUIWindow::on_leave_notify_event (GdkEventCrossing *ev)
+{
+       Keyboard::the_keyboard().leave_window (ev, this);
+       return false;
+}
+
+bool
+PluginUIWindow::on_focus_in_event (GdkEventFocus *ev)
+{
+       Window::on_focus_in_event (ev);
+       //Keyboard::the_keyboard().magic_widget_grab_focus ();
+       return false;
+}
+
+bool
+PluginUIWindow::on_focus_out_event (GdkEventFocus *ev)
+{
+       Window::on_focus_out_event (ev);
+       //Keyboard::the_keyboard().magic_widget_drop_focus ();
+       return false;
+}
+
 void
 PluginUIWindow::on_show ()
 {
-       cerr << "PluginWindow shown\n";
-               
+       if (_pluginui) {
+               _pluginui->update_presets ();
+       }
+
        Window::on_show ();
+
+       if (parent) {
+               // set_transient_for (*parent);
+       }
 }
 
 void
 PluginUIWindow::on_hide ()
 {
-       cerr << "PluginWindow hidden\n";
        Window::on_hide ();
 }
 
@@ -201,9 +270,13 @@ PluginUIWindow::app_activated (bool yn)
        cerr << "APP activated ? " << yn << endl;
        if (_pluginui) {
                if (yn) {
-                       _pluginui->activate ();
-                       present ();
+                       if (was_visible) {
+                               _pluginui->activate ();
+                               present ();
+                               was_visible = true;
+                       }
                } else {
+                       was_visible = is_visible();
                        hide ();
                        _pluginui->deactivate ();
                }
@@ -212,12 +285,32 @@ PluginUIWindow::app_activated (bool yn)
 }
 
 bool
-PluginUIWindow::on_key_press_event (GdkEventKey* event)
+PluginUIWindow::create_lv2_editor(boost::shared_ptr<PluginInsert> insert)
 {
-       if (non_gtk_gui) {
-               return false;
+#ifndef HAVE_LV2
+       return false;
+#else
+
+       boost::shared_ptr<LV2Plugin> vp;
+       
+       if ((vp = boost::dynamic_pointer_cast<LV2Plugin> (insert->plugin())) == 0) {
+               error << _("create_lv2_editor called on non-LV2 plugin") << endmsg;
+               throw failed_constructor ();
+       } else {
+               LV2PluginUI* lpu = new LV2PluginUI (insert, vp);
+               _pluginui = lpu;
+               add (*lpu);
+               lpu->package (*this);
        }
 
+       non_gtk_gui = false;
+       return true;
+#endif
+}
+
+bool
+PluginUIWindow::on_key_press_event (GdkEventKey* event)
+{
        if (!key_press_focus_accelerator_handler (*this, event)) {
                return PublicEditor::instance().on_key_press_event(event);
        } else {
@@ -249,8 +342,8 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
          bypass_button (_("Bypass")),
          latency_gui (*pi, pi->session().frame_rate(), pi->session().get_block_size())
 {
-        //preset_combo.set_use_arrows_always(true);
-       set_popdown_strings (preset_combo, plugin->get_presets());
+       //preset_combo.set_use_arrows_always(true);
+       update_presets();
        preset_combo.set_size_request (100, -1);
        preset_combo.set_active_text ("");
        preset_combo.signal_changed().connect(mem_fun(*this, &PlugUIBase::setting_selected));
@@ -266,6 +359,20 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
 
        bypass_button.set_name ("PluginBypassButton");
        bypass_button.signal_toggled().connect (mem_fun(*this, &PlugUIBase::bypass_toggled));
+       focus_button.add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
+
+       focus_button.signal_button_release_event().connect (mem_fun(*this, &PlugUIBase::focus_toggled));
+       focus_button.add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
+
+       /* these images are not managed, so that we can remove them at will */
+
+       focus_out_image = new Image (get_icon (X_("computer_keyboard")));
+       focus_in_image = new Image (get_icon (X_("computer_keyboard_active")));
+       
+       focus_button.add (*focus_out_image);
+
+       ARDOUR_UI::instance()->set_tip (&focus_button, _("Click to focus all keyboard events on this plugin window"), "");
+       ARDOUR_UI::instance()->set_tip (&bypass_button, _("Click to enable/disable this plugin"), "");
 }
 
 void
@@ -282,8 +389,12 @@ void
 PlugUIBase::setting_selected()
 {
        if (preset_combo.get_active_text().length() > 0) {
-               if (!plugin->load_preset(preset_combo.get_active_text())) {
-                       warning << string_compose(_("Plugin preset %1 not found"), preset_combo.get_active_text()) << endmsg;
+               const Plugin::PresetRecord* pr = plugin->preset_by_label(preset_combo.get_active_text());
+               if (pr) {
+                       plugin->load_preset(pr->uri);
+               } else {
+                       warning << string_compose(_("Plugin preset %1 not found"),
+                                       preset_combo.get_active_text()) << endmsg;
                }
        }
 }
@@ -295,19 +406,17 @@ PlugUIBase::save_plugin_setting ()
        prompter.set_prompt(_("Name of New Preset:"));
        prompter.add_button (Gtk::Stock::ADD, Gtk::RESPONSE_ACCEPT);
        prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
+       prompter.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
 
        prompter.show_all();
 
        switch (prompter.run ()) {
        case Gtk::RESPONSE_ACCEPT:
-
                string name;
-
                prompter.get_result(name);
-
                if (name.length()) {
-                       if(plugin->save_preset(name)){
-                               set_popdown_strings (preset_combo, plugin->get_presets());
+                       if (plugin->save_preset(name)) {
+                               update_presets();
                                preset_combo.set_active_text (name);
                        }
                }
@@ -321,11 +430,42 @@ PlugUIBase::bypass_toggled ()
        bool x;
 
        if ((x = bypass_button.get_active()) == insert->active()) {
-               insert->set_active (!x);
-               if (insert->active()) {
-                       bypass_button.set_label (_("Bypass"));
+               if (x) {
+                       insert->deactivate ();
                } else {
-                       bypass_button.set_label (_("Active"));
+                       insert->activate ();
                }
        }
 }
+
+bool
+PlugUIBase::focus_toggled (GdkEventButton* ev)
+{
+       if (Keyboard::the_keyboard().some_magic_widget_has_focus()) {
+               Keyboard::the_keyboard().magic_widget_drop_focus();
+               focus_button.remove ();
+               focus_button.add (*focus_out_image);
+               focus_out_image->show ();
+               ARDOUR_UI::instance()->set_tip (&focus_button, _("Click to focus all keyboard events on this plugin window"), "");
+       } 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, _("Click to remove keyboard focus from this plugin window"), "");
+       }
+
+       return true;
+}
+
+void
+PlugUIBase::update_presets ()
+{
+       vector<string> preset_labels;
+       vector<ARDOUR::Plugin::PresetRecord> presets = plugin->get_presets();
+       for (vector<ARDOUR::Plugin::PresetRecord>::const_iterator i = presets.begin();
+                  i != presets.end(); ++i) {
+               preset_labels.push_back(i->label);
+       }
+       set_popdown_strings (preset_combo, preset_labels);
+}