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