ardour
plugin_selector.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000-2006 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 #ifdef WAF_BUILD
20 #include "gtk2ardour-config.h"
21 #endif
22 
23 #include <cstdio>
24 #include <map>
25 
26 #include <algorithm>
27 
28 #include <gtkmm/table.h>
29 #include <gtkmm/stock.h>
30 #include <gtkmm/button.h>
31 #include <gtkmm/notebook.h>
32 
33 #include <gtkmm2ext/utils.h>
34 
35 #include "pbd/convert.h"
36 
37 #include "ardour/plugin_manager.h"
38 #include "ardour/plugin.h"
39 #include "ardour/utils.h"
40 
41 #include "ardour_ui.h"
42 #include "plugin_selector.h"
43 #include "gui_thread.h"
44 
45 #include "i18n.h"
46 
47 using namespace ARDOUR;
48 using namespace PBD;
49 using namespace Gtk;
50 using namespace std;
51 
52 static const char* _filter_mode_strings[] = {
53  N_("Name contains"),
54  N_("Type contains"),
55  N_("Category contains"),
56  N_("Author contains"),
57  N_("Library contains"),
58  N_("Favorites only"),
59  N_("Hidden only"),
60  0
61 };
62 
64  : ArdourDialog (_("Plugin Manager"), true, false)
65  , filter_button (Stock::CLEAR)
66  , manager (mgr)
67 
68 {
69  set_name ("PluginSelectorWindow");
70  add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
71 
72  _plugin_menu = 0;
73  in_row_change = false;
74 
78 
79  plugin_model = Gtk::ListStore::create (plugin_columns);
80  plugin_display.set_model (plugin_model);
81  /* XXX translators: try to convert "Fav" into a short term
82  related to "favorite" and "Hid" into a short term
83  related to "hidden"
84  */
85  plugin_display.append_column (_("Fav"), plugin_columns.favorite);
86  plugin_display.append_column (_("Hide"), plugin_columns.hidden);
87  plugin_display.append_column (_("Available Plugins"), plugin_columns.name);
88  plugin_display.append_column (_("Type"), plugin_columns.type_name);
89  plugin_display.append_column (_("Category"), plugin_columns.category);
90  plugin_display.append_column (_("Creator"), plugin_columns.creator);
91  plugin_display.append_column (_("# Audio In"),plugin_columns.audio_ins);
92  plugin_display.append_column (_("# Audio Out"), plugin_columns.audio_outs);
93  plugin_display.append_column (_("# MIDI In"),plugin_columns.midi_ins);
94  plugin_display.append_column (_("# MIDI Out"), plugin_columns.midi_outs);
95  plugin_display.set_headers_visible (true);
96  plugin_display.set_headers_clickable (true);
97  plugin_display.set_reorderable (false);
98  plugin_display.set_rules_hint (true);
99 
100  CellRendererToggle* fav_cell = dynamic_cast<CellRendererToggle*>(plugin_display.get_column_cell_renderer (0));
101  fav_cell->property_activatable() = true;
102  fav_cell->property_radio() = true;
103  fav_cell->signal_toggled().connect (sigc::mem_fun (*this, &PluginSelector::favorite_changed));
104 
105  CellRendererToggle* hidden_cell = dynamic_cast<CellRendererToggle*>(plugin_display.get_column_cell_renderer (1));
106  hidden_cell->property_activatable() = true;
107  hidden_cell->property_radio() = true;
108  hidden_cell->signal_toggled().connect (sigc::mem_fun (*this, &PluginSelector::hidden_changed));
109 
110  scroller.set_border_width(10);
111  scroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
113 
114  amodel = Gtk::ListStore::create(acols);
115  added_list.set_model (amodel);
116  added_list.append_column (_("Plugins to be connected"), acols.text);
117  added_list.set_headers_visible (true);
118  added_list.set_reorderable (false);
119 
120  for (int i = 0; i <=8; i++) {
121  Gtk::TreeView::Column* column = plugin_display.get_column(i);
122  column->set_sort_column(i);
123  }
124 
125  ascroller.set_border_width(10);
126  ascroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
127  ascroller.add(added_list);
128  btn_add = manage(new Gtk::Button(Stock::ADD));
129  ARDOUR_UI::instance()->set_tip(*btn_add, _("Add a plugin to the effect list"));
130  btn_add->set_sensitive (false);
131  btn_remove = manage(new Gtk::Button(Stock::REMOVE));
132  btn_remove->set_sensitive (false);
133  ARDOUR_UI::instance()->set_tip(*btn_remove, _("Remove a plugin from the effect list"));
134  Gtk::Button *btn_update = manage(new Gtk::Button(Stock::REFRESH));
135  ARDOUR_UI::instance()->set_tip(*btn_update, _("Update available plugins"));
136 
137  btn_add->set_name("PluginSelectorButton");
138  btn_remove->set_name("PluginSelectorButton");
139 
140  Gtk::Table* table = manage(new Gtk::Table(7, 11));
141  table->set_size_request(750, 500);
142  table->attach(scroller, 0, 7, 0, 5);
143 
144  HBox* filter_box = manage (new HBox);
145 
146  vector<string> filter_strings = I18N (_filter_mode_strings);
148  filter_mode.set_active_text (filter_strings.front());
149 
150  filter_box->pack_start (filter_mode, false, false);
151  filter_box->pack_start (filter_entry, true, true);
152  filter_box->pack_start (filter_button, false, false);
153 
154  filter_entry.signal_changed().connect (sigc::mem_fun (*this, &PluginSelector::filter_entry_changed));
155  filter_button.signal_clicked().connect (sigc::mem_fun (*this, &PluginSelector::filter_button_clicked));
156  filter_mode.signal_changed().connect (sigc::mem_fun (*this, &PluginSelector::filter_mode_changed));
157 
158  filter_box->show ();
159  filter_mode.show ();
160  filter_entry.show ();
161  filter_button.show ();
162 
163  table->attach (*filter_box, 0, 7, 5, 6, FILL|EXPAND, FILL, 5, 5);
164 
165  table->attach(*btn_add, 1, 2, 6, 7, FILL, FILL, 5, 5);
166  table->attach(*btn_remove, 3, 4, 6, 7, FILL, FILL, 5, 5);
167  table->attach(*btn_update, 5, 6, 6, 7, FILL, FILL, 5, 5);
168 
169  table->attach(ascroller, 0, 7, 8, 10);
170 
171  add_button (Stock::CLOSE, RESPONSE_CLOSE);
172  add_button (_("Insert Plugin(s)"), RESPONSE_APPLY);
173  set_default_response (RESPONSE_APPLY);
174  set_response_sensitive (RESPONSE_APPLY, false);
175  get_vbox()->pack_start (*table);
176 
177  table->set_name("PluginSelectorTable");
178  plugin_display.set_name("PluginSelectorDisplay");
179  //plugin_display.set_name("PluginSelectorList");
180  added_list.set_name("PluginSelectorList");
181 
182  plugin_display.signal_row_activated().connect_notify (sigc::mem_fun(*this, &PluginSelector::row_activated));
183  plugin_display.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &PluginSelector::display_selection_changed));
184  plugin_display.grab_focus();
185 
186  btn_update->signal_clicked().connect (sigc::mem_fun(*this, &PluginSelector::btn_update_clicked));
187  btn_add->signal_clicked().connect(sigc::mem_fun(*this, &PluginSelector::btn_add_clicked));
188  btn_remove->signal_clicked().connect(sigc::mem_fun(*this, &PluginSelector::btn_remove_clicked));
189  added_list.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &PluginSelector::added_list_selection_changed));
190  added_list.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::added_row_clicked));
191 
192  refill ();
193 }
194 
196 {
197  delete _plugin_menu;
198 }
199 
200 void
201 PluginSelector::row_activated(Gtk::TreeModel::Path, Gtk::TreeViewColumn*)
202 {
203  btn_add_clicked();
204 }
205 
206 void
207 PluginSelector::added_row_clicked(GdkEventButton* event)
208 {
209  if (event->type == GDK_2BUTTON_PRESS)
211 }
212 
213 bool
214 PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& filterstr)
215 {
216  std::string compstr;
217  std::string mode = filter_mode.get_active_text ();
218 
219  if (mode == _("Favorites only")) {
220  return manager.get_status (info) == PluginManager::Favorite;
221  }
222 
223  if (mode == _("Hidden only")) {
224  return manager.get_status (info) == PluginManager::Hidden;
225  }
226 
227  if (!filterstr.empty()) {
228 
229  if (mode == _("Name contains")) {
230  compstr = info->name;
231  } else if (mode == _("Category contains")) {
232  compstr = info->category;
233  } else if (mode == _("Type contains")) {
234 
235  switch (info->type) {
236  case LADSPA:
237  compstr = X_("LADSPA");
238  break;
239  case AudioUnit:
240  compstr = X_("AudioUnit");
241  break;
242  case LV2:
243  compstr = X_("LV2");
244  break;
245  case Windows_VST:
246  compstr = X_("VST");
247  break;
248  case LXVST:
249  compstr = X_("LXVST");
250  break;
251  }
252 
253  } else if (mode == _("Author contains")) {
254  compstr = info->creator;
255  } else if (mode == _("Library contains")) {
256  compstr = info->path;
257  }
258 
259  if (compstr.empty()) {
260  return false;
261  }
262 
263  transform (compstr.begin(), compstr.end(), compstr.begin(), ::toupper);
264 
265  if (compstr.find (filterstr) != string::npos) {
266  return true;
267  } else {
268  return false;
269  }
270  }
271 
272  return true;
273 }
274 
275 void
277 {
278  filterstr = filter_entry.get_text ();
279  transform (filterstr.begin(), filterstr.end(), filterstr.begin(), ::toupper);
280 }
281 
282 void
284 {
285  std::string filterstr;
286 
287  in_row_change = true;
288 
289  plugin_model->clear ();
290 
291  setup_filter_string (filterstr);
292 
293  ladspa_refiller (filterstr);
294  lv2_refiller (filterstr);
295  vst_refiller (filterstr);
296  lxvst_refiller (filterstr);
297  au_refiller (filterstr);
298 
299  in_row_change = false;
300 }
301 
302 void
303 PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filterstr, const char* type)
304 {
305  char buf[16];
306 
307  for (PluginInfoList::const_iterator i = plugs.begin(); i != plugs.end(); ++i) {
308 
309  if (show_this_plugin (*i, filterstr)) {
310 
311  TreeModel::Row newrow = *(plugin_model->append());
312  newrow[plugin_columns.favorite] = (manager.get_status (*i) == PluginManager::Favorite);
313  newrow[plugin_columns.hidden] = (manager.get_status (*i) == PluginManager::Hidden);
314  newrow[plugin_columns.name] = (*i)->name;
315  newrow[plugin_columns.type_name] = type;
316  newrow[plugin_columns.category] = (*i)->category;
317 
318  string creator = (*i)->creator;
319  string::size_type pos = 0;
320 
321  /* stupid LADSPA creator strings */
322 #ifdef PLATFORM_WINDOWS
323  while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos;
324 #else
325  while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos;
326 #endif
327  // If there were too few characters to create a
328  // meaningful name, mark this creator as 'Unknown'
329  if (creator.length()<2 || pos<3)
330  creator = "Unknown";
331  else
332  creator = creator.substr (0, pos);
333 
334  newrow[plugin_columns.creator] = creator;
335 
336  if ((*i)->reconfigurable_io ()) {
337  newrow[plugin_columns.audio_ins] = _("variable");
338  newrow[plugin_columns.midi_ins] = _("variable");
339  newrow[plugin_columns.audio_outs] = _("variable");
340  newrow[plugin_columns.midi_outs] = _("variable");
341  } else {
342  snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_audio());
343  newrow[plugin_columns.audio_ins] = buf;
344  snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_midi());
345  newrow[plugin_columns.midi_ins] = buf;
346 
347  snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_audio());
348  newrow[plugin_columns.audio_outs] = buf;
349  snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_midi());
350  newrow[plugin_columns.midi_outs] = buf;
351  }
352 
353  newrow[plugin_columns.plugin] = *i;
354  }
355  }
356 }
357 
358 void
359 PluginSelector::ladspa_refiller (const std::string& filterstr)
360 {
361  refiller (manager.ladspa_plugin_info(), filterstr, "LADSPA");
362 }
363 
364 void
365 PluginSelector::lv2_refiller (const std::string& filterstr)
366 {
367 #ifdef LV2_SUPPORT
368  refiller (manager.lv2_plugin_info(), filterstr, "LV2");
369 #endif
370 }
371 
372 void
373 #ifdef WINDOWS_VST_SUPPORT
374 PluginSelector::vst_refiller (const std::string& filterstr)
375 #else
376 PluginSelector::vst_refiller (const std::string&)
377 #endif
378 {
379 #ifdef WINDOWS_VST_SUPPORT
380  refiller (manager.windows_vst_plugin_info(), filterstr, "VST");
381 #endif
382 }
383 
384 void
385 #ifdef LXVST_SUPPORT
386 PluginSelector::lxvst_refiller (const std::string& filterstr)
387 #else
388 PluginSelector::lxvst_refiller (const std::string&)
389 #endif
390 {
391 #ifdef LXVST_SUPPORT
392  refiller (manager.lxvst_plugin_info(), filterstr, "LXVST");
393 #endif
394 }
395 
396 void
397 #ifdef AUDIOUNIT_SUPPORT
398 PluginSelector::au_refiller (const std::string& filterstr)
399 #else
400 PluginSelector::au_refiller (const std::string&)
401 #endif
402 {
403 #ifdef AUDIOUNIT_SUPPORT
404  refiller (manager.au_plugin_info(), filterstr, "AU");
405 #endif
406 }
407 
408 PluginPtr
410 {
411  if (_session == 0) {
412  return PluginPtr();
413  }
414 
415  return pi->load (*_session);
416 }
417 
418 void
420 {
421  std::string name;
422  PluginInfoPtr pi;
423  TreeModel::Row newrow = *(amodel->append());
424  TreeModel::Row row;
425 
426  row = *(plugin_display.get_selection()->get_selected());
427  name = row[plugin_columns.name];
428  pi = row[plugin_columns.plugin];
429 
430  newrow[acols.text] = name;
431  newrow[acols.plugin] = pi;
432 
433  if (!amodel->children().empty()) {
434  set_response_sensitive (RESPONSE_APPLY, true);
435  }
436 }
437 
438 void
440 {
441  TreeModel::iterator iter = added_list.get_selection()->get_selected();
442 
443  amodel->erase(iter);
444  if (amodel->children().empty()) {
445  set_response_sensitive (RESPONSE_APPLY, false);
446  }
447 }
448 
449 void
451 {
452  manager.refresh ();
453 }
454 
455 void
457 {
458  if (plugin_display.get_selection()->count_selected_rows() != 0) {
459  btn_add->set_sensitive (true);
460  } else {
461  btn_add->set_sensitive (false);
462  }
463 }
464 
465 void
467 {
468  if (added_list.get_selection()->count_selected_rows() != 0) {
469  btn_remove->set_sensitive (true);
470  } else {
471  btn_remove->set_sensitive (false);
472  }
473 }
474 
475 int
477 {
478  ResponseType r;
479  TreeModel::Children::iterator i;
480 
481  bool finish = false;
482 
483  while (!finish) {
484 
485  SelectedPlugins plugins;
486  r = (ResponseType) Dialog::run ();
487 
488  switch (r) {
489  case RESPONSE_APPLY:
490  for (i = amodel->children().begin(); i != amodel->children().end(); ++i) {
491  PluginInfoPtr pp = (*i)[acols.plugin];
492  PluginPtr p = load_plugin (pp);
493  if (p) {
494  plugins.push_back (p);
495  } else {
496  MessageDialog msg (string_compose (_("The plugin \"%1\" could not be loaded\n\nSee the Log window for more details (maybe)"), pp->name));
497  msg.run ();
498  }
499  }
500  if (interested_object && !plugins.empty()) {
501  finish = !interested_object->use_plugins (plugins);
502  }
503 
504  break;
505 
506  default:
507  finish = true;
508  break;
509  }
510  }
511 
512 
513  hide();
514  amodel->clear();
515  interested_object = 0;
516 
517  return (int) r;
518 }
519 
520 void
522 {
523  filter_entry.set_text ("");
524 }
525 
526 void
528 {
529  refill ();
530 }
531 
532 void
534 {
535  std::string mode = filter_mode.get_active_text ();
536 
537  if (mode == _("Favorites only") || mode == _("Hidden only")) {
538  filter_entry.set_sensitive (false);
539  } else {
540  filter_entry.set_sensitive (true);
541  }
542 
543  refill ();
544 }
545 
546 void
548 {
550  filter_entry.grab_focus ();
551 }
552 
555  int cmp;
556 
557  cmp = cmp_nocase_utf8 (a->creator, b->creator);
558 
559  if (cmp < 0) {
560  return true;
561  } else if (cmp == 0) {
562  /* same creator ... compare names */
563  if (cmp_nocase_utf8 (a->name, b->name) < 0) {
564  return true;
565  }
566  }
567  return false;
568  }
569 };
570 
573  int cmp;
574 
575  cmp = cmp_nocase_utf8 (a->name, b->name);
576 
577  if (cmp < 0) {
578  return true;
579  } else if (cmp == 0) {
580  /* same name ... compare type */
581  if (a->type < b->type) {
582  return true;
583  }
584  }
585  return false;
586  }
587 };
588 
591  int cmp;
592 
593  cmp = cmp_nocase_utf8 (a->category, b->category);
594 
595  if (cmp < 0) {
596  return true;
597  } else if (cmp == 0) {
598  /* same category ... compare names */
599  if (cmp_nocase_utf8 (a->name, b->name) < 0) {
600  return true;
601  }
602  }
603  return false;
604  }
605 };
606 
608 Gtk::Menu*
610 {
611  return _plugin_menu;
612 }
613 
614 void
616 {
617  PluginInfoList all_plugs;
618 
619  all_plugs.insert (all_plugs.end(), manager.ladspa_plugin_info().begin(), manager.ladspa_plugin_info().end());
620 #ifdef WINDOWS_VST_SUPPORT
621  all_plugs.insert (all_plugs.end(), manager.windows_vst_plugin_info().begin(), manager.windows_vst_plugin_info().end());
622 #endif
623 #ifdef LXVST_SUPPORT
624  all_plugs.insert (all_plugs.end(), manager.lxvst_plugin_info().begin(), manager.lxvst_plugin_info().end());
625 #endif
626 #ifdef AUDIOUNIT_SUPPORT
627  all_plugs.insert (all_plugs.end(), manager.au_plugin_info().begin(), manager.au_plugin_info().end());
628 #endif
629 #ifdef LV2_SUPPORT
630  all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
631 #endif
632 
633  using namespace Menu_Helpers;
634 
635  delete _plugin_menu;
636 
637  _plugin_menu = manage (new Menu);
638  _plugin_menu->set_name("ArdourContextMenu");
639 
640  MenuList& items = _plugin_menu->items();
641  items.clear ();
642 
643  Gtk::Menu* favs = create_favs_menu(all_plugs);
644  items.push_back (MenuElem (_("Favorites"), *manage (favs)));
645 
646  items.push_back (MenuElem (_("Plugin Manager..."), sigc::mem_fun (*this, &PluginSelector::show_manager)));
647  items.push_back (SeparatorElem ());
648 
649  Menu* by_creator = create_by_creator_menu(all_plugs);
650  items.push_back (MenuElem (_("By Creator"), *manage (by_creator)));
651 
652  Menu* by_category = create_by_category_menu(all_plugs);
653  items.push_back (MenuElem (_("By Category"), *manage (by_category)));
654 }
655 
656 Gtk::Menu*
658 {
659  using namespace Menu_Helpers;
660 
661  Menu* favs = new Menu();
662  favs->set_name("ArdourContextMenu");
663 
664  PluginMenuCompareByName cmp_by_name;
665  all_plugs.sort (cmp_by_name);
666 
667  for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
668  if (manager.get_status (*i) == PluginManager::Favorite) {
669  MenuElem elem ((*i)->name, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i)));
670  elem.get_child()->set_use_underline (false);
671  favs->items().push_back (elem);
672  }
673  }
674  return favs;
675 }
676 
677 Gtk::Menu*
679 {
680  using namespace Menu_Helpers;
681 
682  typedef std::map<std::string,Gtk::Menu*> SubmenuMap;
683  SubmenuMap creator_submenu_map;
684 
685  Menu* by_creator = new Menu();
686  by_creator->set_name("ArdourContextMenu");
687 
688  MenuList& by_creator_items = by_creator->items();
689  PluginMenuCompareByCreator cmp_by_creator;
690  all_plugs.sort (cmp_by_creator);
691 
692  for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
693 
694  if (manager.get_status (*i) == PluginManager::Hidden) continue;
695 
696  string creator = (*i)->creator;
697 
698  /* stupid LADSPA creator strings */
699  string::size_type pos = 0;
700 #ifdef PLATFORM_WINDOWS
701  while (pos < creator.length() && creator[pos]>(-2) && creator[pos]<256 && (isprint (creator[pos]))) ++pos;
702 #else
703  while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos;
704 #endif
705 
706  // Check to see if we found any invalid characters.
707  if (creator.length() != pos) {
708  // If there were too few characters to create a
709  // meaningful name, mark this creator as 'Unknown'
710  if (pos<3)
711  creator = "Unknown?";
712  else
713  creator = creator.substr (0, pos);
714  }
715 
716  SubmenuMap::iterator x;
717  Gtk::Menu* submenu;
718  if ((x = creator_submenu_map.find (creator)) != creator_submenu_map.end()) {
719  submenu = x->second;
720  } else {
721  submenu = new Gtk::Menu;
722  by_creator_items.push_back (MenuElem (creator, *manage (submenu)));
723  creator_submenu_map.insert (pair<std::string,Menu*> (creator, submenu));
724  submenu->set_name("ArdourContextMenu");
725  }
726  MenuElem elem ((*i)->name, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i)));
727  elem.get_child()->set_use_underline (false);
728  submenu->items().push_back (elem);
729  }
730  return by_creator;
731 }
732 
733 Gtk::Menu*
735 {
736  using namespace Menu_Helpers;
737 
738  typedef std::map<std::string,Gtk::Menu*> SubmenuMap;
739  SubmenuMap category_submenu_map;
740 
741  Menu* by_category = new Menu();
742  by_category->set_name("ArdourContextMenu");
743 
744  MenuList& by_category_items = by_category->items();
745  PluginMenuCompareByCategory cmp_by_category;
746  all_plugs.sort (cmp_by_category);
747 
748  for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
749 
750  if (manager.get_status (*i) == PluginManager::Hidden) continue;
751 
752  string category = (*i)->category;
753 
754  SubmenuMap::iterator x;
755  Gtk::Menu* submenu;
756  if ((x = category_submenu_map.find (category)) != category_submenu_map.end()) {
757  submenu = x->second;
758  } else {
759  submenu = new Gtk::Menu;
760  by_category_items.push_back (MenuElem (category, *manage (submenu)));
761  category_submenu_map.insert (pair<std::string,Menu*> (category, submenu));
762  submenu->set_name("ArdourContextMenu");
763  }
764  MenuElem elem ((*i)->name, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i)));
765  elem.get_child()->set_use_underline (false);
766  submenu->items().push_back (elem);
767  }
768  return by_category;
769 }
770 
771 void
773 {
774  PluginPtr p = load_plugin (pi);
775 
776  if (p && interested_object) {
777  SelectedPlugins plugins;
778  plugins.push_back (p);
779  interested_object->use_plugins (plugins);
780  }
781 
782  interested_object = 0;
783 }
784 
785 void
786 PluginSelector::favorite_changed (const std::string& path)
787 {
788  PluginInfoPtr pi;
789 
790  if (in_row_change) {
791  return;
792  }
793 
794  in_row_change = true;
795 
796  TreeModel::iterator iter = plugin_model->get_iter (path);
797 
798  if (iter) {
799 
800  bool favorite = !(*iter)[plugin_columns.favorite];
801 
802  /* change state */
803 
804  (*iter)[plugin_columns.favorite] = favorite;
805  (*iter)[plugin_columns.hidden] = false;
806  PluginManager::PluginStatusType status = (favorite ? PluginManager::Favorite : PluginManager::Normal);
807 
808  /* save new statuses list */
809 
810  pi = (*iter)[plugin_columns.plugin];
811 
812  manager.set_status (pi->type, pi->unique_id, status);
813 
815 
817  }
818  in_row_change = false;
819 }
820 
821 void
822 PluginSelector::hidden_changed (const std::string& path)
823 {
824  PluginInfoPtr pi;
825 
826  if (in_row_change) {
827  return;
828  }
829 
830  in_row_change = true;
831 
832  TreeModel::iterator iter = plugin_model->get_iter (path);
833 
834  if (iter) {
835 
836  bool hidden = !(*iter)[plugin_columns.hidden];
837 
838  /* change state */
839 
840  (*iter)[plugin_columns.favorite] = false;
841  (*iter)[plugin_columns.hidden] = hidden;
842  PluginManager::PluginStatusType status = (hidden ? PluginManager::Hidden : PluginManager::Normal);
843 
844  /* save new statuses list */
845 
846  pi = (*iter)[plugin_columns.plugin];
847 
848  manager.set_status (pi->type, pi->unique_id, status);
849 
851 
853  }
854  in_row_change = false;
855 }
856 
857 void
859 {
860  show_all();
861  run ();
862 }
863 
864 void
866 {
867  interested_object = &obj;
868 }
void added_list_selection_changed()
std::string category
Definition: plugin.h:60
bool operator()(PluginInfoPtr a, PluginInfoPtr b) const
Gtk::TreeModelColumn< bool > hidden
ARDOUR::PluginManager & manager
Gtk::TreeModelColumn< std::string > audio_outs
AddedColumns acols
void filter_mode_changed()
Gtk::Menu * plugin_menu()
LIBARDOUR_API PBD::PropertyDescriptor< bool > hidden
Definition: route_group.h:50
void vst_refiller(const std::string &)
void refiller(const ARDOUR::PluginInfoList &plugs, const ::std::string &filterstr, const char *type)
Gtk::ComboBoxText filter_mode
bool show_this_plugin(const ARDOUR::PluginInfoPtr &, const std::string &)
bool operator()(PluginInfoPtr a, PluginInfoPtr b) const
Definition: ardour_ui.h:130
void added_row_clicked(GdkEventButton *event)
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
std::string path
Definition: plugin.h:62
void favorite_changed(const std::string &path)
ARDOUR::PluginInfoList & windows_vst_plugin_info()
void hidden_changed(const std::string &path)
void set_status(ARDOUR::PluginType type, std::string unique_id, PluginStatusType status)
Definition: Beats.hpp:239
void set_interested_object(PluginInterestedObject &)
LIBGTKMM2EXT_API void set_popdown_strings(Gtk::ComboBoxText &, const std::vector< std::string > &)
Gtk::Button * btn_remove
Gtk::Button * btn_add
void filter_entry_changed()
void ladspa_refiller(const std::string &)
ARDOUR::PluginInfoList & lv2_plugin_info()
Gtk::Entry filter_entry
bool operator()(PluginInfoPtr a, PluginInfoPtr b) const
#define invalidator(x)
Definition: gui_thread.h:40
Gtk::TreeModelColumn< std::string > midi_ins
std::vector< ARDOUR::PluginPtr > SelectedPlugins
#define _(Text)
Definition: i18n.h:11
PluginSelector(ARDOUR::PluginManager &)
void plugin_chosen_from_menu(const ARDOUR::PluginInfoPtr &)
Gtk::Menu * create_by_category_menu(ARDOUR::PluginInfoList &)
boost::shared_ptr< Plugin > PluginPtr
Definition: plugin.h:50
#define X_(Text)
Definition: i18n.h:13
virtual PluginPtr load(Session &session)=0
PBD::Signal0< void > PluginListChanged
void lv2_refiller(const std::string &)
void lxvst_refiller(const std::string &)
ARDOUR::PluginInfoList & ladspa_plugin_info()
PBD::ScopedConnectionList plugin_list_changed_connection
Gtk::TreeModelColumn< std::string > midi_outs
Definition: amp.h:29
void display_selection_changed()
#define gui_context()
Definition: gui_thread.h:36
LIBARDOUR_API int cmp_nocase_utf8(const std::string &s1, const std::string &s2)
PluginInterestedObject * interested_object
Gtk::ScrolledWindow ascroller
virtual bool use_plugins(const SelectedPlugins &)=0
#define I18N(Array)
Definition: i18n.h:14
void filter_button_clicked()
LIBPBD_API Transmitter info
LIBARDOUR_API uint64_t LV2
Definition: debug.cc:51
ARDOUR::PluginPtr load_plugin(ARDOUR::PluginInfoPtr)
void row_activated(Gtk::TreeModel::Path path, Gtk::TreeViewColumn *col)
Gtk::TreeView plugin_display
void set_tip(Gtk::Widget &w, const gchar *tip)
Gtk::TreeModelColumn< std::string > category
static const char * _filter_mode_strings[]
Gtk::TreeModelColumn< std::string > audio_ins
std::string unique_id
Definition: plugin.h:67
ARDOUR::PluginInfoList & au_plugin_info()
void au_refiller(const std::string &)
Gtk::TreeModelColumn< std::string > creator
ARDOUR::PluginInfoList & lxvst_plugin_info()
Gtk::TreeModelColumn< std::string > name
const char * name
Gtk::Menu * _plugin_menu
Gtk::Button filter_button
Gtk::TreeModelColumn< bool > favorite
Gtk::Menu * create_favs_menu(ARDOUR::PluginInfoList &)
Definition: editor.h:86
Glib::RefPtr< Gtk::ListStore > plugin_model
Glib::RefPtr< Gtk::ListStore > amodel
Definition: debug.h:30
std::string creator
Definition: plugin.h:61
Gtk::ScrolledWindow scroller
Gtk::TreeModelColumn< std::string > type_name
std::list< PluginInfoPtr > PluginInfoList
Definition: plugin.h:90
Gtk::Menu * create_by_creator_menu(ARDOUR::PluginInfoList &)
void setup_filter_string(std::string &)
PluginColumns plugin_columns
Gtk::TreeModelColumn< ARDOUR::PluginInfoPtr > plugin
Gtk::TreeView added_list
Gtk::TreeModelColumn< ARDOUR::PluginInfoPtr > plugin
ARDOUR::Session * _session
ARDOUR::PluginType type
Definition: plugin.h:65
std::string name
Definition: plugin.h:59
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
Gtk::TreeModelColumn< std::string > text
#define N_(Text)
Definition: i18n.h:12
PluginStatusType get_status(const PluginInfoPtr &)
void refresh(bool cache_only=false)