Fly my pretties!
[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/button.h>
25 #include <gtkmm/notebook.h>
26 #include <gtkmm/ctree.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
40 static const gchar *i_titles[] = {
41         N_("Available LADSPA plugins"), 
42         N_("Type"),
43         N_("# Inputs"), 
44         N_("# Outputs"),
45         0
46 };
47
48 #ifdef VST_SUPPORT
49 static const gchar *vst_titles[] = {
50         N_("Available VST plugins"), 
51         N_("# Inputs"), 
52         N_("# Outputs"),
53         0
54 };
55 #endif
56
57 static const gchar *o_titles[] = {
58         N_("To be added"),
59         0
60 };
61
62 PluginSelector::PluginSelector (PluginManager *mgr)
63         : ArdourDialog ("plugin selector"),
64           ladspa_display (_input_refiller, this, internationalize (i_titles), false, true),
65 #ifdef VST_SUPPORT
66          vst_display (_vst_refiller, this, internationalize (vst_titles), false, true),
67 #endif
68           o_selector (_output_refiller, this, internationalize (o_titles), false, true)
69 {
70         set_position (Gtk::WIN_POS_MOUSE);
71         set_name ("PluginSelectorWindow");
72         set_title (_("ardour: plugins"));
73         set_modal(true);
74         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
75
76         manager = mgr;
77         session = 0;
78         o_selected_plug = -1;
79         i_selected_plug = 0;
80
81         Gtk::Button *btn_add = manage(new Gtk::Button(_("Add")));
82         ARDOUR_UI::instance()->tooltips().set_tip(*btn_add, _("Add a plugin to the effect list"));
83         Gtk::Button *btn_remove = manage(new Gtk::Button(_("Remove")));
84         ARDOUR_UI::instance()->tooltips().set_tip(*btn_remove, _("Remove a plugin from the effect list"));
85         Gtk::Button *btn_ok = manage(new Gtk::Button(_("OK")));
86         Gtk::Button *btn_cancel = manage(new Gtk::Button(_("Cancel")));
87
88         Gtk::Button *btn_update = manage(new Gtk::Button(_("Update")));
89         ARDOUR_UI::instance()->tooltips().set_tip(*btn_update, _("Update available plugins"));
90
91         btn_ok->set_name("PluginSelectorButton");
92         btn_cancel->set_name("PluginSelectorButton");
93         btn_add->set_name("PluginSelectorButton");
94         btn_remove->set_name("PluginSelectorButton");
95         
96         Gtk::Table* table = manage(new Gtk::Table(7, 10));
97         table->set_size_request(750, 500);
98         table->attach(notebook, 0, 7, 0, 5);
99
100         table->attach(*btn_add, 1, 2, 5, 6, Gtk::FILL, 0, 5, 5);
101         table->attach(*btn_remove, 3, 4, 5, 6, Gtk::FILL, 0, 5, 5);
102         table->attach(*btn_update, 5, 6, 5, 6, Gtk::FILL, 0, 5, 5);
103
104         table->attach(o_selector, 0, 7, 7, 9);
105         table->attach(*btn_ok, 1, 3, 9, 10, Gtk::FILL, 0, 5, 5);
106         table->attach(*btn_cancel, 3, 4, 9, 10, Gtk::FILL, 0, 5, 5);
107         add (*table);
108
109         using namespace Gtk::Notebook_Helpers;
110         notebook.pages().push_back (TabElem (ladspa_display, _("LADSPA")));
111 #ifdef VST_SUPPORT
112         if (Config->get_use_vst()) {
113                 notebook.pages().push_back (TabElem (vst_display, _("VST")));
114         }
115 #endif
116
117         table->set_name("PluginSelectorTable");
118         //ladspa_display.set_name("PluginSelectorDisplay");
119         ladspa_display.clist().set_name("PluginSelectorList");
120         o_selector.clist().set_name("PluginSelectorList");
121         
122         ladspa_display.clist().column_titles_active();
123         ladspa_display.clist().column(0).set_auto_resize (false);
124         ladspa_display.clist().column(0).set_width(470);
125
126         ladspa_display.clist().column(1).set_auto_resize (true);
127         o_selector.clist().column(0).set_auto_resize (true);
128
129         ladspa_display.selection_made.connect (slot(*this, &PluginSelector::i_plugin_selected));
130         ladspa_display.choice_made.connect(slot(*this, &PluginSelector::i_plugin_chosen));
131         ladspa_display.clist().click_column.connect(bind (slot(*this, &PluginSelector::column_clicked), ladspa_display.clist().gobj()));
132 #ifdef VST_SUPPORT
133         if (Config->get_use_vst()) {
134                 vst_display.selection_made.connect (slot(*this, &PluginSelector::i_plugin_selected));
135                 vst_display.choice_made.connect(slot(*this, &PluginSelector::i_plugin_chosen));
136                 vst_display.clist().click_column.connect(bind (slot(*this, &PluginSelector::column_clicked), vst_display.clist().gobj()));
137         }
138 #endif
139         o_selector.selection_made.connect(slot(*this, &PluginSelector::o_plugin_selected));
140         o_selector.choice_made.connect(slot(*this,&PluginSelector::o_plugin_chosen));
141         btn_update-.signal_clicked().connect (slot(*this, &PluginSelector::btn_update_clicked));
142         btn_add->clicked.connect(slot(*this, &PluginSelector::btn_add_clicked));
143         btn_remove->clicked.connect(slot(*this, &PluginSelector::btn_remove_clicked));
144         btn_ok->clicked.connect(slot(*this, &PluginSelector::btn_ok_clicked));
145         btn_cancel->clicked.connect(slot(*this,&PluginSelector::btn_cancel_clicked));
146         delete_event.connect (slot (*this, &PluginSelector::wm_close));
147
148 }
149
150 void
151 PluginSelector::set_session (Session* s)
152 {
153         ENSURE_GUI_THREAD(bind (slot (*this, &PluginSelector::set_session), s));
154         
155         session = s;
156
157         if (session) {
158                 session->going_away.connect (bind (slot (*this, &PluginSelector::set_session), static_cast<Session*> (0)));
159         }
160 }
161
162 void
163 PluginSelector::_input_refiller (Gtk::CList &list, void *arg)
164 {
165         ((PluginSelector *) arg)->input_refiller (list);
166 }
167
168 void
169 PluginSelector::_output_refiller (Gtk::CList &list, void *arg)
170 {
171         ((PluginSelector *) arg)->output_refiller (list);
172 }
173
174 int compare(const void *left, const void *right)
175 {
176   return strcmp(*((char**)left), *((char**)right));
177 }
178
179 void
180 PluginSelector::input_refiller (Gtk::CList &clist)
181 {
182         const gchar *rowdata[4];
183         guint row;
184         list<PluginInfo *> &plugs = manager->ladspa_plugin_info ();
185         list<PluginInfo *>::iterator i;
186         char ibuf[16], obuf[16];
187         
188         // Insert into GTK list
189         for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
190                 rowdata[0] = (*i)->name.c_str();
191                 rowdata[1] = (*i)->category.c_str();
192
193                 snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
194                 snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
195                 rowdata[2] = ibuf;
196                 rowdata[3] = obuf;
197                 
198                 clist.insert_row (row, rowdata);
199                 clist.rows().back().set_data (*i);
200         }
201
202         clist.set_sort_column (0);
203         clist.sort ();
204 }
205
206 #ifdef VST_SUPPORT
207
208 void
209 PluginSelector::_vst_refiller (Gtk::CList &list, void *arg)
210 {
211         ((PluginSelector *) arg)->vst_refiller (list);
212 }
213
214 void
215 PluginSelector::vst_refiller (Gtk::CList &clist)
216 {
217         const gchar *rowdata[3];
218         guint row;
219         list<PluginInfo *> &plugs = manager->vst_plugin_info ();
220         list<PluginInfo *>::iterator i;
221         char ibuf[16], obuf[16];
222         
223         if (!Config->get_use_vst()) {
224                 return;
225         }
226
227         // Insert into GTK list
228
229         for (row = 0, i = plugs.begin(); i != plugs.end(); ++i, ++row) {
230                 rowdata[0] = (*i)->name.c_str();
231
232                 snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
233                 snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
234                 rowdata[1] = ibuf;
235                 rowdata[2] = obuf;
236                 
237                 clist.insert_row (row, rowdata);
238                 clist.rows().back().set_data (*i);
239         }
240
241         clist.set_sort_column (0);
242         clist.sort ();
243 }
244 #endif
245
246 void
247 PluginSelector::output_refiller (Gtk::CList &clist)
248 {
249         const gchar *rowdata[2];
250         guint row;
251         list<PluginInfo*>::iterator i;
252         
253         // Insert into GTK list
254
255         for (row = 0, i = added_plugins.begin(); i != added_plugins.end(); ++i, ++row){
256                 rowdata[0] = (*i)->name.c_str();
257                 clist.insert_row (row, rowdata);
258                 clist.rows().back().set_data (*i);
259         }
260 }
261
262 void
263 PluginSelector::i_plugin_chosen (Gtkmm2ext::Selector *selector,
264                                  Gtkmm2ext::SelectionResult *res)
265 {
266         if (res) {
267                 // get text for name column (0)
268                 i_selected_plug = static_cast<PluginInfo*> (selector->clist().row(res->row).get_data());
269                 //i_selected_plug = *res->text;
270         } else {
271                 i_selected_plug = 0;
272         }
273 }
274
275 void
276 PluginSelector::i_plugin_selected (Gtkmm2ext::Selector *selector,
277                                    Gtkmm2ext::SelectionResult *res)
278 {
279         if (res) {
280                 added_plugins.push_back (static_cast<PluginInfo*> (selector->clist().row(res->row).get_data()));
281                 //added_plugins.push_back(*(res->text));
282                 o_selector.rescan();
283         }
284 }
285
286 void
287 PluginSelector::o_plugin_chosen (Gtkmm2ext::Selector *selector,
288                               Gtkmm2ext::SelectionResult *res)
289 {
290         if (res && res->text) {
291                 o_selected_plug = res->row;
292         } else {
293                 o_selected_plug = -1;
294         }
295
296 }
297
298 void
299 PluginSelector::o_plugin_selected (Gtkmm2ext::Selector *selector,
300                                 Gtkmm2ext::SelectionResult *res)
301 {
302         if(res && res->text){
303                 gint row = 0;
304                 list<PluginInfo*>::iterator i = added_plugins.begin();
305                 while (row < res->row){
306                         i++;
307                         row++;
308                 }
309                 added_plugins.erase(i);
310                 o_selector.rescan();
311                 o_selected_plug = -1;
312         }
313 }
314
315 void
316 PluginSelector::use_plugin (PluginInfo* pi)
317 {
318         list<PluginInfo *>::iterator i;
319
320         if (pi == 0 || session == 0) {
321                 return;
322         }
323
324         Plugin *plugin = manager->load (*session, pi);
325
326         if (plugin) {
327                 PluginCreated (plugin);
328         }
329 }
330
331 void
332 PluginSelector::btn_add_clicked()
333 {
334         if (i_selected_plug) {
335                 added_plugins.push_back (i_selected_plug);
336                 o_selector.rescan();
337         }
338 }
339
340 void
341 PluginSelector::btn_remove_clicked()
342 {
343         if (o_selected_plug > -1){
344                 gint row = 0;
345                 list<PluginInfo*>::iterator i = added_plugins.begin();
346                 while(row < o_selected_plug){
347                         i++;
348                         row++;
349                 }
350                 added_plugins.erase(i);
351                 o_selector.rescan();
352                 o_selected_plug = -1;
353         }
354 }
355
356 // Adds a plugin, and closes the window.
357 void 
358 PluginSelector::btn_ok_clicked()
359 {
360         using namespace Gtk::CList_Helpers;
361
362         list<PluginInfo*>::iterator i;
363
364         for (i = added_plugins.begin(); i != added_plugins.end(); ++i){
365                 use_plugin (*i);
366         }
367
368         hide();
369         added_plugins.clear();
370         o_selector.rescan();
371         i_selected_plug = 0;
372         o_selected_plug = -1;
373
374         SelectionList s_list = ladspa_display.clist().selection();
375         SelectionList::iterator s = s_list.begin();
376         if (s != s_list.end()) {
377                 (*s).unselect();
378         }
379
380 #ifdef VST_SUPPORT
381         SelectionList v_list = vst_display.clist().selection();
382         SelectionList::iterator v = v_list.begin();
383         if (v != v_list.end()) {
384                 (*v).unselect();
385         }
386 #endif
387 }
388
389 void
390 PluginSelector::btn_cancel_clicked()
391 {
392         hide();
393         added_plugins.clear();
394         o_selector.rescan();
395         i_selected_plug = 0;
396         o_selected_plug = -1;
397 }
398
399 void
400 PluginSelector::btn_update_clicked()
401 {
402         manager->refresh ();
403         ladspa_display.rescan ();
404 }
405
406 gint
407 PluginSelector::wm_close(GdkEventAny* ev)
408 {
409         btn_cancel_clicked();
410         return TRUE;
411 }
412
413 void
414 PluginSelector::column_clicked (int column, GtkCList* clist)
415 {
416         gtk_clist_set_sort_column (clist, column);
417         gtk_clist_sort (clist);
418 }