Various optimisations to speed up rec-enable.
[ardour.git] / gtk2_ardour / processor_box.cc
1 /*
2     Copyright (C) 2000-2004 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 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <cmath>
25 #include <iostream>
26 #include <set>
27
28 #include <sigc++/bind.h>
29
30 #include "pbd/convert.h"
31
32 #include <glibmm/miscutils.h>
33
34 #include <gtkmm/messagedialog.h>
35
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/utils.h>
38 #include <gtkmm2ext/choice.h>
39 #include <gtkmm2ext/utils.h>
40 #include <gtkmm2ext/stop_signal.h>
41 #include <gtkmm2ext/doi.h>
42
43 #include "ardour/amp.h"
44 #include "ardour/ardour.h"
45 #include "ardour/audio_diskstream.h"
46 #include "ardour/audio_track.h"
47 #include "ardour/audioengine.h"
48 #include "ardour/internal_send.h"
49 #include "ardour/ladspa_plugin.h"
50 #include "ardour/meter.h"
51 #include "ardour/plugin_insert.h"
52 #include "ardour/port_insert.h"
53 #include "ardour/profile.h"
54 #include "ardour/return.h"
55 #include "ardour/route.h"
56 #include "ardour/send.h"
57 #include "ardour/session.h"
58
59 #include "actions.h"
60 #include "ardour_dialog.h"
61 #include "ardour_ui.h"
62 #include "gui_thread.h"
63 #include "io_selector.h"
64 #include "keyboard.h"
65 #include "mixer_ui.h"
66 #include "mixer_strip.h"
67 #include "plugin_selector.h"
68 #include "plugin_ui.h"
69 #include "processor_box.h"
70 #include "public_editor.h"
71 #include "return_ui.h"
72 #include "route_processor_selection.h"
73 #include "send_ui.h"
74 #include "utils.h"
75
76 #include "i18n.h"
77
78 #ifdef HAVE_AUDIOUNITS
79 class AUPluginUI;
80 #endif
81
82 using namespace std;
83 using namespace sigc;
84 using namespace ARDOUR;
85 using namespace PBD;
86 using namespace Gtk;
87 using namespace Glib;
88 using namespace Gtkmm2ext;
89
90 ProcessorBox* ProcessorBox::_current_processor_box = 0;
91 RefPtr<Action> ProcessorBox::paste_action;
92 Glib::RefPtr<Gdk::Pixbuf> SendProcessorEntry::_slider;
93
94 ProcessorEntry::ProcessorEntry (boost::shared_ptr<Processor> p, Width w)
95         : _processor (p)
96         , _width (w)
97 {
98         _hbox.pack_start (_active, false, false);
99         _event_box.add (_name);
100         _hbox.pack_start (_event_box, true, true);
101         _vbox.pack_start (_hbox);
102
103         _name.set_alignment (0, 0.5);
104         _name.set_text (name ());
105         _name.set_padding (2, 2);
106         
107         _active.set_active (_processor->active ());
108         _active.signal_toggled().connect (mem_fun (*this, &ProcessorEntry::active_toggled));
109         
110         _processor->ActiveChanged.connect (mem_fun (*this, &ProcessorEntry::processor_active_changed));
111         _processor->NameChanged.connect (mem_fun (*this, &ProcessorEntry::processor_name_changed));
112 }
113
114 EventBox&
115 ProcessorEntry::action_widget ()
116 {
117         return _event_box;
118 }
119
120 Gtk::Widget&
121 ProcessorEntry::widget ()
122 {
123         return _vbox;
124 }
125
126 string
127 ProcessorEntry::drag_text () const
128 {
129         return name ();
130 }
131
132 boost::shared_ptr<Processor>
133 ProcessorEntry::processor () const
134 {
135         return _processor;
136 }
137
138 void
139 ProcessorEntry::set_width (Width w)
140 {
141         _width = w;
142 }
143
144 void
145 ProcessorEntry::active_toggled ()
146 {
147         if (_active.get_active ()) {
148                 if (!_processor->active ()) {
149                         _processor->activate ();
150                 }
151         } else {
152                 if (_processor->active ()) {
153                         _processor->deactivate ();
154                 }
155         }
156 }
157
158 void
159 ProcessorEntry::processor_active_changed ()
160 {
161         if (_active.get_active () != _processor->active ()) {
162                 _active.set_active (_processor->active ());
163         }
164 }
165
166 void
167 ProcessorEntry::processor_name_changed ()
168 {
169         _name.set_text (name ());
170 }
171
172 string
173 ProcessorEntry::name () const
174 {
175         boost::shared_ptr<Send> send;
176         string name_display;
177         
178         if (!_processor->active()) {
179                 name_display = " (";
180         }
181         
182         if ((send = boost::dynamic_pointer_cast<Send> (_processor)) != 0 &&
183             !boost::dynamic_pointer_cast<InternalSend>(_processor)) {
184                 
185                 name_display += '>';
186                 
187                 /* grab the send name out of its overall name */
188                 
189                 string::size_type lbracket, rbracket;
190                 lbracket = send->name().find ('[');
191                 rbracket = send->name().find (']');
192                 
193                 switch (_width) {
194                 case Wide:
195                         name_display += send->name().substr (lbracket+1, lbracket-rbracket-1);
196                         break;
197                 case Narrow:
198                         name_display += PBD::short_version (send->name().substr (lbracket+1, lbracket-rbracket-1), 4);
199                         break;
200                 }
201                 
202         } else {
203                 
204                 switch (_width) {
205                 case Wide:
206                         name_display += _processor->display_name();
207                         break;
208                 case Narrow:
209                         name_display += PBD::short_version (_processor->display_name(), 5);
210                         break;
211                 }
212                 
213         }
214         
215         if (!_processor->active()) {
216                 name_display += ')';
217         }
218         
219         return name_display;
220 }
221
222 SendProcessorEntry::SendProcessorEntry (boost::shared_ptr<Send> s, Width w)
223         : ProcessorEntry (s, w),
224           _send (s),
225           _adjustment (0, 0, 1, 0.01, 0.1),
226           _fader (_slider, &_adjustment, false),
227           _ignore_gain_change (false)
228 {
229         _fader.set_controllable (_send->amp()->gain_control ());
230         _vbox.pack_start (_fader);
231
232         _adjustment.signal_value_changed().connect (mem_fun (*this, &SendProcessorEntry::gain_adjusted));
233         _send->amp()->gain_control()->Changed.connect (mem_fun (*this, &SendProcessorEntry::show_gain));
234         show_gain ();
235 }
236
237 void
238 SendProcessorEntry::setup_slider_pix ()
239 {
240         _slider = ::get_icon ("fader_belt_h_thin");
241         assert (_slider);
242 }
243
244 void
245 SendProcessorEntry::show_gain ()
246 {
247         ENSURE_GUI_THREAD (mem_fun (*this, &SendProcessorEntry::show_gain));
248         
249         float const value = gain_to_slider_position (_send->amp()->gain ());
250
251         if (_adjustment.get_value() != value) {
252                 _ignore_gain_change = true;
253                 _adjustment.set_value (value);
254                 _ignore_gain_change = false;
255         }
256 }
257
258 void
259 SendProcessorEntry::gain_adjusted ()
260 {
261         if (_ignore_gain_change) {
262                 return;
263         }
264
265         _send->amp()->set_gain (slider_position_to_gain (_adjustment.get_value()), this);
266 }
267
268
269
270 ProcessorBox::ProcessorBox (ARDOUR::Session& sess, sigc::slot<PluginSelector*> get_plugin_selector,
271                         RouteRedirectSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
272         : _session(sess)
273         , _parent_strip (parent)
274         , _owner_is_mixer (owner_is_mixer)
275         , ab_direction (true)
276         , _get_plugin_selector (get_plugin_selector)
277         , _placement(PreFader)
278         , _rr_selection(rsel)
279 {
280         _width = Wide;
281         processor_menu = 0;
282         send_action_menu = 0;
283         no_processor_redisplay = false;
284
285         processor_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
286         processor_scroller.add (processor_display);
287         pack_start (processor_scroller, true, true);
288
289         processor_display.set_flags (CAN_FOCUS);
290         processor_display.set_name ("ProcessorSelector");
291         processor_display.set_size_request (48, -1);
292         processor_display.set_data ("processorbox", this);
293
294         processor_display.signal_enter_notify_event().connect (mem_fun(*this, &ProcessorBox::enter_notify), false);
295         processor_display.signal_leave_notify_event().connect (mem_fun(*this, &ProcessorBox::leave_notify), false);
296
297         processor_display.signal_key_press_event().connect (mem_fun(*this, &ProcessorBox::processor_key_press_event));
298         processor_display.signal_key_release_event().connect (mem_fun(*this, &ProcessorBox::processor_key_release_event));
299
300         processor_display.ButtonPress.connect (mem_fun (*this, &ProcessorBox::processor_button_press_event));
301         processor_display.ButtonRelease.connect (mem_fun (*this, &ProcessorBox::processor_button_release_event));
302
303         processor_display.Reordered.connect (mem_fun (*this, &ProcessorBox::reordered));
304         processor_display.DropFromAnotherBox.connect (mem_fun (*this, &ProcessorBox::object_drop));
305         processor_display.SelectionChanged.connect (mem_fun (*this, &ProcessorBox::selection_changed));
306 }
307
308 ProcessorBox::~ProcessorBox ()
309 {
310 }
311
312 void
313 ProcessorBox::set_route (boost::shared_ptr<Route> r)
314 {
315         connections.clear ();
316
317         /* new route: any existing block on processor redisplay must be meaningless */
318         no_processor_redisplay = false;
319         _route = r;
320
321         connections.push_back (_route->processors_changed.connect (mem_fun (*this, &ProcessorBox::route_processors_changed)));
322         connections.push_back (_route->GoingAway.connect (
323                         mem_fun (*this, &ProcessorBox::route_going_away)));
324         connections.push_back (_route->NameChanged.connect (
325                         mem_fun(*this, &ProcessorBox::route_name_changed)));
326
327         redisplay_processors ();
328 }
329
330 void
331 ProcessorBox::route_going_away ()
332 {
333         /* don't keep updating display as processors are deleted */
334         no_processor_redisplay = true;
335 }
336
337 void
338 ProcessorBox::object_drop(DnDVBox<ProcessorEntry>* source, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
339 {
340         boost::shared_ptr<Processor> p;
341         if (position) {
342                 p = position->processor ();
343         }
344
345         list<ProcessorEntry*> children = source->selection ();
346         list<boost::shared_ptr<Processor> > procs;
347         for (list<ProcessorEntry*>::const_iterator i = children.begin(); i != children.end(); ++i) {
348                 procs.push_back ((*i)->processor ());
349         }
350
351         for (list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin(); i != procs.end(); ++i) {
352                 XMLNode& state = (*i)->get_state ();
353                 XMLNodeList nlist;
354                 nlist.push_back (&state);
355                 paste_processor_state (nlist, p);
356                 delete &state;
357         }
358
359         /* since the dndvbox doesn't take care of this properly, we have to delete the originals
360            ourselves.
361         */
362
363         if ((context->get_suggested_action() == Gdk::ACTION_MOVE) && source) {
364                 ProcessorBox* other = reinterpret_cast<ProcessorBox*> (source->get_data ("processorbox"));
365                 if (other) {
366                         cerr << "source was another processor box, delete the selected items\n";
367                         other->delete_dragged_processors (procs);
368                 }
369         }
370 }
371
372 void
373 ProcessorBox::update()
374 {
375         redisplay_processors ();
376 }
377
378 void
379 ProcessorBox::set_width (Width w)
380 {
381         if (_width == w) {
382                 return;
383         }
384         
385         _width = w;
386
387         list<ProcessorEntry*> children = processor_display.children ();
388         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
389                 (*i)->set_width (w);
390         }
391
392         redisplay_processors ();
393 }
394
395 void
396 ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
397 {
398         boost::shared_ptr<Send> send;
399         boost::shared_ptr<Return> retrn;
400         boost::shared_ptr<PortInsert> port_insert;
401
402         if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
403                 PortInsertUI *io_selector = reinterpret_cast<PortInsertUI *> (port_insert->get_gui());
404                 port_insert->set_gui (0);
405                 delete io_selector;
406         } else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
407                 SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
408                 send->set_gui (0);
409                 delete sui;
410         } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
411                 ReturnUIWindow *rui = reinterpret_cast<ReturnUIWindow*> (retrn->get_gui());
412                 retrn->set_gui (0);
413                 delete rui;
414         }
415 }
416
417 void
418 ProcessorBox::build_send_action_menu ()
419 {
420         using namespace Menu_Helpers;
421
422         send_action_menu = new Menu;
423         send_action_menu->set_name ("ArdourContextMenu");
424         MenuList& items = send_action_menu->items();
425
426         items.push_back (MenuElem (_("New send"), mem_fun(*this, &ProcessorBox::new_send)));
427         items.push_back (MenuElem (_("Show send controls"), mem_fun(*this, &ProcessorBox::show_send_controls)));
428 }
429
430 Gtk::Menu*
431 ProcessorBox::build_possible_aux_menu ()
432 {
433         boost::shared_ptr<RouteList> rl = _session.get_routes_with_internal_returns();
434
435         if (rl->empty()) {
436                 return 0;
437         }
438
439         using namespace Menu_Helpers;
440         Menu* menu = manage (new Menu);
441         MenuList& items = menu->items();
442
443         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
444                 if (!_route->internal_send_for (*r) && *r != _route) {
445                         items.push_back (MenuElem ((*r)->name(), bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux), boost::weak_ptr<Route>(*r))));
446                 }
447         }
448
449         return menu;
450 }
451
452 void
453 ProcessorBox::show_send_controls ()
454 {
455 }
456
457 void
458 ProcessorBox::new_send ()
459 {
460 }
461
462 void
463 ProcessorBox::show_processor_menu (gint arg)
464 {
465         if (processor_menu == 0) {
466                 processor_menu = build_processor_menu ();
467         }
468
469         Gtk::MenuItem* plugin_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/processormenu/newplugin"));
470
471         if (plugin_menu_item) {
472                 plugin_menu_item->set_submenu (*_get_plugin_selector()->plugin_menu());
473         }
474
475         Gtk::MenuItem* aux_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/processormenu/newaux"));
476
477         if (aux_menu_item) {
478                 Menu* m = build_possible_aux_menu();
479                 if (m && !m->items().empty()) {
480                         aux_menu_item->set_submenu (*m);
481                         aux_menu_item->set_sensitive (true);
482                 } else {
483                         /* stupid gtkmm: we need to pass a null reference here */
484                         gtk_menu_item_set_submenu (aux_menu_item->gobj(), 0);
485                         aux_menu_item->set_sensitive (false);
486                 }
487         }
488
489         paste_action->set_sensitive (!_rr_selection.processors.empty());
490
491         processor_menu->popup (1, arg);
492 }
493
494 bool
495 ProcessorBox::enter_notify (GdkEventCrossing*)
496 {
497         _current_processor_box = this;
498         Keyboard::magic_widget_grab_focus ();
499         processor_display.grab_focus ();
500
501         return false;
502 }
503
504 bool
505 ProcessorBox::leave_notify (GdkEventCrossing* ev)
506 {
507         switch (ev->detail) {
508         case GDK_NOTIFY_INFERIOR:
509                 break;
510         default:
511                 Keyboard::magic_widget_drop_focus ();
512         }
513
514         return false;
515 }
516
517 bool
518 ProcessorBox::processor_key_press_event (GdkEventKey *)
519 {
520         /* do real stuff on key release */
521         return false;
522 }
523
524 bool
525 ProcessorBox::processor_key_release_event (GdkEventKey *ev)
526 {
527         bool ret = false;
528         ProcSelection targets;
529
530         get_selected_processors (targets);
531
532         if (targets.empty()) {
533
534                 int x, y;
535                 processor_display.get_pointer (x, y);
536
537                 pair<ProcessorEntry *, int> const pointer = processor_display.get_child_at_position (x, y);
538
539                 if (pointer.first) {
540                         targets.push_back (pointer.first->processor ());
541                 }
542         }
543
544
545         switch (ev->keyval) {
546         case GDK_a:
547                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
548                         processor_display.select_all ();
549                         ret = true;
550                 } 
551                 break;
552
553         case GDK_c:
554                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
555                         copy_processors (targets);
556                         ret = true;
557                 }
558                 break;
559
560         case GDK_x:
561                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
562                         cut_processors (targets);
563                         ret = true;
564                 }
565                 break;
566
567         case GDK_v:
568                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
569                         if (targets.empty()) {
570                                 paste_processors ();
571                         } else {
572                                 paste_processors (targets.front());
573                         }
574                         ret = true;
575                 }
576                 break;
577
578         case GDK_Up:
579                 break;
580
581         case GDK_Down:
582                 break;
583
584         case GDK_Delete:
585         case GDK_BackSpace:
586                 delete_processors (targets);
587                 ret = true;
588                 break;
589
590         case GDK_Return:
591                 for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
592                         if ((*i)->active()) {
593                                 (*i)->deactivate ();
594                         } else {
595                                 (*i)->activate ();
596                         }
597                 }
598                 ret = true;
599                 break;
600
601         case GDK_slash:
602                 ab_plugins ();
603                 ret = true;
604                 break;
605
606         default:
607                 break;
608         }
609
610         return ret;
611 }
612
613 bool
614 ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* child)
615 {
616         boost::shared_ptr<Processor> processor;
617         if (child) {
618                 processor = child->processor ();
619         }
620         
621         int ret = false;
622         bool selected = processor_display.selected (child);
623
624         if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
625
626                 if (_session.engine().connected()) {
627                         /* XXX giving an error message here is hard, because we may be in the midst of a button press */
628                         edit_processor (processor);
629                 }
630                 ret = true;
631
632         } else if (processor && ev->button == 1 && selected) {
633
634                 // this is purely informational but necessary for route params UI
635                 ProcessorSelected (processor); // emit
636
637         } else if (!processor && ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
638
639                 choose_plugin ();
640                 _get_plugin_selector()->show_manager ();
641         }
642
643         return ret;
644 }
645
646 bool
647 ProcessorBox::processor_button_release_event (GdkEventButton *ev, ProcessorEntry* child)
648 {
649         boost::shared_ptr<Processor> processor;
650         if (child) {
651                 processor = child->processor ();
652         }
653         
654         int ret = false;
655
656         if (processor && Keyboard::is_delete_event (ev)) {
657
658                 Glib::signal_idle().connect (bind (
659                                 mem_fun(*this, &ProcessorBox::idle_delete_processor),
660                                 boost::weak_ptr<Processor>(processor)));
661                 ret = true;
662
663         } else if (Keyboard::is_context_menu_event (ev)) {
664
665                 /* figure out if we are above or below the fader/amp processor,
666                    and set the next insert position appropriately.
667                 */
668
669                 if (processor) {
670                         if (_route->processor_is_prefader (processor)) {
671                                 _placement = PreFader;
672                         } else {
673                                 _placement = PostFader;
674                         }
675                 } else {
676                         _placement = PostFader;
677                 }
678
679                 show_processor_menu (ev->time);
680                 ret = true;
681
682         } else if (processor && Keyboard::is_button2_event (ev)
683 #ifndef GTKOSX
684                    && (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))
685 #endif
686                 ) {
687
688                 /* button2-click with no/appropriate modifiers */
689
690                 if (processor->active()) {
691                         processor->deactivate ();
692                 } else {
693                         processor->activate ();
694                 }
695                 ret = true;
696
697         }
698
699         return false;
700 }
701
702 Menu *
703 ProcessorBox::build_processor_menu ()
704 {
705         processor_menu = dynamic_cast<Gtk::Menu*>(ActionManager::get_widget("/processormenu") );
706         processor_menu->set_name ("ArdourContextMenu");
707
708         show_all_children();
709
710         return processor_menu;
711 }
712
713 void
714 ProcessorBox::selection_changed ()
715 {
716         bool sensitive = (processor_display.selection().empty()) ? false : true;
717         ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions, sensitive);
718 }
719
720 void
721 ProcessorBox::select_all_processors ()
722 {
723         processor_display.select_all ();
724 }
725
726 void
727 ProcessorBox::deselect_all_processors ()
728 {
729         processor_display.select_none ();
730 }
731
732 void
733 ProcessorBox::choose_plugin ()
734 {
735         _get_plugin_selector()->set_interested_object (*this);
736 }
737
738 void
739 ProcessorBox::use_plugins (const SelectedPlugins& plugins)
740 {
741         for (SelectedPlugins::const_iterator p = plugins.begin(); p != plugins.end(); ++p) {
742
743                 boost::shared_ptr<Processor> processor (new PluginInsert (_session, *p));
744
745                 Route::ProcessorStreams err_streams;
746
747                 if (Config->get_new_plugins_active()) {
748                         processor->activate ();
749                 }
750
751                 if (_route->add_processor (processor, _placement, &err_streams)) {
752                         weird_plugin_dialog (**p, err_streams);
753                         // XXX SHAREDPTR delete plugin here .. do we even need to care?
754                 } else {
755
756                         if (Profile->get_sae()) {
757                                 processor->activate ();
758                         }
759                 }
760         }
761 }
762
763 void
764 ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams)
765 {
766         ArdourDialog dialog (_("ardour: weird plugin dialog"));
767         Label label;
768
769         string text = string_compose(_("You attempted to add the plugin \"%1\" at index %2.\n"),
770                         p.name(), streams.index);
771
772         bool has_midi  = streams.count.n_midi() > 0 || p.get_info()->n_inputs.n_midi() > 0;
773         bool has_audio = streams.count.n_audio() > 0 || p.get_info()->n_inputs.n_audio() > 0;
774
775         text += _("\nThis plugin has:\n");
776         if (has_midi) {
777                 text += string_compose("\t%1 ", p.get_info()->n_inputs.n_midi()) + _("MIDI input(s)\n");
778         }
779         if (has_audio) {
780                 text += string_compose("\t%1 ", p.get_info()->n_inputs.n_audio()) + _("audio input(s)\n");
781         }
782
783         text += _("\nBut at the insertion point, there are:\n");
784         if (has_midi) {
785                 text += string_compose("\t%1 ", streams.count.n_midi()) + _("MIDI channel(s)\n");
786         }
787         if (has_audio) {
788                 text += string_compose("\t%1 ", streams.count.n_audio()) + _("audio channel(s)\n");
789         }
790
791         text += _("\nArdour is unable to insert this plugin here.\n");
792         label.set_text(text);
793
794         dialog.get_vbox()->pack_start (label);
795         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
796
797         dialog.set_name (X_("PluginIODialog"));
798         dialog.set_position (Gtk::WIN_POS_MOUSE);
799         dialog.set_modal (true);
800         dialog.show_all ();
801
802         dialog.run ();
803 }
804
805 void
806 ProcessorBox::choose_insert ()
807 {
808         boost::shared_ptr<Processor> processor (new PortInsert (_session, _route->mute_master()));
809         _route->add_processor (processor, _placement);
810 }
811
812 void
813 ProcessorBox::choose_send ()
814 {
815         boost::shared_ptr<Send> send (new Send (_session, _route->mute_master()));
816
817         /* make an educated guess at the initial number of outputs for the send */
818         ChanCount outs = (_session.master_out())
819                         ? _session.master_out()->n_outputs()
820                         : _route->n_outputs();
821
822         /* XXX need processor lock on route */
823         try {
824                 send->output()->ensure_io (outs, false, this);
825         } catch (AudioEngine::PortRegistrationFailure& err) {
826                 error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
827                 return;
828         }
829
830         /* let the user adjust the IO setup before creation.
831
832            Note: this dialog is NOT modal - we just leave it to run and it will
833            return when its Finished signal is emitted - typically when the window
834            is closed.
835          */
836
837         IOSelectorWindow *ios = new IOSelectorWindow (_session, send->output(), true);
838         ios->show_all ();
839
840         /* keep a reference to the send so it doesn't get deleted while
841            the IOSelectorWindow is doing its stuff
842         */
843         _processor_being_created = send;
844
845         ios->selector().Finished.connect (bind (
846                         mem_fun(*this, &ProcessorBox::send_io_finished),
847                         boost::weak_ptr<Processor>(send), ios));
848
849 }
850
851 void
852 ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
853 {
854         boost::shared_ptr<Processor> processor (weak_processor.lock());
855
856         /* drop our temporary reference to the new send */
857         _processor_being_created.reset ();
858
859         if (!processor) {
860                 return;
861         }
862
863         switch (r) {
864         case IOSelector::Cancelled:
865                 // processor will go away when all shared_ptrs to it vanish
866                 break;
867
868         case IOSelector::Accepted:
869                 _route->add_processor (processor, _placement);
870                 if (Profile->get_sae()) {
871                         processor->activate ();
872                 }
873                 break;
874         }
875
876         delete_when_idle (ios);
877 }
878
879 void
880 ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
881 {
882         boost::shared_ptr<Processor> processor (weak_processor.lock());
883
884         /* drop our temporary reference to the new return */
885         _processor_being_created.reset ();
886
887         if (!processor) {
888                 return;
889         }
890
891         switch (r) {
892         case IOSelector::Cancelled:
893                 // processor will go away when all shared_ptrs to it vanish
894                 break;
895
896         case IOSelector::Accepted:
897                 _route->add_processor (processor, _placement);
898                 if (Profile->get_sae()) {
899                         processor->activate ();
900                 }
901                 break;
902         }
903
904         delete_when_idle (ios);
905 }
906
907 void
908 ProcessorBox::choose_aux (boost::weak_ptr<Route> wr)
909 {
910         if (!_route) {
911                 return;
912         }
913
914         boost::shared_ptr<Route> target = wr.lock();
915
916         if (!target) {
917                 return;
918         }
919
920         boost::shared_ptr<RouteList> rlist (new RouteList);
921         rlist->push_back (_route);
922
923         _session.add_internal_sends (target, PreFader, rlist);
924 }
925
926 void
927 ProcessorBox::route_processors_changed (RouteProcessorChange c)
928 {
929         if (c.type == RouteProcessorChange::MeterPointChange && c.meter_visibly_changed == false) {
930                 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
931                 return;
932         }
933
934         redisplay_processors ();
935 }
936
937 void
938 ProcessorBox::redisplay_processors ()
939 {
940         ENSURE_GUI_THREAD (mem_fun(*this, &ProcessorBox::redisplay_processors));
941
942         if (no_processor_redisplay) {
943                 return;
944         }
945
946         processor_display.clear ();
947
948         _route->foreach_processor (mem_fun (*this, &ProcessorBox::add_processor_to_display));
949
950         build_processor_tooltip (processor_eventbox, _("Inserts, sends & plugins:"));
951 }
952
953 void
954 ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
955 {
956         boost::shared_ptr<Processor> processor (p.lock ());
957
958         if (!processor || !processor->display_to_user()) {
959                 return;
960         }
961
962         boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
963         if (send) {
964                 processor_display.add_child (new SendProcessorEntry (send, _width));
965         } else {
966                 processor_display.add_child (new ProcessorEntry (processor, _width));
967         }
968 }
969
970
971 void
972 ProcessorBox::build_processor_tooltip (EventBox& box, string start)
973 {
974         string tip(start);
975
976         list<ProcessorEntry*> children = processor_display.children ();
977         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
978                 tip += '\n';
979                 tip += (*i)->processor()->name();
980         }
981         
982         ARDOUR_UI::instance()->tooltips().set_tip (box, tip);
983 }
984
985 void
986 ProcessorBox::reordered ()
987 {
988         compute_processor_sort_keys ();
989 }
990
991 void
992 ProcessorBox::compute_processor_sort_keys ()
993 {
994         list<ProcessorEntry*> children = processor_display.children ();
995         Route::ProcessorList our_processors;
996
997         for (list<ProcessorEntry*>::iterator iter = children.begin(); iter != children.end(); ++iter) {
998                 our_processors.push_back ((*iter)->processor ());
999         }
1000
1001         if (_route->reorder_processors (our_processors)) {
1002
1003                 /* reorder failed, so redisplay */
1004
1005                 redisplay_processors ();
1006
1007                 /* now tell them about the problem */
1008
1009                 ArdourDialog dialog (_("ardour: weird plugin dialog"));
1010                 Label label;
1011
1012                 label.set_text (_("\
1013 You cannot reorder this set of processors\n\
1014 in that way because the inputs and\n\
1015 outputs do not work correctly."));
1016
1017                 dialog.get_vbox()->pack_start (label);
1018                 dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
1019
1020                 dialog.set_name (X_("PluginIODialog"));
1021                 dialog.set_position (Gtk::WIN_POS_MOUSE);
1022                 dialog.set_modal (true);
1023                 dialog.show_all ();
1024
1025                 dialog.run ();
1026         }
1027 }
1028
1029 void
1030 ProcessorBox::rename_processors ()
1031 {
1032         ProcSelection to_be_renamed;
1033
1034         get_selected_processors (to_be_renamed);
1035
1036         if (to_be_renamed.empty()) {
1037                 return;
1038         }
1039
1040         for (ProcSelection::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
1041                 rename_processor (*i);
1042         }
1043 }
1044
1045 void
1046 ProcessorBox::cut_processors ()
1047 {
1048         ProcSelection to_be_removed;
1049
1050         get_selected_processors (to_be_removed);
1051 }
1052
1053 void
1054 ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
1055 {
1056         if (to_be_removed.empty()) {
1057                 return;
1058         }
1059
1060         XMLNode* node = new XMLNode (X_("cut"));
1061         Route::ProcessorList to_cut;
1062
1063         no_processor_redisplay = true;
1064         for (ProcSelection::const_iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
1065                 // Cut only plugins, sends and returns
1066                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1067                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1068                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1069
1070                         void* gui = (*i)->get_gui ();
1071
1072                         if (gui) {
1073                                 static_cast<Gtk::Widget*>(gui)->hide ();
1074                         }
1075
1076                         XMLNode& child ((*i)->get_state());
1077                         node->add_child_nocopy (child);
1078                         to_cut.push_back (*i);
1079                 }
1080         }
1081
1082         if (_route->remove_processors (to_cut) != 0) {
1083                 delete node;
1084                 no_processor_redisplay = false;
1085                 return;
1086         }
1087
1088         _rr_selection.set (node);
1089
1090         no_processor_redisplay = false;
1091         redisplay_processors ();
1092 }
1093
1094 void
1095 ProcessorBox::copy_processors ()
1096 {
1097         ProcSelection to_be_copied;
1098         get_selected_processors (to_be_copied);
1099         copy_processors (to_be_copied);
1100 }
1101
1102 void
1103 ProcessorBox::copy_processors (const ProcSelection& to_be_copied)
1104 {
1105         if (to_be_copied.empty()) {
1106                 return;
1107         }
1108
1109         XMLNode* node = new XMLNode (X_("copy"));
1110
1111         for (ProcSelection::const_iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
1112                 // Copy only plugins, sends, returns
1113                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1114                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1115                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1116                         node->add_child_nocopy ((*i)->get_state());
1117                 }
1118         }
1119
1120         _rr_selection.set (node);
1121 }
1122
1123 void
1124 ProcessorBox::delete_processors ()
1125 {
1126         ProcSelection to_be_deleted;
1127         get_selected_processors (to_be_deleted);
1128         delete_processors (to_be_deleted);
1129 }
1130
1131 void
1132 ProcessorBox::delete_processors (const ProcSelection& targets)
1133 {
1134         if (targets.empty()) {
1135                 return;
1136         }
1137
1138         no_processor_redisplay = true;
1139
1140         for (ProcSelection::const_iterator i = targets.begin(); i != targets.end(); ++i) {
1141
1142                 void* gui = (*i)->get_gui ();
1143
1144                 if (gui) {
1145                         static_cast<Gtk::Widget*>(gui)->hide ();
1146                 }
1147
1148                 _route->remove_processor(*i);
1149         }
1150
1151         no_processor_redisplay = false;
1152         redisplay_processors ();
1153 }
1154
1155 void
1156 ProcessorBox::delete_dragged_processors (const list<boost::shared_ptr<Processor> >& procs)
1157 {
1158         list<boost::shared_ptr<Processor> >::const_iterator x;
1159
1160         no_processor_redisplay = true;
1161         for (x = procs.begin(); x != procs.end(); ++x) {
1162
1163                 void* gui = (*x)->get_gui ();
1164
1165                 if (gui) {
1166                         static_cast<Gtk::Widget*>(gui)->hide ();
1167                 }
1168
1169                 _route->remove_processor(*x);
1170         }
1171
1172         no_processor_redisplay = false;
1173         redisplay_processors ();
1174 }
1175
1176 gint
1177 ProcessorBox::idle_delete_processor (boost::weak_ptr<Processor> weak_processor)
1178 {
1179         boost::shared_ptr<Processor> processor (weak_processor.lock());
1180
1181         if (!processor) {
1182                 return false;
1183         }
1184
1185         /* NOT copied to _mixer.selection() */
1186
1187         no_processor_redisplay = true;
1188         _route->remove_processor (processor);
1189         no_processor_redisplay = false;
1190         redisplay_processors ();
1191
1192         return false;
1193 }
1194
1195 void
1196 ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
1197 {
1198         ArdourPrompter name_prompter (true);
1199         string result;
1200         name_prompter.set_title (_("Rename Processor"));
1201         name_prompter.set_prompt (_("New name:"));
1202         name_prompter.set_initial_text (processor->name());
1203         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1204         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1205         name_prompter.show_all ();
1206
1207         switch (name_prompter.run ()) {
1208
1209         case Gtk::RESPONSE_ACCEPT:
1210                 name_prompter.get_result (result);
1211                 if (result.length()) {
1212                         if (_session.route_by_name (result)) {
1213                                 ARDOUR_UI::instance()->popup_error (_("A track already exists with that name."));
1214                                 return;
1215                         }
1216                         processor->set_name (result);
1217                 }
1218                 break;
1219         }
1220
1221         return;
1222 }
1223
1224 void
1225 ProcessorBox::paste_processors ()
1226 {
1227         if (_rr_selection.processors.empty()) {
1228                 return;
1229         }
1230
1231         paste_processor_state (_rr_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
1232 }
1233
1234 void
1235 ProcessorBox::paste_processors (boost::shared_ptr<Processor> before)
1236 {
1237
1238         if (_rr_selection.processors.empty()) {
1239                 return;
1240         }
1241
1242         paste_processor_state (_rr_selection.processors.get_node().children(), before);
1243 }
1244
1245 void
1246 ProcessorBox::paste_processor_state (const XMLNodeList& nlist, boost::shared_ptr<Processor> p)
1247 {
1248         XMLNodeConstIterator niter;
1249         list<boost::shared_ptr<Processor> > copies;
1250
1251         if (nlist.empty()) {
1252                 return;
1253         }
1254
1255         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1256
1257                 XMLProperty const * type = (*niter)->property ("type");
1258                 assert (type);
1259
1260                 boost::shared_ptr<Processor> p;
1261                 try {
1262                         if (type->value() == "meter" ||
1263                             type->value() == "main-outs" ||
1264                             type->value() == "amp" ||
1265                             type->value() == "intsend" || type->value() == "intreturn") {
1266                                 /* do not paste meter, main outs, amp or internal send/returns */
1267                                 continue;
1268
1269                         } else if (type->value() == "send") {
1270
1271                                 XMLNode n (**niter);
1272                                 Send::make_unique (n, _session);
1273                                 p.reset (new Send (_session, _route->mute_master(), n));
1274
1275                         } else if (type->value() == "return") {
1276
1277                                 XMLNode n (**niter);
1278                                 Return::make_unique (n, _session);
1279                                 p.reset (new Return (_session, **niter));
1280
1281                         } else {
1282                                 /* XXX its a bit limiting to assume that everything else
1283                                    is a plugin.
1284                                 */
1285                                 p.reset (new PluginInsert (_session, **niter));
1286                         }
1287
1288                         copies.push_back (p);
1289                 }
1290
1291                 catch (...) {
1292                         cerr << "plugin insert constructor failed\n";
1293                 }
1294         }
1295
1296         if (copies.empty()) {
1297                 return;
1298         }
1299
1300         if (_route->add_processors (copies, p)) {
1301
1302                 string msg = _(
1303                         "Copying the set of processors on the clipboard failed,\n\
1304 probably because the I/O configuration of the plugins\n\
1305 could not match the configuration of this track.");
1306                 MessageDialog am (msg);
1307                 am.run ();
1308         }
1309 }
1310
1311 void
1312 ProcessorBox::activate_processor (boost::shared_ptr<Processor> r)
1313 {
1314         r->activate ();
1315 }
1316
1317 void
1318 ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
1319 {
1320         r->deactivate ();
1321 }
1322
1323 void
1324 ProcessorBox::get_selected_processors (ProcSelection& processors)
1325 {
1326         list<ProcessorEntry*> selection = processor_display.selection ();
1327         for (list<ProcessorEntry*>::iterator i = selection.begin(); i != selection.end(); ++i) {
1328                 processors.push_back ((*i)->processor ());
1329         }
1330 }
1331
1332 void
1333 ProcessorBox::for_selected_processors (void (ProcessorBox::*method)(boost::shared_ptr<Processor>))
1334 {
1335         list<ProcessorEntry*> selection = processor_display.selection ();
1336         for (list<ProcessorEntry*>::iterator i = selection.begin(); i != selection.end(); ++i) {
1337                 (this->*method) ((*i)->processor ());
1338         }
1339 }
1340
1341 void
1342 ProcessorBox::all_processors_active (bool state)
1343 {
1344         _route->all_processors_active (_placement, state);
1345 }
1346
1347 void
1348 ProcessorBox::ab_plugins ()
1349 {
1350         _route->ab_plugins (ab_direction);
1351         ab_direction = !ab_direction;
1352 }
1353
1354
1355 void
1356 ProcessorBox::clear_processors ()
1357 {
1358         string prompt;
1359         vector<string> choices;
1360
1361         prompt = string_compose (_("Do you really want to remove all processors from %1?\n"
1362                                    "(this cannot be undone)"), _route->name());
1363
1364         choices.push_back (_("Cancel"));
1365         choices.push_back (_("Yes, remove them all"));
1366
1367         Gtkmm2ext::Choice prompter (prompt, choices);
1368
1369         if (prompter.run () == 1) {
1370                 _route->clear_processors (PreFader);
1371                 _route->clear_processors (PostFader);
1372         }
1373 }
1374
1375 void
1376 ProcessorBox::clear_processors (Placement p)
1377 {
1378         string prompt;
1379         vector<string> choices;
1380
1381         if (p == PreFader) {
1382                 prompt = string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1383                                            "(this cannot be undone)"), _route->name());
1384         } else {
1385                 prompt = string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1386                                            "(this cannot be undone)"), _route->name());
1387         }
1388
1389         choices.push_back (_("Cancel"));
1390         choices.push_back (_("Yes, remove them all"));
1391
1392         Gtkmm2ext::Choice prompter (prompt, choices);
1393
1394         if (prompter.run () == 1) {
1395                 _route->clear_processors (p);
1396         }
1397 }
1398
1399 void
1400 ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
1401 {
1402         boost::shared_ptr<Send> send;
1403         boost::shared_ptr<Return> retrn;
1404         boost::shared_ptr<PluginInsert> plugin_insert;
1405         boost::shared_ptr<PortInsert> port_insert;
1406         Window* gidget = 0;
1407
1408         if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
1409
1410                 if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) {
1411                         return;
1412                 }
1413         }
1414
1415         if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
1416
1417                 if (!_session.engine().connected()) {
1418                         return;
1419                 }
1420
1421 #ifdef OLD_SEND_EDITING
1422                 SendUIWindow *send_ui;
1423
1424                 if (send->get_gui() == 0) {
1425                         send_ui = new SendUIWindow (send, _session);
1426                         send_ui->set_title (send->name());
1427                         send->set_gui (send_ui);
1428
1429                 } else {
1430                         send_ui = reinterpret_cast<SendUIWindow *> (send->get_gui());
1431                 }
1432
1433                 gidget = send_ui;
1434 #else
1435                 if (_parent_strip) {
1436                         _parent_strip->show_send (send);
1437                 }
1438 #endif
1439
1440         } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
1441
1442                 if (!_session.engine().connected()) {
1443                         return;
1444                 }
1445
1446                 boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor);
1447
1448                 ReturnUIWindow *return_ui;
1449
1450                 if (retrn->get_gui() == 0) {
1451
1452                         return_ui = new ReturnUIWindow (retrn, _session);
1453                         return_ui->set_title (retrn->name ());
1454                         send->set_gui (return_ui);
1455
1456                 } else {
1457                         return_ui = reinterpret_cast<ReturnUIWindow *> (retrn->get_gui());
1458                 }
1459
1460                 gidget = return_ui;
1461
1462         } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
1463
1464                 PluginUIWindow *plugin_ui;
1465
1466                 /* these are both allowed to be null */
1467
1468                 Container* toplevel = get_toplevel();
1469                 Window* win = dynamic_cast<Gtk::Window*>(toplevel);
1470
1471                 if (plugin_insert->get_gui() == 0) {
1472
1473                         plugin_ui = new PluginUIWindow (win, plugin_insert);
1474                         plugin_ui->set_title (generate_processor_title (plugin_insert));
1475                         plugin_insert->set_gui (plugin_ui);
1476
1477                 } else {
1478                         plugin_ui = reinterpret_cast<PluginUIWindow *> (plugin_insert->get_gui());
1479                         plugin_ui->set_parent (win);
1480                 }
1481
1482                 gidget = plugin_ui;
1483
1484         } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
1485
1486                 if (!_session.engine().connected()) {
1487                         MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible"));
1488                         msg.run ();
1489                         return;
1490                 }
1491
1492                 PortInsertWindow *io_selector;
1493
1494                 if (port_insert->get_gui() == 0) {
1495                         io_selector = new PortInsertWindow (_session, port_insert);
1496                         port_insert->set_gui (io_selector);
1497
1498                 } else {
1499                         io_selector = reinterpret_cast<PortInsertWindow *> (port_insert->get_gui());
1500                 }
1501
1502                 gidget = io_selector;
1503         }
1504
1505         if (gidget) {
1506                 if (gidget->is_visible()) {
1507                         gidget->get_window()->raise ();
1508                 } else {
1509                         gidget->show_all ();
1510                         gidget->present ();
1511                 }
1512         }
1513 }
1514
1515 void
1516 ProcessorBox::register_actions ()
1517 {
1518         Glib::RefPtr<Gtk::ActionGroup> popup_act_grp = Gtk::ActionGroup::create(X_("processormenu"));
1519         Glib::RefPtr<Action> act;
1520
1521         /* new stuff */
1522         ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin"),
1523                         sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
1524
1525         act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"),
1526                         sigc::ptr_fun (ProcessorBox::rb_choose_insert));
1527         ActionManager::jack_sensitive_actions.push_back (act);
1528         act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."),
1529                         sigc::ptr_fun (ProcessorBox::rb_choose_send));
1530         ActionManager::jack_sensitive_actions.push_back (act);
1531
1532         ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ..."));
1533
1534         ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear (all)"),
1535                         sigc::ptr_fun (ProcessorBox::rb_clear));
1536         ActionManager::register_action (popup_act_grp, X_("clear_pre"), _("Clear (pre-fader)"),
1537                         sigc::ptr_fun (ProcessorBox::rb_clear_pre));
1538         ActionManager::register_action (popup_act_grp, X_("clear_post"), _("Clear (post-fader)"),
1539                         sigc::ptr_fun (ProcessorBox::rb_clear_post));
1540
1541         /* standard editing stuff */
1542         act = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"),
1543                         sigc::ptr_fun (ProcessorBox::rb_cut));
1544         ActionManager::plugin_selection_sensitive_actions.push_back(act);
1545         act = ActionManager::register_action (popup_act_grp, X_("copy"), _("Copy"),
1546                         sigc::ptr_fun (ProcessorBox::rb_copy));
1547         ActionManager::plugin_selection_sensitive_actions.push_back(act);
1548
1549         act = ActionManager::register_action (popup_act_grp, X_("delete"), _("Delete"),
1550                         sigc::ptr_fun (ProcessorBox::rb_delete));
1551         ActionManager::plugin_selection_sensitive_actions.push_back(act); // ??
1552
1553         paste_action = ActionManager::register_action (popup_act_grp, X_("paste"), _("Paste"),
1554                         sigc::ptr_fun (ProcessorBox::rb_paste));
1555         act = ActionManager::register_action (popup_act_grp, X_("rename"), _("Rename"),
1556                         sigc::ptr_fun (ProcessorBox::rb_rename));
1557         ActionManager::plugin_selection_sensitive_actions.push_back(act);
1558         ActionManager::register_action (popup_act_grp, X_("selectall"), _("Select All"),
1559                         sigc::ptr_fun (ProcessorBox::rb_select_all));
1560         ActionManager::register_action (popup_act_grp, X_("deselectall"), _("Deselect All"),
1561                         sigc::ptr_fun (ProcessorBox::rb_deselect_all));
1562
1563         /* activation etc. */
1564
1565         ActionManager::register_action (popup_act_grp, X_("activate_all"), _("Activate all"),
1566                                         sigc::ptr_fun (ProcessorBox::rb_activate_all));
1567         ActionManager::register_action (popup_act_grp, X_("deactivate_all"), _("Deactivate all"),
1568                                         sigc::ptr_fun (ProcessorBox::rb_deactivate_all));
1569         ActionManager::register_action (popup_act_grp, X_("ab_plugins"), _("A/B Plugins"),
1570                                         sigc::ptr_fun (ProcessorBox::rb_ab_plugins));
1571
1572         /* show editors */
1573         act = ActionManager::register_action (popup_act_grp, X_("edit"), _("Edit"),
1574                                               sigc::ptr_fun (ProcessorBox::rb_edit));
1575         ActionManager::plugin_selection_sensitive_actions.push_back(act);
1576
1577         ActionManager::add_action_group (popup_act_grp);
1578 }
1579
1580 void
1581 ProcessorBox::rb_ab_plugins ()
1582 {
1583         if (_current_processor_box == 0) {
1584                 return;
1585         }
1586
1587         _current_processor_box->ab_plugins ();
1588 }
1589
1590 void
1591 ProcessorBox::rb_choose_plugin ()
1592 {
1593         if (_current_processor_box == 0) {
1594                 return;
1595         }
1596         _current_processor_box->choose_plugin ();
1597 }
1598
1599 void
1600 ProcessorBox::rb_choose_insert ()
1601 {
1602         if (_current_processor_box == 0) {
1603                 return;
1604         }
1605         _current_processor_box->choose_insert ();
1606 }
1607
1608 void
1609 ProcessorBox::rb_choose_send ()
1610 {
1611         if (_current_processor_box == 0) {
1612                 return;
1613         }
1614         _current_processor_box->choose_send ();
1615 }
1616
1617 void
1618 ProcessorBox::rb_choose_aux (boost::weak_ptr<Route> wr)
1619 {
1620         if (_current_processor_box == 0) {
1621                 return;
1622         }
1623
1624         _current_processor_box->choose_aux (wr);
1625 }
1626
1627 void
1628 ProcessorBox::rb_clear ()
1629 {
1630         if (_current_processor_box == 0) {
1631                 return;
1632         }
1633
1634         _current_processor_box->clear_processors ();
1635 }
1636
1637
1638 void
1639 ProcessorBox::rb_clear_pre ()
1640 {
1641         if (_current_processor_box == 0) {
1642                 return;
1643         }
1644
1645         _current_processor_box->clear_processors (PreFader);
1646 }
1647
1648
1649 void
1650 ProcessorBox::rb_clear_post ()
1651 {
1652         if (_current_processor_box == 0) {
1653                 return;
1654         }
1655
1656         _current_processor_box->clear_processors (PostFader);
1657 }
1658
1659 void
1660 ProcessorBox::rb_cut ()
1661 {
1662         if (_current_processor_box == 0) {
1663                 return;
1664         }
1665
1666         _current_processor_box->cut_processors ();
1667 }
1668
1669 void
1670 ProcessorBox::rb_delete ()
1671 {
1672         if (_current_processor_box == 0) {
1673                 return;
1674         }
1675
1676         _current_processor_box->delete_processors ();
1677 }
1678
1679 void
1680 ProcessorBox::rb_copy ()
1681 {
1682         if (_current_processor_box == 0) {
1683                 return;
1684         }
1685         _current_processor_box->copy_processors ();
1686 }
1687
1688 void
1689 ProcessorBox::rb_paste ()
1690 {
1691         if (_current_processor_box == 0) {
1692                 return;
1693         }
1694
1695         _current_processor_box->paste_processors ();
1696 }
1697
1698 void
1699 ProcessorBox::rb_rename ()
1700 {
1701         if (_current_processor_box == 0) {
1702                 return;
1703         }
1704         _current_processor_box->rename_processors ();
1705 }
1706
1707 void
1708 ProcessorBox::rb_select_all ()
1709 {
1710         if (_current_processor_box == 0) {
1711                 return;
1712         }
1713
1714         _current_processor_box->select_all_processors ();
1715 }
1716
1717 void
1718 ProcessorBox::rb_deselect_all ()
1719 {
1720         if (_current_processor_box == 0) {
1721                 return;
1722         }
1723
1724         _current_processor_box->deselect_all_processors ();
1725 }
1726
1727 void
1728 ProcessorBox::rb_activate_all ()
1729 {
1730         if (_current_processor_box == 0) {
1731                 return;
1732         }
1733
1734         _current_processor_box->all_processors_active (true);
1735 }
1736
1737 void
1738 ProcessorBox::rb_deactivate_all ()
1739 {
1740         if (_current_processor_box == 0) {
1741                 return;
1742         }
1743         _current_processor_box->all_processors_active (false);
1744 }
1745
1746 void
1747 ProcessorBox::rb_edit ()
1748 {
1749         if (_current_processor_box == 0) {
1750                 return;
1751         }
1752
1753         _current_processor_box->for_selected_processors (&ProcessorBox::edit_processor);
1754 }
1755
1756 void
1757 ProcessorBox::route_name_changed ()
1758 {
1759         ENSURE_GUI_THREAD (mem_fun (*this, &ProcessorBox::route_name_changed));
1760
1761         boost::shared_ptr<Processor> processor;
1762         boost::shared_ptr<PluginInsert> plugin_insert;
1763         boost::shared_ptr<Send> send;
1764
1765         list<ProcessorEntry*> children = processor_display.children();
1766
1767         for (list<ProcessorEntry*>::iterator iter = children.begin(); iter != children.end(); ++iter) {
1768
1769                 processor = (*iter)->processor ();
1770
1771                 void* gui = processor->get_gui();
1772
1773                 if (!gui) {
1774                         continue;
1775                 }
1776
1777                 /* rename editor windows for sends and plugins */
1778
1779                 if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
1780                         static_cast<Window*>(gui)->set_title (send->name ());
1781                 } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
1782                         static_cast<Window*>(gui)->set_title (generate_processor_title (plugin_insert));
1783                 }
1784         }
1785 }
1786
1787 string
1788 ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
1789 {
1790         string maker = pi->plugin()->maker() ? pi->plugin()->maker() : "";
1791         string::size_type email_pos;
1792
1793         if ((email_pos = maker.find_first_of ('<')) != string::npos) {
1794                 maker = maker.substr (0, email_pos - 1);
1795         }
1796
1797         if (maker.length() > 32) {
1798                 maker = maker.substr (0, 32);
1799                 maker += " ...";
1800         }
1801
1802         return string_compose(_("%1: %2 (by %3)"), _route->name(), pi->name(), maker);
1803 }
1804