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