Fix processor box for no crash on click
[ardour.git] / gtk2_ardour / plugin_presets_ui.cc
1 /*
2  * Copyright (C) 2018-2019 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include "gtkmm2ext/utils.h"
20
21 #include "ardour/plugin.h"
22 #include "gui_thread.h"
23
24 #include "plugin_presets_ui.h"
25
26 #include "pbd/i18n.h"
27
28 using namespace ARDOUR;
29
30 PluginPresetsUI::PluginPresetsUI (boost::shared_ptr<PluginInsert> insert)
31         : _insert (insert)
32         , _load_button (_("Load"))
33 {
34         _plugin_preset_model = Gtk::TreeStore::create (_plugin_preset_columns);
35         _plugin_preset_display.set_model (_plugin_preset_model);
36         _plugin_preset_display.set_headers_visible (true);
37         _plugin_preset_display.get_selection ()->set_mode (Gtk::SELECTION_SINGLE);
38         _plugin_preset_display.get_selection ()->signal_changed ().connect (sigc::mem_fun (*this, &PluginPresetsUI::preset_selected));
39         _plugin_preset_display.signal_row_activated ().connect (sigc::mem_fun (*this, &PluginPresetsUI::row_activated));
40         _plugin_preset_display.set_sensitive (true);
41
42         Gtk::CellRendererText* label_render = Gtk::manage (new Gtk::CellRendererText());
43         Gtk::TreeView::Column* label_col = Gtk::manage (new Gtk::TreeView::Column (_("Preset"), *label_render));
44         label_col->add_attribute (label_render->property_markup(), _plugin_preset_columns.name);
45         _plugin_preset_display.append_column (*label_col);
46
47         _preset_desc.set_editable (false);
48         _preset_desc.set_can_focus (false);
49         _preset_desc.set_wrap_mode (Gtk::WRAP_WORD);
50         _preset_desc.set_size_request (400,200);
51         _preset_desc.set_name (X_("TextOnBackground"));
52         _preset_desc.set_border_width (6);
53
54         _preset_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
55         _preset_scroller.add (_plugin_preset_display);
56
57         _load_button.set_name ("generic button");
58         _load_button.signal_clicked.connect (sigc::mem_fun (*this, &PluginPresetsUI::load_preset));
59         _load_button.set_sensitive (false);
60
61         attach (_preset_scroller, 0, 1, 0, 2, Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 2, 0);
62         attach (_preset_desc, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 2, 0);
63         attach (_load_button, 1, 2, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 0);
64
65         boost::shared_ptr<Plugin> plugin (_insert->plugin ());
66
67         plugin->PresetAdded.connect (_preset_connections, invalidator (*this), boost::bind (&PluginPresetsUI::update_preset_list, this), gui_context ());
68         plugin->PresetRemoved.connect (_preset_connections, invalidator (*this), boost::bind (&PluginPresetsUI::update_preset_list, this), gui_context ());
69         plugin->PresetLoaded.connect (_preset_connections, invalidator (*this), boost::bind (&PluginPresetsUI::update_preset_list, this), gui_context ());
70
71         update_preset_list ();
72 }
73
74 void
75 PluginPresetsUI::update_preset_list ()
76 {
77         boost::shared_ptr<Plugin> plugin (_insert->plugin ());
78
79         Plugin::PresetRecord const& p = plugin->last_preset ();
80         std::vector<Plugin::PresetRecord> presets = plugin->get_presets ();
81
82
83         std::string selected_uri;
84         if (_plugin_preset_display.get_selection ()->count_selected_rows () == 1) {
85                 Gtk::TreeIter iter = _plugin_preset_display.get_selection ()->get_selected ();
86                 ARDOUR::Plugin::PresetRecord const& ppr ((*iter)[_plugin_preset_columns.plugin_preset]);
87                 selected_uri = ppr.uri;
88         }
89
90         _plugin_preset_model->clear ();
91
92         bool found_active = false;
93
94         for (std::vector<Plugin::PresetRecord>::const_iterator i = presets.begin (); i != presets.end (); ++i) {
95                 Gtk::TreeModel::Row row = *(_plugin_preset_model->append ());
96                 if (p.uri == i->uri) {
97                         row[_plugin_preset_columns.name] = string_compose ("<span weight=\"bold\"  background=\"green\">%1</span>", Gtkmm2ext::markup_escape_text (i->label));
98                         found_active = true;
99                 } else {
100                         row[_plugin_preset_columns.name] = Gtkmm2ext::markup_escape_text (i->label);
101                 }
102                 row[_plugin_preset_columns.description] = i->description;
103                 row[_plugin_preset_columns.plugin_preset] = *i;
104         }
105
106         {
107                 Gtk::TreeModel::Row row = *(_plugin_preset_model->prepend ());
108                 if (found_active) {
109                         row[_plugin_preset_columns.name] = _("(none)");
110                 } else {
111                         row[_plugin_preset_columns.name] = string_compose ("<span weight=\"bold\"  background=\"green\">%1</span>", _("(none)"));
112                 }
113                 row[_plugin_preset_columns.description] = "";
114                 row[_plugin_preset_columns.plugin_preset] = Plugin::PresetRecord ();
115         }
116
117         Gtk::TreeModel::Children rows = _plugin_preset_model->children ();
118         for (Gtk::TreeModel::Children::iterator i = rows.begin (); i != rows.end (); ++i) {
119                 ARDOUR::Plugin::PresetRecord const& ppr ((*i)[_plugin_preset_columns.plugin_preset]);
120                 if (ppr.uri == selected_uri) {
121                         _plugin_preset_display.get_selection ()->select (*i);
122                         break;
123                 }
124         }
125
126 }
127
128 void
129 PluginPresetsUI::preset_selected ()
130 {
131         if (_plugin_preset_display.get_selection ()->count_selected_rows () != 1) {
132                 return;
133         }
134
135         Gtk::TreeIter iter = _plugin_preset_display.get_selection ()->get_selected ();
136         assert (iter);
137         ARDOUR::Plugin::PresetRecord const& ppr ((*iter)[_plugin_preset_columns.plugin_preset]);
138
139         std::string d;
140         if (!ppr.valid) {
141                 d = "-";
142         } else if (ppr.user) {
143                 d = _("(user preset)");
144         } else {
145                 d = (*iter)[_plugin_preset_columns.description];
146         }
147         _preset_desc.get_buffer ()->set_text (d);
148
149         Plugin::PresetRecord const& p = _insert->plugin ()->last_preset ();
150         _load_button.set_sensitive (ppr.valid && !(p.valid && p.uri == ppr.uri));
151 }
152
153 void
154 PluginPresetsUI::row_activated (Gtk::TreeModel::Path, Gtk::TreeViewColumn*)
155 {
156         if (_load_button.get_sensitive ()) {
157                 load_preset ();
158         }
159 }
160
161 void
162 PluginPresetsUI::load_preset ()
163 {
164         if (_plugin_preset_display.get_selection ()->count_selected_rows () != 1) {
165                 return;
166         }
167
168         Gtk::TreeIter iter = _plugin_preset_display.get_selection ()->get_selected ();
169         ARDOUR::Plugin::PresetRecord const& ppr ((*iter)[_plugin_preset_columns.plugin_preset]);
170         if (ppr.valid) {
171                 _insert->load_preset (ppr);
172         }
173 }