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