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