Prompter now prevents blank strings or unaltered names & now has a horizontal orienta...
[ardour.git] / gtk2_ardour / plugin_selector.cc
1 /*
2     Copyright (C) 2000 Paul Davis 
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
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cstdio>
21 #include <lrdf.h>
22
23 #include <gtkmm/table.h>
24 #include <gtkmm/stock.h>
25 #include <gtkmm/button.h>
26 #include <gtkmm/notebook.h>
27
28 #include <ardour/plugin_manager.h>
29 #include <ardour/plugin.h>
30 #include <ardour/configuration.h>
31
32 #include "ardour_ui.h"
33 #include "plugin_selector.h"
34 #include "gui_thread.h"
35
36 #include "i18n.h"
37
38 using namespace ARDOUR;
39 using namespace Gtk;
40
41 PluginSelector::PluginSelector (PluginManager *mgr)
42         : ArdourDialog (_("ardour: plugins"), true, false)
43 {
44         set_position (Gtk::WIN_POS_MOUSE);
45         set_name ("PluginSelectorWindow");
46         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
47
48         manager = mgr;
49         session = 0;
50         o_selected_plug = -1;
51         i_selected_plug = 0;
52
53         lmodel = Gtk::ListStore::create(lcols);
54         ladspa_display.set_model (lmodel);
55         ladspa_display.append_column (_("Available LADSPA Plugins"), lcols.name);
56         ladspa_display.append_column (_("Type"), lcols.type);
57         ladspa_display.append_column (_("# Inputs"),lcols.ins);
58         ladspa_display.append_column (_("# Outputs"), lcols.outs);
59         ladspa_display.set_headers_visible (true);
60         ladspa_display.set_reorderable (false);
61         lscroller.set_border_width(10);
62         lscroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
63         lscroller.add(ladspa_display);
64
65         amodel = Gtk::ListStore::create(acols);
66         added_list.set_model (amodel);
67         added_list.append_column (_("Plugins to be Connected to Insert"), acols.text);
68         added_list.set_headers_visible (true);
69         added_list.set_reorderable (false);
70
71         for (int i = 0; i <=3; i++) {
72                 Gtk::TreeView::Column* column = ladspa_display.get_column(i);
73                 column->set_sort_column(i);
74         }
75
76 #ifdef VST_SUPPORT
77         vmodel = ListStore::create(vcols);
78         vst_display.set_model (vmodel);
79         vst_display.append_column (_("Available plugins"), vcols.name);
80         vst_display.append_column (_("# Inputs"), vcols.ins);
81         vst_display.append_column (_("# Outputs"), vcols.outs);
82         vst_display.set_headers_visible (true);
83         vst_display.set_reorderable (false);
84         vscroller.set_border_width(10);
85         vscroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
86         vscroller.add(vst_display);
87
88         for (int i = 0; i <=2; i++) {
89                 Gtk::TreeView::Column* column = vst_display.get_column(i);
90                 column->set_sort_column(i);
91         }
92 #endif
93         ascroller.set_border_width(10);
94         ascroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
95         ascroller.add(added_list);
96         Gtk::Button *btn_add = manage(new Gtk::Button(Stock::ADD));
97         ARDOUR_UI::instance()->tooltips().set_tip(*btn_add, _("Add a plugin to the effect list"));
98         Gtk::Button *btn_remove = manage(new Gtk::Button(Stock::REMOVE));
99         ARDOUR_UI::instance()->tooltips().set_tip(*btn_remove, _("Remove a plugin from the effect list"));
100         Gtk::Button *btn_update = manage(new Gtk::Button(Stock::REFRESH));
101         ARDOUR_UI::instance()->tooltips().set_tip(*btn_update, _("Update available plugins"));
102
103         btn_add->set_name("PluginSelectorButton");
104         btn_remove->set_name("PluginSelectorButton");
105
106         Gtk::Table* table = manage(new Gtk::Table(7, 10));
107         table->set_size_request(750, 500);
108         table->attach(notebook, 0, 7, 0, 5);
109
110         table->attach(*btn_add, 1, 2, 5, 6, Gtk::FILL, Gtk::FILL, 5, 5);
111         table->attach(*btn_remove, 3, 4, 5, 6, Gtk::FILL, Gtk::FILL, 5, 5);
112         table->attach(*btn_update, 5, 6, 5, 6, Gtk::FILL, Gtk::FILL, 5, 5);
113
114         table->attach(ascroller, 0, 7, 7, 9);
115
116         add_button (Stock::CANCEL, RESPONSE_CANCEL);
117         add_button (Stock::CONNECT, RESPONSE_APPLY);
118         set_default_response (RESPONSE_APPLY);
119
120         get_vbox()->pack_start (*table);
121
122         using namespace Gtk::Notebook_Helpers;
123         notebook.pages().push_back (TabElem (lscroller, _("LADSPA")));
124 #ifdef VST_SUPPORT
125         if (Config->get_use_vst()) {
126                 notebook.pages().push_back (TabElem (vscroller, _("VST")));
127         }
128 #endif
129
130         table->set_name("PluginSelectorTable");
131         ladspa_display.set_name("PluginSelectorDisplay");
132         //ladspa_display.set_name("PluginSelectorList");
133         added_list.set_name("PluginSelectorList");
134
135         ladspa_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
136 #ifdef VST_SUPPORT
137         if (Config->get_use_vst()) {
138                 vst_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
139         }
140 #endif
141         
142         btn_update->signal_clicked().connect (mem_fun(*this, &PluginSelector::btn_update_clicked));
143         btn_add->signal_clicked().connect(mem_fun(*this, &PluginSelector::btn_add_clicked));
144         btn_remove->signal_clicked().connect(mem_fun(*this, &PluginSelector::btn_remove_clicked));
145
146         input_refiller ();
147 }
148
149 void
150 PluginSelector::row_clicked(GdkEventButton* event)
151 {
152         if (event->type == GDK_2BUTTON_PRESS)
153                 btn_add_clicked();
154 }
155
156 void
157 PluginSelector::set_session (Session* s)
158 {
159         ENSURE_GUI_THREAD(bind (mem_fun(*this, &PluginSelector::set_session), s));
160         
161         session = s;
162
163         if (session) {
164                 session->going_away.connect (bind (mem_fun(*this, &PluginSelector::set_session), static_cast<Session*> (0)));
165         }
166 }
167
168 void
169 PluginSelector::_input_refiller (void *arg)
170 {
171
172         ((PluginSelector *) arg)->input_refiller ();
173 }
174
175 int compare(const void *left, const void *right)
176 {
177   return strcmp(*((char**)left), *((char**)right));
178 }
179
180 void
181 PluginSelector::input_refiller ()
182 {
183         guint row;
184         list<PluginInfo *> &plugs = manager->ladspa_plugin_info ();
185         list<PluginInfo *>::iterator i;
186         char ibuf[16], obuf[16];
187         lmodel->clear();
188 #ifdef VST_SUPPORT
189         vmodel->clear();
190 #endif
191         // Insert into GTK list
192         for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
193                 snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
194                 snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
195                 
196                 Gtk::TreeModel::Row newrow = *(lmodel->append());
197                 newrow[lcols.name] = (*i)->name.c_str();
198                 newrow[lcols.type] = (*i)->category.c_str();
199                 newrow[lcols.ins] = ibuf;
200                 newrow[lcols.outs] = obuf;
201                 newrow[lcols.plugin] = *i;
202         }
203
204         lmodel->set_sort_column (0, Gtk::SORT_ASCENDING);
205 }
206
207 #ifdef VST_SUPPORT
208
209 void
210 PluginSelector::_vst_refiller (void *arg)
211 {
212         ((PluginSelector *) arg)->vst_refiller ();
213 }
214
215 void
216 PluginSelector::vst_refiller ()
217 {
218         guint row;
219         list<PluginInfo *> &plugs = manager->vst_plugin_info ();
220         list<PluginInfo *>::iterator i;
221         char ibuf[16], obuf[16];
222         
223         // Insert into GTK list
224         for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
225
226                 snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
227                 snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
228                 
229                 Gtk::TreeModel::Row newrow = *(vmodel->append());
230                 newrow[vcols.name] = (*i)->name.c_str();
231                 newrow[vcols.ins] = ibuf;
232                 newrow[vcols.outs] = obuf;
233                 newrow[vcols.plugin] = *i;
234         }
235         vmodel->set_sort_column (0, Gtk::SORT_ASCENDING);
236 }
237 #endif
238
239 void
240 PluginSelector::use_plugin (PluginInfo* pi)
241 {
242         list<PluginInfo *>::iterator i;
243
244         if (pi == 0 || session == 0) {
245                 return;
246         }
247
248         Plugin *plugin = manager->load (*session, pi);
249
250         if (plugin) {
251                 PluginCreated (plugin);
252         }
253 }
254
255 void
256 PluginSelector::btn_add_clicked()
257 {
258         bool vst = notebook.get_current_page(); // 0 = LADSPA, 1 = VST
259         std::string name;
260         ARDOUR::PluginInfo *pi;
261         Gtk::TreeModel::Row newrow = *(amodel->append());
262         
263         if (vst) {
264 #ifdef VST_SUPPORT
265                 Gtk::TreeModel::Row row = *(vst_display.get_selection()->get_selected());
266                 name = row[vcols.name];
267                 pi = row[vcols.plugin];
268                 added_plugins.push_back (row[vcols.plugin]);
269 #endif
270         } else {
271                 Gtk::TreeModel::Row row = *(ladspa_display.get_selection()->get_selected());
272                 name = row[lcols.name];
273                 pi = row[lcols.plugin];
274                 added_plugins.push_back (row[lcols.plugin]);
275         }
276         newrow[acols.text] = name;
277         newrow[acols.plugin] = pi;
278 }
279
280 void
281 PluginSelector::btn_remove_clicked()
282 {
283         list<PluginInfo*>::iterator i;
284         Gtk::TreeModel::iterator iter = added_list.get_selection()->get_selected();
285         for (i = added_plugins.begin(); (*i) != (*iter)[acols.plugin]; ++i);
286
287         added_plugins.erase(i); 
288         amodel->erase(iter);
289 }
290
291 void
292 PluginSelector::btn_update_clicked()
293 {
294         manager->refresh ();
295         input_refiller ();
296 }
297
298 int
299 PluginSelector::run ()
300 {
301         ResponseType r;
302         list<PluginInfo*>::iterator i;
303
304         r = (ResponseType) Dialog::run ();
305
306         switch (r) {
307         case RESPONSE_APPLY:
308                 for (i = added_plugins.begin(); i != added_plugins.end(); ++i){
309                         use_plugin (*i);
310                 }
311                 break;
312
313         default:
314                 break;
315         }
316
317         cleanup ();
318
319         return (int) r;
320 }
321
322 void
323 PluginSelector::cleanup ()
324 {
325         hide();
326         added_plugins.clear();
327         amodel->clear();
328 }
329