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