2 * Copyright (C) 2005-2006 Nick Mainsbridge <mainsbridge@gmail.com>
3 * Copyright (C) 2005-2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
5 * Copyright (C) 2006-2009 Sampo Savolainen <v2@iki.fi>
6 * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
7 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
8 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
9 * Copyright (C) 2013-2018 John Emmas <john@creativepost.co.uk>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "gtk2ardour-config.h"
35 #include "pbd/stl_delete.h"
36 #include "pbd/xml++.h"
37 #include "pbd/failed_constructor.h"
39 #include "gtkmm/widget.h"
40 #include "gtkmm/box.h"
42 #include "gtkmm2ext/utils.h"
43 #include "gtkmm2ext/doi.h"
44 #include "gtkmm2ext/application.h"
46 #include "widgets/tooltips.h"
47 #include "widgets/fastmeter.h"
49 #include "ardour/session.h"
50 #include "ardour/plugin.h"
51 #include "ardour/plugin_insert.h"
52 #include "ardour/ladspa_plugin.h"
53 #ifdef WINDOWS_VST_SUPPORT
54 #include "ardour/windows_vst_plugin.h"
55 #include "windows_vst_plugin_ui.h"
58 #include "ardour/lxvst_plugin.h"
59 #include "lxvst_plugin_ui.h"
62 #include "ardour/mac_vst_plugin.h"
63 #include "vst_plugin_ui.h"
66 #include "ardour/lv2_plugin.h"
67 #include "lv2_plugin_ui.h"
70 #include "ardour_window.h"
71 #include "ardour_ui.h"
72 #include "plugin_ui.h"
74 #include "gui_thread.h"
75 #include "public_editor.h"
76 #include "processor_box.h"
78 #include "latency_gui.h"
79 #include "plugin_dspload_ui.h"
80 #include "plugin_eq_gui.h"
81 #include "plugin_presets_ui.h"
83 #include "new_plugin_preset_dialog.h"
88 using namespace ARDOUR;
89 using namespace ARDOUR_UI_UTILS;
90 using namespace ArdourWidgets;
92 using namespace Gtkmm2ext;
96 PluginUIWindow::PluginUIWindow (
97 boost::shared_ptr<PluginInsert> insert,
100 : ArdourWindow (string())
101 , was_visible (false)
102 , _keyboard_focused (false)
103 #ifdef AUDIOUNIT_SUPPORT
104 , pre_deactivate_x (-1)
105 , pre_deactivate_y (-1)
109 bool have_gui = false;
110 Label* label = manage (new Label());
111 label->set_markup ("<b>THIS IS THE PLUGIN UI</b>");
113 if (editor && insert->plugin()->has_editor()) {
114 switch (insert->type()) {
115 case ARDOUR::Windows_VST:
116 have_gui = create_windows_vst_editor (insert);
120 have_gui = create_lxvst_editor (insert);
124 have_gui = create_mac_vst_editor (insert);
127 case ARDOUR::AudioUnit:
128 have_gui = create_audiounit_editor (insert);
132 error << _("Eh? LADSPA plugins don't have editors!") << endmsg;
136 have_gui = create_lv2_editor (insert);
140 #ifndef WINDOWS_VST_SUPPORT
141 error << string_compose (_("unknown type of editor-supplying plugin (note: no VST support in this version of %1)"), PROGRAM_NAME)
144 error << _("unknown type of editor-supplying plugin")
147 throw failed_constructor ();
153 GenericPluginUI* pu = new GenericPluginUI (insert, scrollable);
156 _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
158 set_wmclass (X_("ardour_plugin_editor"), PROGRAM_NAME);
160 signal_map_event().connect (sigc::mem_fun (*pu, &GenericPluginUI::start_updating));
161 signal_unmap_event().connect (sigc::mem_fun (*pu, &GenericPluginUI::stop_updating));
164 set_name ("PluginEditor");
165 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
167 insert->DropReferences.connect (death_connection, invalidator (*this), boost::bind (&PluginUIWindow::plugin_going_away, this), gui_context());
169 gint h = _pluginui->get_preferred_height ();
170 gint w = _pluginui->get_preferred_width ();
173 if (h > 600) h = 600;
176 set_default_size (w, h);
177 set_resizable (_pluginui->resizable());
180 PluginUIWindow::~PluginUIWindow ()
183 cerr << "PluginWindow deleted for " << this << endl;
189 PluginUIWindow::on_show ()
191 set_role("plugin_ui");
194 _pluginui->update_preset_list ();
195 _pluginui->update_preset ();
199 #if defined (HAVE_AUDIOUNITS) && defined(__APPLE__)
200 if (pre_deactivate_x >= 0) {
201 move (pre_deactivate_x, pre_deactivate_y);
205 if (_pluginui->on_window_show (_title)) {
212 PluginUIWindow::on_hide ()
214 #if defined (HAVE_AUDIOUNITS) && defined(__APPLE__)
215 get_position (pre_deactivate_x, pre_deactivate_y);
221 _pluginui->on_window_hide ();
226 PluginUIWindow::set_title(const std::string& title)
228 Gtk::Window::set_title(title);
233 #ifdef WINDOWS_VST_SUPPORT
234 PluginUIWindow::create_windows_vst_editor(boost::shared_ptr<PluginInsert> insert)
236 PluginUIWindow::create_windows_vst_editor(boost::shared_ptr<PluginInsert>)
239 #ifndef WINDOWS_VST_SUPPORT
243 boost::shared_ptr<WindowsVSTPlugin> vp;
245 if ((vp = boost::dynamic_pointer_cast<WindowsVSTPlugin> (insert->plugin())) == 0) {
246 error << string_compose (_("unknown type of editor-supplying plugin (note: no VST support in this version of %1)"), PROGRAM_NAME)
248 throw failed_constructor ();
250 WindowsVSTPluginUI* vpu = new WindowsVSTPluginUI (insert, vp, GTK_WIDGET(this->gobj()));
253 _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
255 vpu->package (*this);
264 PluginUIWindow::create_lxvst_editor(boost::shared_ptr<PluginInsert> insert)
266 PluginUIWindow::create_lxvst_editor(boost::shared_ptr<PluginInsert>)
269 #ifndef LXVST_SUPPORT
273 boost::shared_ptr<LXVSTPlugin> lxvp;
275 if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (insert->plugin())) == 0) {
276 error << string_compose (_("unknown type of editor-supplying plugin (note: no linuxVST support in this version of %1)"), PROGRAM_NAME)
278 throw failed_constructor ();
280 LXVSTPluginUI* lxvpu = new LXVSTPluginUI (insert, lxvp);
283 _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
285 lxvpu->package (*this);
293 #ifdef MACVST_SUPPORT
294 PluginUIWindow::create_mac_vst_editor (boost::shared_ptr<PluginInsert> insert)
296 PluginUIWindow::create_mac_vst_editor (boost::shared_ptr<PluginInsert>)
299 #ifndef MACVST_SUPPORT
302 boost::shared_ptr<MacVSTPlugin> mvst;
303 if ((mvst = boost::dynamic_pointer_cast<MacVSTPlugin> (insert->plugin())) == 0) {
304 error << string_compose (_("unknown type of editor-supplying plugin (note: no MacVST support in this version of %1)"), PROGRAM_NAME)
306 throw failed_constructor ();
308 VSTPluginUI* vpu = create_mac_vst_gui (insert);
310 _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
312 vpu->package (*this);
314 Application::instance()->ActivationChanged.connect (mem_fun (*this, &PluginUIWindow::app_activated));
322 #ifdef AUDIOUNIT_SUPPORT
323 PluginUIWindow::create_audiounit_editor (boost::shared_ptr<PluginInsert> insert)
325 PluginUIWindow::create_audiounit_editor (boost::shared_ptr<PluginInsert>)
328 #ifndef AUDIOUNIT_SUPPORT
332 _pluginui = create_au_gui (insert, &box);
333 _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
336 Application::instance()->ActivationChanged.connect (mem_fun (*this, &PluginUIWindow::app_activated));
344 PluginUIWindow::app_activated (bool yn)
346 PluginUIWindow::app_activated (bool)
349 #ifdef AUDIOUNIT_SUPPORT
353 _pluginui->activate ();
354 if (pre_deactivate_x >= 0) {
355 move (pre_deactivate_x, pre_deactivate_y);
361 was_visible = is_visible();
362 get_position (pre_deactivate_x, pre_deactivate_y);
364 _pluginui->deactivate ();
371 PluginUIWindow::create_lv2_editor(boost::shared_ptr<PluginInsert> insert)
374 boost::shared_ptr<LV2Plugin> vp;
376 if ((vp = boost::dynamic_pointer_cast<LV2Plugin> (insert->plugin())) == 0) {
377 error << _("create_lv2_editor called on non-LV2 plugin") << endmsg;
378 throw failed_constructor ();
380 LV2PluginUI* lpu = new LV2PluginUI (insert, vp);
383 lpu->package (*this);
384 _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
394 PluginUIWindow::keyboard_focused (bool yn)
396 _keyboard_focused = yn;
400 PluginUIWindow::on_key_press_event (GdkEventKey* event)
402 if (_keyboard_focused) {
404 _pluginui->grab_focus();
405 if (_pluginui->non_gtk_gui()) {
406 _pluginui->forward_key_event (event);
408 return relay_key_press (event, this);
413 /* for us to be getting key press events, there really
414 MUST be a _pluginui, but just to be safe, check ...
418 _pluginui->grab_focus();
419 if (_pluginui->non_gtk_gui()) {
420 /* pass main window as the window for the event
421 to be handled in, not this one, because there are
422 no widgets in this window that we want to have
425 return relay_key_press (event, &ARDOUR_UI::instance()->main_window());
427 return relay_key_press (event, this);
435 PluginUIWindow::on_key_release_event (GdkEventKey *event)
437 if (_keyboard_focused) {
439 if (_pluginui->non_gtk_gui()) {
440 _pluginui->forward_key_event (event);
444 gtk_window_propagate_key_event (GTK_WINDOW(gobj()), event);
446 /* don't forward releases */
451 PluginUIWindow::plugin_going_away ()
453 ENSURE_GUI_THREAD (*this, &PluginUIWindow::plugin_going_away)
456 _pluginui->stop_updating(0);
459 death_connection.disconnect ();
462 PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
464 , plugin (insert->plugin())
465 , add_button (_("Add"))
466 , save_button (_("Save"))
467 , delete_button (_("Delete"))
468 , reset_button (_("Reset"))
469 , bypass_button (ArdourButton::led_default_elements)
470 , pin_management_button (_("Pinout"))
471 , description_expander (_("Description"))
472 , plugin_analysis_expander (_("Plugin analysis"))
473 , cpuload_expander (_("CPU Profile"))
480 _preset_modified.set_size_request (16, -1);
481 _preset_combo.set_text("(default)");
482 set_tooltip (_preset_combo, _("Presets (if any) for this plugin\n(Both factory and user-created)"));
483 set_tooltip (add_button, _("Save a new preset"));
484 set_tooltip (save_button, _("Save the current preset"));
485 set_tooltip (delete_button, _("Delete the current preset"));
486 set_tooltip (reset_button, _("Reset parameters to default (if no parameters are in automation play mode)"));
487 set_tooltip (pin_management_button, _("Show Plugin Pin Management Dialog"));
488 set_tooltip (bypass_button, _("Disable signal processing by the plugin"));
491 update_preset_list ();
494 add_button.set_name ("generic button");
495 add_button.set_icon (ArdourIcon::PsetAdd);
496 add_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::add_plugin_setting));
498 save_button.set_name ("generic button");
499 save_button.set_icon (ArdourIcon::PsetSave);
500 save_button.signal_clicked.connect(sigc::mem_fun(*this, &PlugUIBase::save_plugin_setting));
502 delete_button.set_name ("generic button");
503 delete_button.set_icon (ArdourIcon::PsetDelete);
504 delete_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::delete_plugin_setting));
506 reset_button.set_name ("generic button");
507 reset_button.set_icon (ArdourIcon::PluginReset);
508 reset_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::reset_plugin_parameters));
510 pin_management_button.set_name ("generic button");
511 pin_management_button.set_icon (ArdourIcon::PluginPinout);
512 pin_management_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::manage_pins));
514 insert->ActiveChanged.connect (active_connection, invalidator (*this), boost::bind (&PlugUIBase::processor_active_changed, this, boost::weak_ptr<Processor>(insert)), gui_context());
516 bypass_button.set_name ("plugin bypass button");
517 bypass_button.set_text (_("Bypass"));
518 bypass_button.set_icon (ArdourIcon::PluginBypass);
519 bypass_button.set_active (!pi->enabled ());
520 bypass_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PlugUIBase::bypass_button_release), false);
521 focus_button.add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
523 focus_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PlugUIBase::focus_toggled));
524 focus_button.add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
526 /* these images are not managed, so that we can remove them at will */
528 focus_out_image = new Image (get_icon (X_("computer_keyboard")));
529 focus_in_image = new Image (get_icon (X_("computer_keyboard_active")));
531 focus_button.add (*focus_out_image);
533 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));
534 set_tooltip (bypass_button, _("Click to enable/disable this plugin"));
536 description_expander.property_expanded().signal_changed().connect( sigc::mem_fun(*this, &PlugUIBase::toggle_description));
537 description_expander.set_expanded(false);
539 plugin_analysis_expander.property_expanded().signal_changed().connect( sigc::mem_fun(*this, &PlugUIBase::toggle_plugin_analysis));
540 plugin_analysis_expander.set_expanded(false);
542 cpuload_expander.property_expanded().signal_changed().connect( sigc::mem_fun(*this, &PlugUIBase::toggle_cpuload_display));
543 cpuload_expander.set_expanded(false);
545 insert->DropReferences.connect (death_connection, invalidator (*this), boost::bind (&PlugUIBase::plugin_going_away, this), gui_context());
547 plugin->PresetAdded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
548 plugin->PresetRemoved.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
549 plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset, this), gui_context ());
550 plugin->PresetDirty.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset_modified, this), gui_context ());
552 insert->AutomationStateChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::automation_state_changed, this), gui_context());
554 insert->LatencyChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::set_latency_label, this), gui_context());
556 automation_state_changed();
559 PlugUIBase::~PlugUIBase()
565 delete latency_dialog;
569 PlugUIBase::plugin_going_away ()
571 /* drop references to the plugin/insert */
577 PlugUIBase::set_latency_label ()
579 samplecnt_t const l = insert->effective_latency ();
580 samplecnt_t const sr = insert->session().sample_rate ();
585 t = string_compose (P_("latency (%1 sample)", "latency (%1 samples)", l), l);
587 t = string_compose (_("latency (%1 ms)"), (float) l / ((float) sr / 1000.0f));
590 latency_button.set_text (t);
594 PlugUIBase::latency_button_clicked ()
597 latency_gui = new LatencyGUI (*(insert.get()), insert->session().sample_rate(), insert->session().get_block_size());
598 latency_dialog = new ArdourWindow (_("Edit Latency"));
599 /* use both keep-above and transient for to try cover as many
600 different WM's as possible.
602 latency_dialog->set_keep_above (true);
603 Window* win = dynamic_cast<Window*> (bypass_button.get_toplevel ());
605 latency_dialog->set_transient_for (*win);
607 latency_dialog->add (*latency_gui);
610 latency_gui->refresh ();
611 latency_dialog->show_all ();
615 PlugUIBase::processor_active_changed (boost::weak_ptr<Processor> weak_p)
617 ENSURE_GUI_THREAD (*this, &PlugUIBase::processor_active_changed, weak_p);
618 boost::shared_ptr<Processor> p (weak_p.lock());
621 bypass_button.set_active (!p->enabled ());
626 PlugUIBase::preset_selected (Plugin::PresetRecord preset)
628 if (_no_load_preset) {
631 if (!preset.label.empty()) {
632 insert->load_preset (preset);
634 // blank selected = no preset
635 plugin->clear_preset();
639 #ifdef NO_PLUGIN_STATE
640 static bool seen_saving_message = false;
642 static void show_no_plugin_message()
644 info << string_compose (_("Plugin presets are not supported in this build of %1. Consider paying for a full version"),
647 info << _("To get full access to updates without this limitation\n"
648 "consider becoming a subscriber for a low cost every month.")
650 info << X_("https://community.ardour.org/s/subscribe")
652 ARDOUR_UI::instance()->popup_error(_("Plugin presets are not supported in this build, see the Log window for more information."));
657 PlugUIBase::add_plugin_setting ()
659 #ifndef NO_PLUGIN_STATE
660 NewPluginPresetDialog d (plugin, _("New Preset"));
663 case Gtk::RESPONSE_ACCEPT:
664 if (d.name().empty()) {
669 plugin->remove_preset (d.name ());
672 Plugin::PresetRecord const r = plugin->save_preset (d.name());
673 if (!r.uri.empty ()) {
674 plugin->load_preset (r);
679 if (!seen_saving_message) {
680 seen_saving_message = true;
681 show_no_plugin_message();
687 PlugUIBase::save_plugin_setting ()
689 #ifndef NO_PLUGIN_STATE
690 string const name = _preset_combo.get_text ();
691 plugin->remove_preset (name);
692 Plugin::PresetRecord const r = plugin->save_preset (name);
693 if (!r.uri.empty ()) {
694 plugin->load_preset (r);
697 if (!seen_saving_message) {
698 seen_saving_message = true;
699 show_no_plugin_message();
705 PlugUIBase::delete_plugin_setting ()
707 #ifndef NO_PLUGIN_STATE
708 plugin->remove_preset (_preset_combo.get_text ());
710 if (!seen_saving_message) {
711 seen_saving_message = true;
712 show_no_plugin_message();
718 PlugUIBase::automation_state_changed ()
720 reset_button.set_sensitive (insert->can_reset_all_parameters());
724 PlugUIBase::reset_plugin_parameters ()
726 insert->reset_parameters_to_default ();
730 PlugUIBase::manage_pins ()
732 PluginPinWindowProxy* proxy = insert->pinmgr_proxy ();
736 proxy->get ()->raise();
741 PlugUIBase::bypass_button_release (GdkEventButton*)
743 bool view_says_bypassed = (bypass_button.active_state() != 0);
745 if (view_says_bypassed != insert->enabled ()) {
746 insert->enable (view_says_bypassed);
753 PlugUIBase::focus_toggled (GdkEventButton*)
755 if (Keyboard::the_keyboard().some_magic_widget_has_focus()) {
756 Keyboard::the_keyboard().magic_widget_drop_focus();
757 focus_button.remove ();
758 focus_button.add (*focus_out_image);
759 focus_out_image->show ();
760 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));
761 KeyboardFocused (false);
763 Keyboard::the_keyboard().magic_widget_grab_focus();
764 focus_button.remove ();
765 focus_button.add (*focus_in_image);
766 focus_in_image->show ();
767 set_tooltip (focus_button, string_compose (_("Click to allow normal use of %1 keyboard shortcuts"), PROGRAM_NAME));
768 KeyboardFocused (true);
775 PlugUIBase::toggle_description()
777 if (description_expander.get_expanded() &&
778 !description_expander.get_child()) {
779 const std::string text = plugin->get_docs();
784 Gtk::Label* label = manage(new Gtk::Label(text));
785 label->set_line_wrap(true);
786 label->set_line_wrap_mode(Pango::WRAP_WORD);
787 description_expander.add(*label);
788 description_expander.show_all();
791 if (!description_expander.get_expanded()) {
792 const int child_height = description_expander.get_child ()->get_height ();
794 description_expander.remove();
796 Gtk::Window *toplevel = (Gtk::Window*) description_expander.get_ancestor (GTK_TYPE_WINDOW);
800 toplevel->get_size (wr.width, wr.height);
801 wr.height -= child_height;
802 toplevel->resize (wr.width, wr.height);
808 PlugUIBase::toggle_plugin_analysis()
810 if (plugin_analysis_expander.get_expanded() &&
811 !plugin_analysis_expander.get_child()) {
814 eqgui = new PluginEqGui (insert);
817 plugin_analysis_expander.add (*eqgui);
818 plugin_analysis_expander.show_all ();
819 eqgui->start_listening ();
822 if (!plugin_analysis_expander.get_expanded()) {
823 // Hide & remove from expander
824 const int child_height = plugin_analysis_expander.get_child ()->get_height ();
827 eqgui->stop_listening ();
828 plugin_analysis_expander.remove();
830 Gtk::Window *toplevel = (Gtk::Window*) plugin_analysis_expander.get_ancestor (GTK_TYPE_WINDOW);
834 toplevel->get_size (wr.width, wr.height);
835 wr.height -= child_height;
836 toplevel->resize (wr.width, wr.height);
842 PlugUIBase::toggle_cpuload_display()
844 if (cpuload_expander.get_expanded() && !cpuload_expander.get_child()) {
845 if (stats_gui == 0) {
846 stats_gui = new PluginLoadStatsGui (insert);
848 cpuload_expander.add (*stats_gui);
849 cpuload_expander.show_all();
850 stats_gui->start_updating ();
853 if (!cpuload_expander.get_expanded()) {
854 const int child_height = cpuload_expander.get_child ()->get_height ();
857 stats_gui->stop_updating ();
858 cpuload_expander.remove();
860 Gtk::Window *toplevel = (Gtk::Window*) cpuload_expander.get_ancestor (GTK_TYPE_WINDOW);
864 toplevel->get_size (wr.width, wr.height);
865 wr.height -= child_height;
866 toplevel->resize (wr.width, wr.height);
873 PlugUIBase::update_preset_list ()
875 using namespace Menu_Helpers;
877 vector<ARDOUR::Plugin::PresetRecord> presets = plugin->get_presets();
881 // Add a menu entry for each preset
882 _preset_combo.clear_items();
883 for (vector<ARDOUR::Plugin::PresetRecord>::const_iterator i = presets.begin(); i != presets.end(); ++i) {
884 _preset_combo.AddMenuElem(
885 MenuElem(i->label, sigc::bind(sigc::mem_fun(*this, &PlugUIBase::preset_selected), *i)));
888 // Add an empty entry for un-setting current preset (see preset_selected)
889 Plugin::PresetRecord no_preset;
890 _preset_combo.AddMenuElem(
891 MenuElem("", sigc::bind(sigc::mem_fun(*this, &PlugUIBase::preset_selected), no_preset)));
897 PlugUIBase::update_preset ()
899 Plugin::PresetRecord p = plugin->last_preset();
903 _preset_combo.set_text (_("(none)"));
905 _preset_combo.set_text (p.label);
909 delete_button.set_sensitive (!p.uri.empty() && p.user);
910 update_preset_modified ();
914 PlugUIBase::update_preset_modified ()
916 Plugin::PresetRecord p = plugin->last_preset();
919 save_button.set_sensitive (false);
920 _preset_modified.set_text ("");
924 bool const c = plugin->parameter_changed_since_last_preset ();
925 if (_preset_modified.get_text().empty() == c) {
926 _preset_modified.set_text (c ? "*" : "");
928 save_button.set_sensitive (c && p.user);
932 PlugUIBase::preset_added_or_removed ()
934 /* Update both the list and the currently-displayed preset */
935 update_preset_list ();