db5ee835c5d3882c82940a018808e91785883f68
[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/internal_return.h"
48 #include "ardour/ladspa_plugin.h"
49 #include "ardour/meter.h"
50 #include "ardour/plugin_insert.h"
51 #include "ardour/port_insert.h"
52 #include "ardour/profile.h"
53 #include "ardour/return.h"
54 #include "ardour/route.h"
55 #include "ardour/send.h"
56 #include "ardour/session.h"
57 #include "ardour/dB.h"
58
59 #include "actions.h"
60 #include "ardour_dialog.h"
61 #include "ardour_ui.h"
62 #include "gui_thread.h"
63 #include "io_selector.h"
64 #include "keyboard.h"
65 #include "mixer_ui.h"
66 #include "mixer_strip.h"
67 #include "plugin_selector.h"
68 #include "plugin_ui.h"
69 #include "port_insert_ui.h"
70 #include "processor_box.h"
71 #include "public_editor.h"
72 #include "return_ui.h"
73 #include "route_processor_selection.h"
74 #include "send_ui.h"
75 #include "utils.h"
76
77 #include "i18n.h"
78
79 #ifdef AUDIOUNIT_SUPPORT
80 class AUPluginUI;
81 #endif
82
83 using namespace std;
84 using namespace ARDOUR;
85 using namespace PBD;
86 using namespace Gtk;
87 using namespace Glib;
88 using namespace Gtkmm2ext;
89
90 ProcessorBox* ProcessorBox::_current_processor_box = 0;
91 RefPtr<Action> ProcessorBox::paste_action;
92 RefPtr<Action> ProcessorBox::cut_action;
93 RefPtr<Action> ProcessorBox::rename_action;
94 RefPtr<Action> ProcessorBox::edit_action;
95 RefPtr<Action> ProcessorBox::controls_action;
96 Glib::RefPtr<Gdk::Pixbuf> ProcessorEntry::_slider_pixbuf;
97
98 ProcessorEntry::ProcessorEntry (boost::shared_ptr<Processor> p, Width w)
99         : _button (ArdourButton::led_default_elements)
100         , _position (PreFader)
101         , _processor (p)
102         , _width (w)
103         , _visual_state (Gtk::STATE_NORMAL)
104 {
105         _vbox.show ();
106         
107         _button.set_diameter (3);
108         _button.set_distinct_led_click (true);
109         _button.set_led_left (true);
110         _button.signal_led_clicked.connect (sigc::mem_fun (*this, &ProcessorEntry::led_clicked));
111         _button.set_text (name (_width));
112
113         if (_processor) {
114
115                 _vbox.pack_start (_button, true, true);
116
117                 if (_processor->active()) {
118                         _button.set_active_state (Gtkmm2ext::Active);
119                 }
120                 
121                 _button.show ();
122                 
123                 _processor->ActiveChanged.connect (active_connection, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed, this), gui_context());
124                 _processor->PropertyChanged.connect (name_connection, invalidator (*this), ui_bind (&ProcessorEntry::processor_property_changed, this, _1), gui_context());
125
126                 set<Evoral::Parameter> p = _processor->what_can_be_automated ();
127                 for (set<Evoral::Parameter>::iterator i = p.begin(); i != p.end(); ++i) {
128                         if (boost::dynamic_pointer_cast<Amp> (_processor)) {
129                                 /* Don't give Fader processors separate controls here */
130                                 continue;
131                         }
132
133                         string d = _processor->describe_parameter (*i);
134                         if (boost::dynamic_pointer_cast<Send> (_processor)) {
135                                 /* Little hack; don't label send level faders */
136                                 d = "";
137                         }
138
139                         Control* c = new Control (_slider_pixbuf, _processor->automation_control (*i), d);
140                         _controls.push_back (c);
141                         _vbox.pack_start (c->box);
142                 }
143
144                 setup_tooltip ();
145                 setup_visuals ();
146         } else {
147                 _vbox.set_size_request (-1, _button.size_request().height);
148         }
149 }
150
151 ProcessorEntry::~ProcessorEntry ()
152 {
153         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
154                 delete *i;
155         }
156 }
157
158 EventBox&
159 ProcessorEntry::action_widget ()
160 {
161         return _button;
162 }
163
164 Gtk::Widget&
165 ProcessorEntry::widget ()
166 {
167         return _vbox;
168 }
169
170 string
171 ProcessorEntry::drag_text () const
172 {
173         return name (Wide);
174 }
175
176 void
177 ProcessorEntry::set_position (Position p)
178 {
179         _position = p;
180         setup_visuals ();
181 }
182
183 void
184 ProcessorEntry::set_visual_state (Gtkmm2ext::VisualState s, bool yn)
185 {
186         if (yn) {
187                 _button.set_visual_state (Gtkmm2ext::VisualState (_button.visual_state() | s));
188         } else {
189                 _button.set_visual_state (Gtkmm2ext::VisualState (_button.visual_state() & ~s));
190         }
191 }
192
193 void
194 ProcessorEntry::setup_visuals ()
195 {
196         switch (_position) {
197         case PreFader:
198                 _button.set_name ("processor prefader");
199                 break;
200
201         case Fader:
202                 _button.set_name ("processor fader");
203                 break;
204
205         case PostFader:
206                 _button.set_name ("processor postfader");
207                 break;
208         }
209 }
210
211
212 boost::shared_ptr<Processor>
213 ProcessorEntry::processor () const
214 {
215         return _processor;
216 }
217
218 void
219 ProcessorEntry::set_enum_width (Width w)
220 {
221         _width = w;
222 }
223
224 void
225 ProcessorEntry::led_clicked()
226 {
227         if (_processor) {
228                 if (_button.active_state() == Gtkmm2ext::Active) {
229                         _processor->deactivate ();
230                 } else {
231                         _processor->activate ();
232                 }
233         }
234 }
235
236 void
237 ProcessorEntry::processor_active_changed ()
238 {
239         if (_processor) {
240                 if (_processor->active()) {
241                         _button.set_active_state (Gtkmm2ext::Active);
242                 } else {
243                         _button.unset_active_state ();
244                 }
245         }
246 }
247
248 void
249 ProcessorEntry::processor_property_changed (const PropertyChange& what_changed)
250 {
251         if (what_changed.contains (ARDOUR::Properties::name)) {
252                 _button.set_text (name (_width));
253                 setup_tooltip ();
254         }
255 }
256
257 void
258 ProcessorEntry::setup_tooltip ()
259 {
260         ARDOUR_UI::instance()->set_tip (_button, name (Wide));
261 }
262
263 string
264 ProcessorEntry::name (Width w) const
265 {
266         boost::shared_ptr<Send> send;
267         string name_display;
268
269         if (!_processor) {
270                 return string();
271         }
272
273         if ((send = boost::dynamic_pointer_cast<Send> (_processor)) != 0 &&
274             !boost::dynamic_pointer_cast<InternalSend>(_processor)) {
275
276                 name_display += '>';
277
278                 /* grab the send name out of its overall name */
279
280                 string::size_type lbracket, rbracket;
281                 lbracket = send->name().find ('[');
282                 rbracket = send->name().find (']');
283
284                 switch (w) {
285                 case Wide:
286                         name_display += send->name().substr (lbracket+1, lbracket-rbracket-1);
287                         break;
288                 case Narrow:
289                         name_display += PBD::short_version (send->name().substr (lbracket+1, lbracket-rbracket-1), 4);
290                         break;
291                 }
292
293         } else {
294
295                 switch (w) {
296                 case Wide:
297                         name_display += _processor->display_name();
298                         break;
299                 case Narrow:
300                         name_display += PBD::short_version (_processor->display_name(), 5);
301                         break;
302                 }
303
304         }
305
306         return name_display;
307 }
308
309 void
310 ProcessorEntry::setup_slider_pix ()
311 {
312         _slider_pixbuf = ::get_icon ("fader_belt_h_thin");
313         assert (_slider_pixbuf);
314 }
315
316 void
317 ProcessorEntry::set_pixel_width (int p)
318 {
319         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
320                 (*i)->set_pixel_width (p);
321         }
322 }
323
324 void
325 ProcessorEntry::show_all_controls ()
326 {
327         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
328                 (*i)->show ();
329         }
330 }
331
332 void
333 ProcessorEntry::hide_all_controls ()
334 {
335         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
336                 (*i)->hide ();
337         }
338 }
339
340 void
341 ProcessorEntry::add_control_state (XMLNode* node) const
342 {
343         for (list<Control*>::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
344                 (*i)->add_state (node);
345         }
346 }
347
348 void
349 ProcessorEntry::set_control_state (XMLNode const * node)
350 {
351         for (list<Control*>::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
352                 (*i)->set_state (node);
353         }
354 }
355
356 string
357 ProcessorEntry::state_id () const
358 {
359         return string_compose ("processor %1", _processor->id().to_s());
360 }
361
362 void
363 ProcessorEntry::hide_things ()
364 {
365         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
366                 (*i)->hide_things ();
367         }
368 }
369
370 ProcessorEntry::Control::Control (Glib::RefPtr<Gdk::Pixbuf> s, boost::shared_ptr<AutomationControl> c, string const & l)
371         : _control (c)
372         , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
373         , _slider (s, &_adjustment, 0, false)
374         , _ignore_slider_adjustment (false)
375         , _visible (false)
376 {
377         _slider.set_controllable (c);
378
379         if (!l.empty ()) {
380                 box.pack_start (_label);
381                 _label.show ();
382                 _label.set_text (l);
383         }
384
385         _slider.show ();
386         box.pack_start (_slider);
387
388         double const lo = c->internal_to_interface (c->lower ());
389         double const up = c->internal_to_interface (c->upper ());
390
391         _adjustment.set_lower (lo);
392         _adjustment.set_upper (up);
393         _adjustment.set_step_increment ((up - lo) / 100);
394         _adjustment.set_page_increment ((up - lo) / 10);
395         _slider.set_default_value (c->internal_to_interface (c->normal ()));
396
397         _adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &Control::slider_adjusted));
398         c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
399
400         control_changed ();
401 }
402
403 void
404 ProcessorEntry::Control::set_pixel_width (int p)
405 {
406         _slider.set_fader_length (p);
407 }
408
409 void
410 ProcessorEntry::Control::slider_adjusted ()
411 {
412         if (_ignore_slider_adjustment) {
413                 return;
414         }
415         
416         boost::shared_ptr<AutomationControl> c = _control.lock ();
417
418         if (!c) {
419                 return;
420         }
421
422         c->set_value (c->interface_to_internal (_adjustment.get_value ()));
423 }
424
425 void
426 ProcessorEntry::Control::control_changed ()
427 {
428         boost::shared_ptr<AutomationControl> c = _control.lock ();
429         if (!c) {
430                 return;
431         }
432
433         _ignore_slider_adjustment = true;
434
435         _adjustment.set_value (c->internal_to_interface (c->get_value ()));
436
437         stringstream s;
438         s.precision (1);
439         s.setf (ios::fixed, ios::floatfield);
440         s << c->internal_to_user (c->get_value ());
441         
442         _slider.set_tooltip_text (s.str ());
443         
444         _ignore_slider_adjustment = false;
445 }
446
447 void
448 ProcessorEntry::Control::add_state (XMLNode* node) const
449 {
450         XMLNode* c = new XMLNode (X_("Object"));
451         c->add_property (X_("id"), state_id ());
452         c->add_property (X_("visible"), _visible);
453         node->add_child_nocopy (*c);
454 }
455
456 void
457 ProcessorEntry::Control::set_state (XMLNode const * node)
458 {
459         XMLNode* n = GUIObjectState::get_node (node, state_id ());
460         if (n) {
461                 XMLProperty* p = n->property (X_("visible"));
462                 if (p && string_is_affirmative (p->value ())) {
463                         show ();
464                 } else {
465                         hide ();
466                 }
467         } else {
468                 hide ();
469         }
470 }
471
472 void
473 ProcessorEntry::Control::show ()
474 {
475         box.show ();
476         _visible = true;
477 }
478
479 void
480 ProcessorEntry::Control::hide ()
481 {
482         box.hide ();
483         _visible = false;
484 }
485
486 /** Called when the Editor might have re-shown things that
487     we want hidden.
488 */
489 void
490 ProcessorEntry::Control::hide_things ()
491 {
492         if (!_visible) {
493                 box.hide ();
494         }
495 }
496
497 string
498 ProcessorEntry::Control::state_id () const
499 {
500         boost::shared_ptr<AutomationControl> c = _control.lock ();
501         assert (c);
502
503         return string_compose (X_("control %1"), c->id().to_s ());
504 }
505
506 BlankProcessorEntry::BlankProcessorEntry (Width w)
507         : ProcessorEntry (boost::shared_ptr<Processor>(), w)
508 {
509 }
510
511 PluginInsertProcessorEntry::PluginInsertProcessorEntry (boost::shared_ptr<ARDOUR::PluginInsert> p, Width w)
512         : ProcessorEntry (p, w)
513         , _plugin_insert (p)
514 {
515         p->SplittingChanged.connect (
516                 _splitting_connection, invalidator (*this), ui_bind (&PluginInsertProcessorEntry::plugin_insert_splitting_changed, this), gui_context()
517                 );
518
519         _splitting_icon.set_size_request (-1, 12);
520
521         _vbox.pack_start (_splitting_icon);
522         _vbox.reorder_child (_splitting_icon, 0);
523
524         plugin_insert_splitting_changed ();
525 }
526
527 void
528 PluginInsertProcessorEntry::plugin_insert_splitting_changed ()
529 {
530         if (_plugin_insert->splitting ()) {
531                 _splitting_icon.show ();
532         } else {
533                 _splitting_icon.hide ();
534         }
535 }
536
537 void
538 PluginInsertProcessorEntry::hide_things ()
539 {
540         ProcessorEntry::hide_things ();
541         plugin_insert_splitting_changed ();
542 }
543
544 void
545 PluginInsertProcessorEntry::setup_visuals ()
546 {
547         switch (_position) {
548         case PreFader:
549                 _splitting_icon.set_name ("ProcessorPreFader");
550                 break;
551
552         case Fader:
553                 _splitting_icon.set_name ("ProcessorFader");
554                 break;
555
556         case PostFader:
557                 _splitting_icon.set_name ("ProcessorPostFader");
558                 break;
559         }
560
561         ProcessorEntry::setup_visuals ();
562 }
563
564 bool
565 PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose* ev)
566 {
567         cairo_t* cr = gdk_cairo_create (get_window()->gobj());
568
569         cairo_set_line_width (cr, 1);
570
571         double const width = ev->area.width;
572         double const height = ev->area.height;
573
574         Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
575         cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
576
577         cairo_rectangle (cr, 0, 0, width, height);
578         cairo_fill (cr);
579
580         Gdk::Color const fg = get_style()->get_fg (STATE_NORMAL);
581         cairo_set_source_rgb (cr, fg.get_red_p (), fg.get_green_p (), fg.get_blue_p ());
582
583         cairo_move_to (cr, width * 0.3, height);
584         cairo_line_to (cr, width * 0.3, height * 0.5);
585         cairo_line_to (cr, width * 0.7, height * 0.5);
586         cairo_line_to (cr, width * 0.7, height);
587         cairo_move_to (cr, width * 0.5, height * 0.5);
588         cairo_line_to (cr, width * 0.5, 0);
589         cairo_stroke (cr);
590
591         return true;
592 }
593
594 ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
595                             RouteProcessorSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
596         : _parent_strip (parent)
597         , _owner_is_mixer (owner_is_mixer)
598         , ab_direction (true)
599         , _get_plugin_selector (get_plugin_selector)
600         , _placement (-1)
601         , _visible_prefader_processors (0)
602         , _rr_selection(rsel)
603 {
604         set_session (sess);
605
606         _width = Wide;
607         processor_menu = 0;
608         no_processor_redisplay = false;
609
610         processor_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
611         processor_scroller.add (processor_display);
612         pack_start (processor_scroller, true, true);
613
614         processor_display.set_flags (CAN_FOCUS);
615         processor_display.set_name ("ProcessorList");
616         processor_display.set_size_request (48, -1);
617         processor_display.set_data ("processorbox", this);
618         processor_display.set_spacing (2);
619
620         processor_display.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify), false);
621         processor_display.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify), false);
622
623         processor_display.ButtonPress.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event));
624         processor_display.ButtonRelease.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event));
625
626         processor_display.Reordered.connect (sigc::mem_fun (*this, &ProcessorBox::reordered));
627         processor_display.DropFromAnotherBox.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop));
628
629         processor_scroller.show ();
630         processor_display.show ();
631
632         if (parent) {
633                 parent->DeliveryChanged.connect (
634                         _mixer_strip_connections, invalidator (*this), ui_bind (&ProcessorBox::mixer_strip_delivery_changed, this, _1), gui_context ()
635                         );
636         }
637
638         ARDOUR_UI::instance()->set_tip (processor_display, _("Right-click to add/remove/edit\nplugins,inserts,sends and more"));
639 }
640
641 ProcessorBox::~ProcessorBox ()
642 {
643         /* it may appear as if we should delete processor_menu but that is a
644          * pointer to a widget owned by the UI Manager, and has potentially
645          * be returned to many other ProcessorBoxes. GTK doesn't really make
646          * clear the ownership of this widget, which is a menu and thus is
647          * never packed into any container other than an implict GtkWindow.
648          *
649          * For now, until or if we ever get clarification over the ownership
650          * story just let it continue to exist. At worst, its a small memory leak.
651          */
652 }
653
654 void
655 ProcessorBox::set_route (boost::shared_ptr<Route> r)
656 {
657         if (_route == r) {
658                 return;
659         }
660
661         _route_connections.drop_connections();
662
663         /* new route: any existing block on processor redisplay must be meaningless */
664         no_processor_redisplay = false;
665         _route = r;
666
667         _route->processors_changed.connect (
668                 _route_connections, invalidator (*this), ui_bind (&ProcessorBox::route_processors_changed, this, _1), gui_context()
669                 );
670
671         _route->DropReferences.connect (
672                 _route_connections, invalidator (*this), boost::bind (&ProcessorBox::route_going_away, this), gui_context()
673                 );
674
675         _route->PropertyChanged.connect (
676                 _route_connections, invalidator (*this), ui_bind (&ProcessorBox::route_property_changed, this, _1), gui_context()
677                 );
678
679         redisplay_processors ();
680 }
681
682 void
683 ProcessorBox::route_going_away ()
684 {
685         /* don't keep updating display as processors are deleted */
686         no_processor_redisplay = true;
687         _route.reset ();
688 }
689
690 void
691 ProcessorBox::object_drop(DnDVBox<ProcessorEntry>* source, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
692 {
693         boost::shared_ptr<Processor> p;
694         if (position) {
695                 p = position->processor ();
696         }
697
698         list<ProcessorEntry*> children = source->selection ();
699         list<boost::shared_ptr<Processor> > procs;
700         for (list<ProcessorEntry*>::const_iterator i = children.begin(); i != children.end(); ++i) {
701                 if ((*i)->processor ()) {
702                         procs.push_back ((*i)->processor ());
703                 }
704         }
705
706         for (list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin(); i != procs.end(); ++i) {
707                 XMLNode& state = (*i)->get_state ();
708                 XMLNodeList nlist;
709                 nlist.push_back (&state);
710                 paste_processor_state (nlist, p);
711                 delete &state;
712         }
713
714         /* since the dndvbox doesn't take care of this properly, we have to delete the originals
715            ourselves.
716         */
717
718         if ((context->get_suggested_action() == Gdk::ACTION_MOVE) && source) {
719                 ProcessorBox* other = reinterpret_cast<ProcessorBox*> (source->get_data ("processorbox"));
720                 if (other) {
721                         other->delete_dragged_processors (procs);
722                 }
723         }
724 }
725
726 void
727 ProcessorBox::update()
728 {
729         redisplay_processors ();
730 }
731
732 void
733 ProcessorBox::set_width (Width w)
734 {
735         if (_width == w) {
736                 return;
737         }
738
739         _width = w;
740
741         list<ProcessorEntry*> children = processor_display.children ();
742         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
743                 (*i)->set_enum_width (w);
744         }
745
746         redisplay_processors ();
747 }
748
749 Gtk::Menu*
750 ProcessorBox::build_possible_aux_menu ()
751 {
752         boost::shared_ptr<RouteList> rl = _session->get_routes_with_internal_returns();
753
754         if (rl->empty()) {
755                 return 0;
756         }
757
758         using namespace Menu_Helpers;
759         Menu* menu = manage (new Menu);
760         MenuList& items = menu->items();
761
762         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
763                 if (!_route->internal_send_for (*r) && *r != _route) {
764                         items.push_back (MenuElem ((*r)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux), boost::weak_ptr<Route>(*r))));
765                 }
766         }
767
768         return menu;
769 }
770
771 void
772 ProcessorBox::show_processor_menu (int arg)
773 {
774         if (processor_menu == 0) {
775                 processor_menu = build_processor_menu ();
776                 processor_menu->signal_unmap().connect (sigc::mem_fun (*this, &ProcessorBox::processor_menu_unmapped));
777         }
778
779         /* Sort out the plugin submenu */
780
781         Gtk::MenuItem* plugin_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
782
783         if (plugin_menu_item) {
784                 plugin_menu_item->set_submenu (*_get_plugin_selector()->plugin_menu());
785         }
786
787         /* And the aux submenu */
788
789         Gtk::MenuItem* aux_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newaux"));
790
791         if (aux_menu_item) {
792                 Menu* m = build_possible_aux_menu();
793                 if (m && !m->items().empty()) {
794                         aux_menu_item->set_submenu (*m);
795                         aux_menu_item->set_sensitive (true);
796                 } else {
797                         /* stupid gtkmm: we need to pass a null reference here */
798                         gtk_menu_item_set_submenu (aux_menu_item->gobj(), 0);
799                         aux_menu_item->set_sensitive (false);
800                 }
801         }
802
803         boost::shared_ptr<Processor> single_selection;
804         if (processor_display.selection().size() == 1) {
805                 single_selection = processor_display.selection().front()->processor ();
806         }
807
808         /* And the controls submenu */
809
810         Gtk::MenuItem* controls_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/controls"));
811
812         if (controls_menu_item) {
813                 if (single_selection) {
814                         Menu* m = build_controls_menu (single_selection);
815                         if (m && !m->items().empty()) {
816                                 controls_menu_item->set_submenu (*m);
817                                 controls_menu_item->set_sensitive (true);
818                         } else {
819                                 gtk_menu_item_set_submenu (controls_menu_item->gobj(), 0);
820                                 controls_menu_item->set_sensitive (false);
821                         }
822                 }
823         }
824
825         /* Sensitise actions as approprioate */
826
827         cut_action->set_sensitive (can_cut());
828         paste_action->set_sensitive (!_rr_selection.processors.empty());
829
830         const bool sensitive = !processor_display.selection().empty();
831         ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions, sensitive);
832         edit_action->set_sensitive (one_processor_can_be_edited ());
833
834         boost::shared_ptr<PluginInsert> pi;
835         if (single_selection) {
836                 pi = boost::dynamic_pointer_cast<PluginInsert> (single_selection);
837         }
838
839         /* disallow rename for multiple selections, for plugin inserts and for the fader */
840         rename_action->set_sensitive (single_selection && !pi && !boost::dynamic_pointer_cast<Amp> (single_selection));
841
842         processor_menu->popup (1, arg);
843
844         /* Add a placeholder gap to the processor list to indicate where a processor would be
845            inserted were one chosen from the menu.
846         */
847         int x, y;
848         processor_display.get_pointer (x, y);
849         _placement = processor_display.add_placeholder (y);
850
851         if (_visible_prefader_processors == 0) {
852                 if (_placement == 1) {
853                         _placement = 0;
854                 }
855         }
856 }
857
858 bool
859 ProcessorBox::enter_notify (GdkEventCrossing*)
860 {
861         _current_processor_box = this;
862         return false;
863 }
864
865 bool
866 ProcessorBox::leave_notify (GdkEventCrossing* ev)
867 {
868         return false;
869 }
870
871 void
872 ProcessorBox::processor_operation (ProcessorOperation op) 
873 {
874         ProcSelection targets;
875
876         get_selected_processors (targets);
877
878         if (targets.empty()) {
879
880                 int x, y;
881                 processor_display.get_pointer (x, y);
882
883                 pair<ProcessorEntry *, double> const pointer = processor_display.get_child_at_position (y);
884
885                 if (pointer.first && pointer.first->processor()) {
886                         targets.push_back (pointer.first->processor ());
887                 }
888         }
889
890         switch (op) {
891         case ProcessorsSelectAll:
892                 processor_display.select_all ();
893                 break;
894
895         case ProcessorsCopy:
896                 copy_processors (targets);
897                 break;
898
899         case ProcessorsCut:
900                 cut_processors (targets);
901                 break;
902
903         case ProcessorsPaste:
904                 if (targets.empty()) {
905                         paste_processors ();
906                 } else {
907                         paste_processors (targets.front());
908                 }
909                 break;
910
911         case ProcessorsDelete:
912                 delete_processors (targets);
913                 break;
914
915         case ProcessorsToggleActive:
916                 for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
917                         if ((*i)->active()) {
918                                 (*i)->deactivate ();
919                         } else {
920                                 (*i)->activate ();
921                         }
922                 }
923                 break;
924
925         case ProcessorsAB:
926                 ab_plugins ();
927                 break;
928
929         default:
930                 break;
931         }
932 }
933
934 bool
935 ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* child)
936 {
937         boost::shared_ptr<Processor> processor;
938         if (child) {
939                 processor = child->processor ();
940         }
941
942         int ret = false;
943         bool selected = processor_display.selected (child);
944
945         if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
946
947                 if (_session->engine().connected()) {
948                         /* XXX giving an error message here is hard, because we may be in the midst of a button press */
949                         toggle_edit_processor (processor);
950                 }
951                 ret = true;
952
953         } else if (processor && ev->button == 1 && selected) {
954
955                 // this is purely informational but necessary for route params UI
956                 ProcessorSelected (processor); // emit
957
958         } else if (!processor && ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
959
960                 choose_plugin ();
961                 _get_plugin_selector()->show_manager ();
962         }
963
964         return ret;
965 }
966
967 bool
968 ProcessorBox::processor_button_release_event (GdkEventButton *ev, ProcessorEntry* child)
969 {
970         boost::shared_ptr<Processor> processor;
971         if (child) {
972                 processor = child->processor ();
973         }
974
975         if (processor && Keyboard::is_delete_event (ev)) {
976
977                 Glib::signal_idle().connect (sigc::bind (
978                                 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor),
979                                 boost::weak_ptr<Processor>(processor)));
980
981         } else if (Keyboard::is_context_menu_event (ev)) {
982
983                 show_processor_menu (ev->time);
984
985         } else if (processor && Keyboard::is_button2_event (ev)
986 #ifndef GTKOSX
987                    && (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))
988 #endif
989                 ) {
990
991                 /* button2-click with no/appropriate modifiers */
992
993                 if (processor->active()) {
994                         processor->deactivate ();
995                 } else {
996                         processor->activate ();
997                 }
998         }
999
1000         return false;
1001 }
1002
1003 Menu *
1004 ProcessorBox::build_processor_menu ()
1005 {
1006         processor_menu = dynamic_cast<Gtk::Menu*>(ActionManager::get_widget("/ProcessorMenu") );
1007         processor_menu->set_name ("ArdourContextMenu");
1008         return processor_menu;
1009 }
1010
1011 void
1012 ProcessorBox::select_all_processors ()
1013 {
1014         processor_display.select_all ();
1015 }
1016
1017 void
1018 ProcessorBox::deselect_all_processors ()
1019 {
1020         processor_display.select_none ();
1021 }
1022
1023 void
1024 ProcessorBox::choose_plugin ()
1025 {
1026         _get_plugin_selector()->set_interested_object (*this);
1027 }
1028
1029 /** @return true if an error occurred, otherwise false */
1030 bool
1031 ProcessorBox::use_plugins (const SelectedPlugins& plugins)
1032 {
1033         for (SelectedPlugins::const_iterator p = plugins.begin(); p != plugins.end(); ++p) {
1034
1035                 boost::shared_ptr<Processor> processor (new PluginInsert (*_session, *p));
1036
1037                 Route::ProcessorStreams err_streams;
1038
1039                 if (_route->add_processor_by_index (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
1040                         weird_plugin_dialog (**p, err_streams);
1041                         return true;
1042                         // XXX SHAREDPTR delete plugin here .. do we even need to care?
1043                 } else {
1044
1045                         if (Profile->get_sae()) {
1046                                 processor->activate ();
1047                         }
1048                 }
1049         }
1050
1051         return false;
1052 }
1053
1054 void
1055 ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams)
1056 {
1057         ArdourDialog dialog (_("Plugin Incompatibility"));
1058         Label label;
1059
1060         string text = string_compose(_("You attempted to add the plugin \"%1\" in slot %2.\n"),
1061                         p.name(), streams.index);
1062
1063         bool has_midi  = streams.count.n_midi() > 0 || p.get_info()->n_inputs.n_midi() > 0;
1064         bool has_audio = streams.count.n_audio() > 0 || p.get_info()->n_inputs.n_audio() > 0;
1065
1066         text += _("\nThis plugin has:\n");
1067         if (has_midi) {
1068                 uint32_t const n = p.get_info()->n_inputs.n_midi ();
1069                 text += string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n), n);
1070         }
1071         if (has_audio) {
1072                 uint32_t const n = p.get_info()->n_inputs.n_audio ();
1073                 text += string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n), n);
1074         }
1075
1076         text += _("\nbut at the insertion point, there are:\n");
1077         if (has_midi) {
1078                 uint32_t const n = streams.count.n_midi ();
1079                 text += string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n), n);
1080         }
1081         if (has_audio) {
1082                 uint32_t const n = streams.count.n_audio ();
1083                 text += string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n), n);
1084         }
1085
1086         text += string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME);
1087         label.set_text(text);
1088
1089         dialog.get_vbox()->pack_start (label);
1090         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
1091
1092         dialog.set_name (X_("PluginIODialog"));
1093         dialog.set_position (Gtk::WIN_POS_MOUSE);
1094         dialog.set_modal (true);
1095         dialog.show_all ();
1096
1097         dialog.run ();
1098 }
1099
1100 void
1101 ProcessorBox::choose_insert ()
1102 {
1103         boost::shared_ptr<Processor> processor (new PortInsert (*_session, _route->pannable(), _route->mute_master()));
1104         _route->add_processor_by_index (processor, _placement);
1105 }
1106
1107 /* Caller must not hold process lock */
1108 void
1109 ProcessorBox::choose_send ()
1110 {
1111         boost::shared_ptr<Send> send (new Send (*_session, _route->pannable(), _route->mute_master()));
1112
1113         /* make an educated guess at the initial number of outputs for the send */
1114         ChanCount outs = (_session->master_out())
1115                         ? _session->master_out()->n_outputs()
1116                         : _route->n_outputs();
1117
1118         /* XXX need processor lock on route */
1119         try {
1120                 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
1121                 send->output()->ensure_io (outs, false, this);
1122         } catch (AudioEngine::PortRegistrationFailure& err) {
1123                 error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
1124                 return;
1125         }
1126
1127         /* let the user adjust the IO setup before creation.
1128
1129            Note: this dialog is NOT modal - we just leave it to run and it will
1130            return when its Finished signal is emitted - typically when the window
1131            is closed.
1132          */
1133
1134         IOSelectorWindow *ios = new IOSelectorWindow (_session, send->output(), true);
1135         ios->show ();
1136
1137         /* keep a reference to the send so it doesn't get deleted while
1138            the IOSelectorWindow is doing its stuff
1139         */
1140         _processor_being_created = send;
1141
1142         ios->selector().Finished.connect (sigc::bind (
1143                         sigc::mem_fun(*this, &ProcessorBox::send_io_finished),
1144                         boost::weak_ptr<Processor>(send), ios));
1145
1146 }
1147
1148 void
1149 ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
1150 {
1151         boost::shared_ptr<Processor> processor (weak_processor.lock());
1152
1153         /* drop our temporary reference to the new send */
1154         _processor_being_created.reset ();
1155
1156         if (!processor) {
1157                 return;
1158         }
1159
1160         switch (r) {
1161         case IOSelector::Cancelled:
1162                 // processor will go away when all shared_ptrs to it vanish
1163                 break;
1164
1165         case IOSelector::Accepted:
1166                 _route->add_processor_by_index (processor, _placement);
1167                 if (Profile->get_sae()) {
1168                         processor->activate ();
1169                 }
1170                 break;
1171         }
1172
1173         delete_when_idle (ios);
1174 }
1175
1176 void
1177 ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
1178 {
1179         boost::shared_ptr<Processor> processor (weak_processor.lock());
1180
1181         /* drop our temporary reference to the new return */
1182         _processor_being_created.reset ();
1183
1184         if (!processor) {
1185                 return;
1186         }
1187
1188         switch (r) {
1189         case IOSelector::Cancelled:
1190                 // processor will go away when all shared_ptrs to it vanish
1191                 break;
1192
1193         case IOSelector::Accepted:
1194                 _route->add_processor_by_index (processor, _placement);
1195                 if (Profile->get_sae()) {
1196                         processor->activate ();
1197                 }
1198                 break;
1199         }
1200
1201         delete_when_idle (ios);
1202 }
1203
1204 void
1205 ProcessorBox::choose_aux (boost::weak_ptr<Route> wr)
1206 {
1207         if (!_route) {
1208                 return;
1209         }
1210
1211         boost::shared_ptr<Route> target = wr.lock();
1212
1213         if (!target) {
1214                 return;
1215         }
1216
1217         boost::shared_ptr<RouteList> rlist (new RouteList);
1218         rlist->push_back (_route);
1219
1220         _session->add_internal_sends (target, PreFader, rlist);
1221 }
1222
1223 void
1224 ProcessorBox::route_processors_changed (RouteProcessorChange c)
1225 {
1226         if (c.type == RouteProcessorChange::MeterPointChange && c.meter_visibly_changed == false) {
1227                 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1228                 return;
1229         }
1230
1231         redisplay_processors ();
1232 }
1233
1234 void
1235 ProcessorBox::redisplay_processors ()
1236 {
1237         ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors);
1238         bool     fader_seen;
1239
1240         if (no_processor_redisplay) {
1241                 return;
1242         }
1243
1244         processor_display.clear ();
1245
1246         _visible_prefader_processors = 0;
1247         fader_seen = false;
1248
1249         _route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &ProcessorBox::help_count_visible_prefader_processors), 
1250                                                &_visible_prefader_processors, &fader_seen));
1251
1252         if (_visible_prefader_processors == 0) { // fader only
1253                 BlankProcessorEntry* bpe = new BlankProcessorEntry (_width);
1254                 bpe->set_pixel_width (get_allocation().get_width());
1255                 processor_display.add_child (bpe);
1256         }
1257
1258         _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display));
1259
1260         for (list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin(); i != _processor_window_proxies.end(); ++i) {
1261                 (*i)->marked = false;
1262         }
1263
1264         _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list));
1265
1266         /* trim dead wood from the processor window proxy list */
1267
1268         list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin();
1269         while (i != _processor_window_proxies.end()) {
1270                 list<ProcessorWindowProxy*>::iterator j = i;
1271                 ++j;
1272
1273                 if (!(*i)->marked) {
1274                         ARDOUR_UI::instance()->remove_window_proxy (*i);
1275                         delete *i;
1276                         _processor_window_proxies.erase (i);
1277                 }
1278
1279                 i = j;
1280         }
1281
1282         setup_entry_positions ();
1283 }
1284
1285 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
1286  *  not already have one.
1287  */
1288 void
1289 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
1290 {
1291         boost::shared_ptr<Processor> p = w.lock ();
1292         if (!p) {
1293                 return;
1294         }
1295
1296         list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin ();
1297         while (i != _processor_window_proxies.end()) {
1298
1299                 boost::shared_ptr<Processor> t = (*i)->processor().lock ();
1300
1301                 if (p == t) {
1302                         /* this processor is already on the list; done */
1303                         (*i)->marked = true;
1304                         return;
1305                 }
1306
1307                 ++i;
1308         }
1309
1310         /* not on the list; add it */
1311
1312         string loc;
1313         if (_parent_strip) {
1314                 if (_parent_strip->mixer_owned()) {
1315                         loc = X_("M");
1316                 } else {
1317                         loc = X_("R");
1318                 }
1319         } else {
1320                 loc = X_("P");
1321         }
1322
1323         ProcessorWindowProxy* wp = new ProcessorWindowProxy (
1324                 string_compose ("%1-%2-%3", loc, _route->id(), p->id()),
1325                 _session->extra_xml (X_("UI")),
1326                 this,
1327                 w);
1328
1329         wp->marked = true;
1330
1331         /* if the processor already has an existing UI,
1332            note that so that we don't recreate it
1333         */
1334
1335         void* existing_ui = p->get_ui ();
1336
1337         if (existing_ui) {
1338                 wp->set (static_cast<Gtk::Window*>(existing_ui));
1339         }
1340
1341         _processor_window_proxies.push_back (wp);
1342         ARDOUR_UI::instance()->add_window_proxy (wp);
1343 }
1344
1345 void
1346 ProcessorBox::help_count_visible_prefader_processors (boost::weak_ptr<Processor> p, uint32_t* cnt, bool* amp_seen)
1347 {
1348         boost::shared_ptr<Processor> processor (p.lock ());
1349
1350         if (processor && processor->display_to_user()) {
1351
1352                 if (boost::dynamic_pointer_cast<Amp>(processor)) {
1353                         *amp_seen = true;
1354                 } else {
1355                         if (!*amp_seen) {
1356                                 (*cnt)++;
1357                         }
1358                 }
1359         }
1360 }
1361
1362 void
1363 ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
1364 {
1365         boost::shared_ptr<Processor> processor (p.lock ());
1366
1367         if (!processor || !processor->display_to_user()) {
1368                 return;
1369         }
1370
1371         boost::shared_ptr<PluginInsert> plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor);
1372         ProcessorEntry* e = 0;
1373         if (plugin_insert) {
1374                 e = new PluginInsertProcessorEntry (plugin_insert, _width);
1375         } else {
1376                 e = new ProcessorEntry (processor, _width);
1377         }
1378
1379         e->set_pixel_width (get_allocation().get_width());
1380
1381         /* Set up this entry's state from the GUIObjectState */
1382         XMLNode* proc = entry_gui_object_state (e);
1383         if (proc) {
1384                 e->set_control_state (proc);
1385         }
1386         
1387         if (boost::dynamic_pointer_cast<Send> (processor)) {
1388                 /* Always show send controls */
1389                 e->show_all_controls ();
1390         }
1391
1392         processor_display.add_child (e);
1393 }
1394
1395 void
1396 ProcessorBox::reordered ()
1397 {
1398         compute_processor_sort_keys ();
1399         setup_entry_positions ();
1400 }
1401
1402 void
1403 ProcessorBox::setup_entry_positions ()
1404 {
1405         list<ProcessorEntry*> children = processor_display.children ();
1406         bool pre_fader = true;
1407
1408         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
1409                 if (boost::dynamic_pointer_cast<Amp>((*i)->processor())) {
1410                         pre_fader = false;
1411                         (*i)->set_position (ProcessorEntry::Fader);
1412                 } else {
1413                         if (pre_fader) {
1414                                 (*i)->set_position (ProcessorEntry::PreFader);
1415                         } else {
1416                                 (*i)->set_position (ProcessorEntry::PostFader);
1417                         }
1418                 }
1419         }
1420 }
1421
1422 void
1423 ProcessorBox::compute_processor_sort_keys ()
1424 {
1425         list<ProcessorEntry*> children = processor_display.children ();
1426         Route::ProcessorList our_processors;
1427
1428         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
1429                 if ((*i)->processor()) {
1430                         our_processors.push_back ((*i)->processor ());
1431                 }
1432         }
1433
1434         if (_route->reorder_processors (our_processors)) {
1435                 /* Reorder failed, so report this to the user.  As far as I can see this must be done
1436                    in an idle handler: it seems that the redisplay_processors() that happens below destroys
1437                    widgets that were involved in the drag-and-drop on the processor list, which causes problems
1438                    when the drag is torn down after this handler function is finished.
1439                 */
1440                 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder));
1441         }
1442 }
1443
1444 void
1445 ProcessorBox::report_failed_reorder ()
1446 {
1447         /* reorder failed, so redisplay */
1448
1449         redisplay_processors ();
1450
1451         /* now tell them about the problem */
1452
1453         ArdourDialog dialog (_("Plugin Incompatibility"));
1454         Label label;
1455
1456         label.set_text (_("\
1457 You cannot reorder these plugins/sends/inserts\n\
1458 in that way because the inputs and\n\
1459 outputs will not work correctly."));
1460
1461         dialog.get_vbox()->set_border_width (12);
1462         dialog.get_vbox()->pack_start (label);
1463         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
1464
1465         dialog.set_name (X_("PluginIODialog"));
1466         dialog.set_position (Gtk::WIN_POS_MOUSE);
1467         dialog.set_modal (true);
1468         dialog.show_all ();
1469
1470         dialog.run ();
1471 }
1472
1473 void
1474 ProcessorBox::rename_processors ()
1475 {
1476         ProcSelection to_be_renamed;
1477
1478         get_selected_processors (to_be_renamed);
1479
1480         if (to_be_renamed.empty()) {
1481                 return;
1482         }
1483
1484         for (ProcSelection::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
1485                 rename_processor (*i);
1486         }
1487 }
1488
1489 bool
1490 ProcessorBox::can_cut () const
1491 {
1492         vector<boost::shared_ptr<Processor> > sel;
1493
1494         get_selected_processors (sel);
1495
1496         /* cut_processors () does not cut inserts */
1497
1498         for (vector<boost::shared_ptr<Processor> >::const_iterator i = sel.begin (); i != sel.end (); ++i) {
1499
1500                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1501                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1502                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1503                         return true;
1504                 }
1505         }
1506
1507         return false;
1508 }
1509
1510 void
1511 ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
1512 {
1513         if (to_be_removed.empty()) {
1514                 return;
1515         }
1516
1517         XMLNode* node = new XMLNode (X_("cut"));
1518         Route::ProcessorList to_cut;
1519
1520         no_processor_redisplay = true;
1521         for (ProcSelection::const_iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
1522                 // Cut only plugins, sends and returns
1523                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1524                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1525                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1526
1527                         Window* w = get_processor_ui (*i);
1528
1529                         if (w) {
1530                                 w->hide ();
1531                         }
1532
1533                         XMLNode& child ((*i)->get_state());
1534                         node->add_child_nocopy (child);
1535                         to_cut.push_back (*i);
1536                 }
1537         }
1538
1539         if (_route->remove_processors (to_cut) != 0) {
1540                 delete node;
1541                 no_processor_redisplay = false;
1542                 return;
1543         }
1544
1545         _rr_selection.set (node);
1546
1547         no_processor_redisplay = false;
1548         redisplay_processors ();
1549 }
1550
1551 void
1552 ProcessorBox::copy_processors (const ProcSelection& to_be_copied)
1553 {
1554         if (to_be_copied.empty()) {
1555                 return;
1556         }
1557
1558         XMLNode* node = new XMLNode (X_("copy"));
1559
1560         for (ProcSelection::const_iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
1561                 // Copy only plugins, sends, returns
1562                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1563                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1564                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1565                         node->add_child_nocopy ((*i)->get_state());
1566                 }
1567         }
1568
1569         _rr_selection.set (node);
1570 }
1571
1572 void
1573 ProcessorBox::processors_up ()
1574 {
1575         /* unimplemented */
1576 }
1577
1578 void
1579 ProcessorBox::processors_down ()
1580 {
1581         /* unimplemented */
1582 }
1583         
1584
1585 void
1586 ProcessorBox::delete_processors (const ProcSelection& targets)
1587 {
1588         if (targets.empty()) {
1589                 return;
1590         }
1591
1592         no_processor_redisplay = true;
1593
1594         for (ProcSelection::const_iterator i = targets.begin(); i != targets.end(); ++i) {
1595
1596                 Window* w = get_processor_ui (*i);
1597
1598                 if (w) {
1599                         w->hide ();
1600                 }
1601
1602                 _route->remove_processor(*i);
1603         }
1604
1605         no_processor_redisplay = false;
1606         redisplay_processors ();
1607 }
1608
1609 void
1610 ProcessorBox::delete_dragged_processors (const list<boost::shared_ptr<Processor> >& procs)
1611 {
1612         list<boost::shared_ptr<Processor> >::const_iterator x;
1613
1614         no_processor_redisplay = true;
1615         for (x = procs.begin(); x != procs.end(); ++x) {
1616
1617                 Window* w = get_processor_ui (*x);
1618
1619                 if (w) {
1620                         w->hide ();
1621                 }
1622
1623                 _route->remove_processor(*x);
1624         }
1625
1626         no_processor_redisplay = false;
1627         redisplay_processors ();
1628 }
1629
1630 gint
1631 ProcessorBox::idle_delete_processor (boost::weak_ptr<Processor> weak_processor)
1632 {
1633         boost::shared_ptr<Processor> processor (weak_processor.lock());
1634
1635         if (!processor) {
1636                 return false;
1637         }
1638
1639         /* NOT copied to _mixer.selection() */
1640
1641         no_processor_redisplay = true;
1642         _route->remove_processor (processor);
1643         no_processor_redisplay = false;
1644         redisplay_processors ();
1645
1646         return false;
1647 }
1648
1649 void
1650 ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
1651 {
1652         ArdourPrompter name_prompter (true);
1653         string result;
1654         name_prompter.set_title (_("Rename Processor"));
1655         name_prompter.set_prompt (_("New name:"));
1656         name_prompter.set_initial_text (processor->name());
1657         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1658         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1659         name_prompter.show_all ();
1660
1661         switch (name_prompter.run ()) {
1662
1663         case Gtk::RESPONSE_ACCEPT:
1664                 name_prompter.get_result (result);
1665                 if (result.length()) {
1666
1667                        int tries = 0;
1668                        string test = result;
1669
1670                        while (tries < 100) {
1671                                if (_session->io_name_is_legal (test)) {
1672                                        result = test;
1673                                        break;
1674                                }
1675                                tries++;
1676
1677                                test = string_compose ("%1-%2", result, tries);
1678                        }
1679
1680                        if (tries < 100) {
1681                                processor->set_name (result);
1682                        } else {
1683                                /* unlikely! */
1684                                ARDOUR_UI::instance()->popup_error
1685                                        (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result));
1686                        }
1687                 }
1688                 break;
1689         }
1690
1691         return;
1692 }
1693
1694 void
1695 ProcessorBox::paste_processors ()
1696 {
1697         if (_rr_selection.processors.empty()) {
1698                 return;
1699         }
1700
1701         paste_processor_state (_rr_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
1702 }
1703
1704 void
1705 ProcessorBox::paste_processors (boost::shared_ptr<Processor> before)
1706 {
1707
1708         if (_rr_selection.processors.empty()) {
1709                 return;
1710         }
1711
1712         paste_processor_state (_rr_selection.processors.get_node().children(), before);
1713 }
1714
1715 void
1716 ProcessorBox::paste_processor_state (const XMLNodeList& nlist, boost::shared_ptr<Processor> p)
1717 {
1718         XMLNodeConstIterator niter;
1719         list<boost::shared_ptr<Processor> > copies;
1720
1721         if (nlist.empty()) {
1722                 return;
1723         }
1724
1725         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1726
1727                 XMLProperty const * type = (*niter)->property ("type");
1728                 assert (type);
1729
1730                 boost::shared_ptr<Processor> p;
1731                 try {
1732                         if (type->value() == "meter" ||
1733                             type->value() == "main-outs" ||
1734                             type->value() == "amp" ||
1735                             type->value() == "intsend" || type->value() == "intreturn") {
1736                                 /* do not paste meter, main outs, amp or internal send/returns */
1737                                 continue;
1738
1739                         } else if (type->value() == "send") {
1740
1741                                 XMLNode n (**niter);
1742                                 Send::make_unique (n, *_session);
1743                                 Send* s = new Send (*_session, _route->pannable(), _route->mute_master());
1744                                 if (s->set_state (n, Stateful::loading_state_version)) {
1745                                         delete s;
1746                                         return;
1747                                 }
1748
1749                                 p.reset (s);
1750
1751
1752                         } else if (type->value() == "return") {
1753
1754                                 XMLNode n (**niter);
1755                                 Return::make_unique (n, *_session);
1756                                 Return* r = new Return (*_session);
1757
1758                                 if (r->set_state (n, Stateful::loading_state_version)) {
1759                                         delete r;
1760                                         return;
1761                                 }
1762
1763                                 p.reset (r);
1764
1765                         } else if (type->value() == "port") {
1766
1767                                 XMLNode n (**niter);
1768                                 p.reset (new PortInsert (*_session, _route->pannable (), _route->mute_master ()));
1769                                 if (p->set_state (n, Stateful::loading_state_version)) {
1770                                         return;
1771                                 }
1772
1773                         } else {
1774                                 /* XXX its a bit limiting to assume that everything else
1775                                    is a plugin.
1776                                 */
1777
1778                                 p.reset (new PluginInsert (*_session));
1779                                 p->set_state (**niter, Stateful::current_state_version);
1780                         }
1781
1782                         copies.push_back (p);
1783                 }
1784
1785                 catch (...) {
1786                         cerr << "plugin insert constructor failed\n";
1787                 }
1788         }
1789
1790         if (copies.empty()) {
1791                 return;
1792         }
1793
1794         if (_route->add_processors (copies, p)) {
1795
1796                 string msg = _(
1797                         "Copying the set of processors on the clipboard failed,\n\
1798 probably because the I/O configuration of the plugins\n\
1799 could not match the configuration of this track.");
1800                 MessageDialog am (msg);
1801                 am.run ();
1802         }
1803 }
1804
1805 void
1806 ProcessorBox::activate_processor (boost::shared_ptr<Processor> r)
1807 {
1808         r->activate ();
1809 }
1810
1811 void
1812 ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
1813 {
1814         r->deactivate ();
1815 }
1816
1817 void
1818 ProcessorBox::get_selected_processors (ProcSelection& processors) const
1819 {
1820         const list<ProcessorEntry*> selection = processor_display.selection ();
1821         for (list<ProcessorEntry*>::const_iterator i = selection.begin(); i != selection.end(); ++i) {
1822                 processors.push_back ((*i)->processor ());
1823         }
1824 }
1825
1826 void
1827 ProcessorBox::for_selected_processors (void (ProcessorBox::*method)(boost::shared_ptr<Processor>))
1828 {
1829         list<ProcessorEntry*> selection = processor_display.selection ();
1830         for (list<ProcessorEntry*>::iterator i = selection.begin(); i != selection.end(); ++i) {
1831                 (this->*method) ((*i)->processor ());
1832         }
1833 }
1834
1835 void
1836 ProcessorBox::all_visible_processors_active (bool state)
1837 {
1838         _route->all_visible_processors_active (state);
1839 }
1840
1841 void
1842 ProcessorBox::ab_plugins ()
1843 {
1844         _route->ab_plugins (ab_direction);
1845         ab_direction = !ab_direction;
1846 }
1847
1848
1849 void
1850 ProcessorBox::clear_processors ()
1851 {
1852         string prompt;
1853         vector<string> choices;
1854
1855         prompt = string_compose (_("Do you really want to remove all processors from %1?\n"
1856                                    "(this cannot be undone)"), _route->name());
1857
1858         choices.push_back (_("Cancel"));
1859         choices.push_back (_("Yes, remove them all"));
1860
1861         Gtkmm2ext::Choice prompter (_("Remove processors"), prompt, choices);
1862
1863         if (prompter.run () == 1) {
1864                 _route->clear_processors (PreFader);
1865                 _route->clear_processors (PostFader);
1866         }
1867 }
1868
1869 void
1870 ProcessorBox::clear_processors (Placement p)
1871 {
1872         string prompt;
1873         vector<string> choices;
1874
1875         if (p == PreFader) {
1876                 prompt = string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1877                                            "(this cannot be undone)"), _route->name());
1878         } else {
1879                 prompt = string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1880                                            "(this cannot be undone)"), _route->name());
1881         }
1882
1883         choices.push_back (_("Cancel"));
1884         choices.push_back (_("Yes, remove them all"));
1885
1886         Gtkmm2ext::Choice prompter (_("Remove processors"), prompt, choices);
1887
1888         if (prompter.run () == 1) {
1889                 _route->clear_processors (p);
1890         }
1891 }
1892
1893 bool
1894 ProcessorBox::processor_can_be_edited (boost::shared_ptr<Processor> processor)
1895 {
1896         boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack> (_route);
1897         if (at && at->freeze_state() == AudioTrack::Frozen) {
1898                 return false;
1899         }
1900
1901         if (
1902                 (boost::dynamic_pointer_cast<Send> (processor) && !boost::dynamic_pointer_cast<InternalSend> (processor))||
1903                 boost::dynamic_pointer_cast<Return> (processor) ||
1904                 boost::dynamic_pointer_cast<PluginInsert> (processor) ||
1905                 boost::dynamic_pointer_cast<PortInsert> (processor)
1906                 ) {
1907                 return true;
1908         }
1909
1910         return false;
1911 }
1912
1913 bool
1914 ProcessorBox::one_processor_can_be_edited ()
1915 {
1916         list<ProcessorEntry*> selection = processor_display.selection ();
1917         list<ProcessorEntry*>::iterator i = selection.begin();
1918         while (i != selection.end() && processor_can_be_edited ((*i)->processor()) == false) {
1919                 ++i;
1920         }
1921
1922         return (i != selection.end());
1923 }
1924
1925 void
1926 ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor)
1927 {
1928         boost::shared_ptr<Send> send;
1929         boost::shared_ptr<InternalSend> internal_send;
1930         boost::shared_ptr<Return> retrn;
1931         boost::shared_ptr<PluginInsert> plugin_insert;
1932         boost::shared_ptr<PortInsert> port_insert;
1933         Window* gidget = 0;
1934
1935         if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
1936
1937                 if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) {
1938                         return;
1939                 }
1940         }
1941
1942         if (boost::dynamic_pointer_cast<Amp> (processor)) {
1943
1944                 if (_parent_strip) {
1945                         _parent_strip->revert_to_default_display ();
1946                 }
1947
1948         } else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
1949
1950                 if (!_session->engine().connected()) {
1951                         return;
1952                 }
1953
1954                 if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
1955                         SendUIWindow* w = new SendUIWindow (send, _session);
1956                         w->show ();
1957                 } else {
1958                         /* assign internal send to main fader */
1959                         if (_parent_strip) {
1960                                 if (_parent_strip->current_delivery() == send) {
1961                                         _parent_strip->revert_to_default_display ();
1962                                 } else {
1963                                         _parent_strip->show_send(send);
1964                                 }
1965                         } 
1966                 }
1967
1968         } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
1969
1970                 if (boost::dynamic_pointer_cast<InternalReturn> (retrn)) {
1971                         /* no GUI for these */
1972                         return;
1973                 }
1974
1975                 if (!_session->engine().connected()) {
1976                         return;
1977                 }
1978
1979                 boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor);
1980
1981                 ReturnUIWindow *return_ui;
1982                 Window* w = get_processor_ui (retrn);
1983
1984                 if (w == 0) {
1985
1986                         return_ui = new ReturnUIWindow (retrn, _session);
1987                         return_ui->set_title (retrn->name ());
1988                         set_processor_ui (send, return_ui);
1989
1990                 } else {
1991                         return_ui = dynamic_cast<ReturnUIWindow *> (w);
1992                 }
1993
1994                 gidget = return_ui;
1995
1996         } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
1997
1998                 PluginUIWindow *plugin_ui;
1999
2000                 /* these are both allowed to be null */
2001
2002                 Container* toplevel = get_toplevel();
2003                 Window* win = dynamic_cast<Gtk::Window*>(toplevel);
2004
2005                 Window* w = get_processor_ui (plugin_insert);
2006
2007                 if (w == 0) {
2008
2009                         plugin_ui = new PluginUIWindow (win, plugin_insert);
2010                         plugin_ui->set_title (generate_processor_title (plugin_insert));
2011                         set_processor_ui (plugin_insert, plugin_ui);
2012
2013                 } else {
2014                         plugin_ui = dynamic_cast<PluginUIWindow *> (w);
2015                         plugin_ui->set_parent (win);
2016                 }
2017
2018                 gidget = plugin_ui;
2019
2020         } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
2021
2022                 if (!_session->engine().connected()) {
2023                         MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible"));
2024                         msg.run ();
2025                         return;
2026                 }
2027
2028                 PortInsertWindow *io_selector;
2029
2030                 Window* w = get_processor_ui (port_insert);
2031
2032                 if (w == 0) {
2033                         io_selector = new PortInsertWindow (_session, port_insert);
2034                         set_processor_ui (port_insert, io_selector);
2035
2036                 } else {
2037                         io_selector = dynamic_cast<PortInsertWindow *> (w);
2038                 }
2039
2040                 gidget = io_selector;
2041         }
2042
2043         if (gidget) {
2044                 if (gidget->is_visible()) {
2045                         gidget->hide ();
2046                 } else {
2047                         gidget->show_all ();
2048                         gidget->present ();
2049                 }
2050         }
2051 }
2052
2053 void
2054 ProcessorBox::register_actions ()
2055 {
2056         Glib::RefPtr<Gtk::ActionGroup> popup_act_grp = Gtk::ActionGroup::create(X_("ProcessorMenu"));
2057         Glib::RefPtr<Action> act;
2058
2059         /* new stuff */
2060         ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin"),
2061                         sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
2062
2063         act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"),
2064                         sigc::ptr_fun (ProcessorBox::rb_choose_insert));
2065         ActionManager::jack_sensitive_actions.push_back (act);
2066         act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New External Send ..."),
2067                         sigc::ptr_fun (ProcessorBox::rb_choose_send));
2068         ActionManager::jack_sensitive_actions.push_back (act);
2069
2070         ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ..."));
2071
2072         ActionManager::register_action (popup_act_grp, X_("controls"), _("Controls"));
2073
2074         ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear (all)"),
2075                         sigc::ptr_fun (ProcessorBox::rb_clear));
2076         ActionManager::register_action (popup_act_grp, X_("clear_pre"), _("Clear (pre-fader)"),
2077                         sigc::ptr_fun (ProcessorBox::rb_clear_pre));
2078         ActionManager::register_action (popup_act_grp, X_("clear_post"), _("Clear (post-fader)"),
2079                         sigc::ptr_fun (ProcessorBox::rb_clear_post));
2080
2081         /* standard editing stuff */
2082         cut_action = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"),
2083                                                      sigc::ptr_fun (ProcessorBox::rb_cut));
2084         ActionManager::plugin_selection_sensitive_actions.push_back(cut_action);
2085         act = ActionManager::register_action (popup_act_grp, X_("copy"), _("Copy"),
2086                         sigc::ptr_fun (ProcessorBox::rb_copy));
2087         ActionManager::plugin_selection_sensitive_actions.push_back(act);
2088
2089         act = ActionManager::register_action (popup_act_grp, X_("delete"), _("Delete"),
2090                         sigc::ptr_fun (ProcessorBox::rb_delete));
2091         ActionManager::plugin_selection_sensitive_actions.push_back(act); // ??
2092
2093         paste_action = ActionManager::register_action (popup_act_grp, X_("paste"), _("Paste"),
2094                         sigc::ptr_fun (ProcessorBox::rb_paste));
2095         rename_action = ActionManager::register_action (popup_act_grp, X_("rename"), _("Rename"),
2096                         sigc::ptr_fun (ProcessorBox::rb_rename));
2097         ActionManager::register_action (popup_act_grp, X_("selectall"), _("Select All"),
2098                         sigc::ptr_fun (ProcessorBox::rb_select_all));
2099         ActionManager::register_action (popup_act_grp, X_("deselectall"), _("Deselect All"),
2100                         sigc::ptr_fun (ProcessorBox::rb_deselect_all));
2101
2102         /* activation etc. */
2103
2104         ActionManager::register_action (popup_act_grp, X_("activate_all"), _("Activate All"),
2105                         sigc::ptr_fun (ProcessorBox::rb_activate_all));
2106         ActionManager::register_action (popup_act_grp, X_("deactivate_all"), _("Deactivate All"),
2107                         sigc::ptr_fun (ProcessorBox::rb_deactivate_all));
2108         ActionManager::register_action (popup_act_grp, X_("ab_plugins"), _("A/B Plugins"),
2109                         sigc::ptr_fun (ProcessorBox::rb_ab_plugins));
2110
2111         /* show editors */
2112         edit_action = ActionManager::register_action (
2113                 popup_act_grp, X_("edit"), _("Edit..."),
2114                 sigc::ptr_fun (ProcessorBox::rb_edit));
2115
2116         ActionManager::add_action_group (popup_act_grp);
2117 }
2118
2119 void
2120 ProcessorBox::rb_ab_plugins ()
2121 {
2122         if (_current_processor_box == 0) {
2123                 return;
2124         }
2125
2126         _current_processor_box->ab_plugins ();
2127 }
2128
2129 void
2130 ProcessorBox::rb_choose_plugin ()
2131 {
2132         if (_current_processor_box == 0) {
2133                 return;
2134         }
2135         _current_processor_box->choose_plugin ();
2136 }
2137
2138 void
2139 ProcessorBox::rb_choose_insert ()
2140 {
2141         if (_current_processor_box == 0) {
2142                 return;
2143         }
2144         _current_processor_box->choose_insert ();
2145 }
2146
2147 void
2148 ProcessorBox::rb_choose_send ()
2149 {
2150         if (_current_processor_box == 0) {
2151                 return;
2152         }
2153         _current_processor_box->choose_send ();
2154 }
2155
2156 void
2157 ProcessorBox::rb_choose_aux (boost::weak_ptr<Route> wr)
2158 {
2159         if (_current_processor_box == 0) {
2160                 return;
2161         }
2162
2163         _current_processor_box->choose_aux (wr);
2164 }
2165
2166 void
2167 ProcessorBox::rb_clear ()
2168 {
2169         if (_current_processor_box == 0) {
2170                 return;
2171         }
2172
2173         _current_processor_box->clear_processors ();
2174 }
2175
2176
2177 void
2178 ProcessorBox::rb_clear_pre ()
2179 {
2180         if (_current_processor_box == 0) {
2181                 return;
2182         }
2183
2184         _current_processor_box->clear_processors (PreFader);
2185 }
2186
2187
2188 void
2189 ProcessorBox::rb_clear_post ()
2190 {
2191         if (_current_processor_box == 0) {
2192                 return;
2193         }
2194
2195         _current_processor_box->clear_processors (PostFader);
2196 }
2197
2198 void
2199 ProcessorBox::rb_cut ()
2200 {
2201         if (_current_processor_box == 0) {
2202                 return;
2203         }
2204
2205         _current_processor_box->processor_operation (ProcessorsCut);
2206 }
2207
2208 void
2209 ProcessorBox::rb_delete ()
2210 {
2211         if (_current_processor_box == 0) {
2212                 return;
2213         }
2214
2215         _current_processor_box->processor_operation (ProcessorsDelete);
2216 }
2217
2218 void
2219 ProcessorBox::rb_copy ()
2220 {
2221         if (_current_processor_box == 0) {
2222                 return;
2223         }
2224         _current_processor_box->processor_operation (ProcessorsCopy);
2225 }
2226
2227 void
2228 ProcessorBox::rb_paste ()
2229 {
2230         if (_current_processor_box == 0) {
2231                 return;
2232         }
2233
2234         _current_processor_box->processor_operation (ProcessorsPaste);
2235 }
2236
2237 void
2238 ProcessorBox::rb_rename ()
2239 {
2240         if (_current_processor_box == 0) {
2241                 return;
2242         }
2243         _current_processor_box->rename_processors ();
2244 }
2245
2246 void
2247 ProcessorBox::rb_select_all ()
2248 {
2249         if (_current_processor_box == 0) {
2250                 return;
2251         }
2252
2253         _current_processor_box->processor_operation (ProcessorsSelectAll);
2254 }
2255
2256 void
2257 ProcessorBox::rb_deselect_all ()
2258 {
2259         if (_current_processor_box == 0) {
2260                 return;
2261         }
2262
2263         _current_processor_box->deselect_all_processors ();
2264 }
2265
2266 void
2267 ProcessorBox::rb_activate_all ()
2268 {
2269         if (_current_processor_box == 0) {
2270                 return;
2271         }
2272
2273         _current_processor_box->all_visible_processors_active (true);
2274 }
2275
2276 void
2277 ProcessorBox::rb_deactivate_all ()
2278 {
2279         if (_current_processor_box == 0) {
2280                 return;
2281         }
2282         _current_processor_box->all_visible_processors_active (false);
2283 }
2284
2285 void
2286 ProcessorBox::rb_edit ()
2287 {
2288         if (_current_processor_box == 0) {
2289                 return;
2290         }
2291
2292         _current_processor_box->for_selected_processors (&ProcessorBox::toggle_edit_processor);
2293 }
2294
2295 void
2296 ProcessorBox::route_property_changed (const PropertyChange& what_changed)
2297 {
2298         if (!what_changed.contains (ARDOUR::Properties::name)) {
2299                 return;
2300         }
2301
2302         ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed, what_changed);
2303
2304         boost::shared_ptr<Processor> processor;
2305         boost::shared_ptr<PluginInsert> plugin_insert;
2306         boost::shared_ptr<Send> send;
2307
2308         list<ProcessorEntry*> children = processor_display.children();
2309
2310         for (list<ProcessorEntry*>::iterator iter = children.begin(); iter != children.end(); ++iter) {
2311
2312                 processor = (*iter)->processor ();
2313
2314                 if (!processor) {
2315                         continue;
2316                 }
2317
2318                 Window* w = get_processor_ui (processor);
2319
2320                 if (!w) {
2321                         continue;
2322                 }
2323
2324                 /* rename editor windows for sends and plugins */
2325
2326                 if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
2327                         w->set_title (send->name ());
2328                 } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
2329                         w->set_title (generate_processor_title (plugin_insert));
2330                 }
2331         }
2332 }
2333
2334 string
2335 ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
2336 {
2337         string maker = pi->plugin()->maker() ? pi->plugin()->maker() : "";
2338         string::size_type email_pos;
2339
2340         if ((email_pos = maker.find_first_of ('<')) != string::npos) {
2341                 maker = maker.substr (0, email_pos - 1);
2342         }
2343
2344         if (maker.length() > 32) {
2345                 maker = maker.substr (0, 32);
2346                 maker += " ...";
2347         }
2348
2349         return string_compose(_("%1: %2 (by %3)"), _route->name(), pi->name(), maker);
2350 }
2351
2352 void
2353 ProcessorBox::on_size_allocate (Allocation& a)
2354 {
2355         HBox::on_size_allocate (a);
2356
2357         list<ProcessorEntry*> children = processor_display.children ();
2358         for (list<ProcessorEntry*>::const_iterator i = children.begin(); i != children.end(); ++i) {
2359                 (*i)->set_pixel_width (a.get_width ());
2360         }
2361 }
2362
2363 /** @param p Processor.
2364  *  @return the UI window for \a p.
2365  */
2366 Window *
2367 ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const
2368 {
2369         list<ProcessorWindowProxy*>::const_iterator i = _processor_window_proxies.begin ();
2370         while (i != _processor_window_proxies.end()) {
2371                 boost::shared_ptr<Processor> t = (*i)->processor().lock ();
2372                 if (t && t == p) {
2373                         return (*i)->get ();
2374                 }
2375
2376                 ++i;
2377         }
2378
2379         return 0;
2380 }
2381
2382 /** Make a note of the UI window that a processor is using.
2383  *  @param p Processor.
2384  *  @param w UI window.
2385  */
2386 void
2387 ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w)
2388 {
2389         list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin ();
2390
2391         p->set_ui (w);
2392
2393         while (i != _processor_window_proxies.end()) {
2394                 boost::shared_ptr<Processor> t = (*i)->processor().lock ();
2395                 if (t && t == p) {
2396                         (*i)->set (w);
2397                         return;
2398                 }
2399
2400                 ++i;
2401         }
2402
2403         /* we shouldn't get here, because the ProcessorUIList should always contain
2404            an entry for each processor.
2405         */
2406         assert (false);
2407 }
2408
2409 void
2410 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr<Delivery> w)
2411 {
2412         boost::shared_ptr<Delivery> d = w.lock ();
2413         if (!d) {
2414                 return;
2415         }
2416
2417         list<ProcessorEntry*> children = processor_display.children ();
2418         list<ProcessorEntry*>::const_iterator i = children.begin();
2419         while (i != children.end() && (*i)->processor() != d) {
2420                 ++i;
2421         }
2422
2423         if (i == children.end()) {
2424                 processor_display.set_active (0);
2425         } else {
2426                 processor_display.set_active (*i);
2427         }
2428 }
2429
2430 /** Called to repair the damage of Editor::show_window doing a show_all() */
2431 void
2432 ProcessorBox::hide_things ()
2433 {
2434         list<ProcessorEntry*> c = processor_display.children ();
2435         for (list<ProcessorEntry*>::iterator i = c.begin(); i != c.end(); ++i) {
2436                 (*i)->hide_things ();
2437         }
2438 }
2439
2440 void
2441 ProcessorBox::processor_menu_unmapped ()
2442 {
2443         processor_display.remove_placeholder ();
2444 }
2445
2446 Menu *
2447 ProcessorBox::build_controls_menu (boost::shared_ptr<Processor> p)
2448 {
2449         using namespace Menu_Helpers;
2450         Menu* menu = manage (new Menu);
2451         MenuList& items = menu->items ();
2452
2453         items.push_back (
2454                 MenuElem (_("Show All Controls"), sigc::bind (sigc::mem_fun (*this, &ProcessorBox::show_or_hide_all_controls), boost::weak_ptr<Processor> (p), true)
2455                         ));
2456         
2457         items.push_back (
2458                 MenuElem (_("Hide All Controls"), sigc::bind (sigc::mem_fun (*this, &ProcessorBox::show_or_hide_all_controls), boost::weak_ptr<Processor> (p), false)
2459                         ));
2460
2461         return menu;
2462 }
2463
2464 void
2465 ProcessorBox::show_or_hide_all_controls (boost::weak_ptr<Processor> w, bool show)
2466 {
2467         boost::shared_ptr<Processor> p (w.lock ());
2468         if (!p) {
2469                 return;
2470         }
2471
2472         list<ProcessorEntry*> processors = processor_display.children ();
2473         list<ProcessorEntry*>::iterator i = processors.begin();
2474         while (i != processors.end () && (*i)->processor() != p) {
2475                 ++i;
2476         }
2477
2478         if (i == processors.end ()) {
2479                 return;
2480         }
2481
2482         if (show) {
2483                 (*i)->show_all_controls ();
2484         } else {
2485                 (*i)->hide_all_controls ();
2486         }
2487
2488         update_gui_object_state (*i);
2489 }
2490
2491 XMLNode *
2492 ProcessorBox::entry_gui_object_state (ProcessorEntry* entry)
2493 {
2494         if (!_parent_strip) {
2495                 return 0;
2496         }
2497
2498         GUIObjectState& st = _parent_strip->gui_object_state ();
2499         
2500         XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
2501         assert (strip);
2502         return st.get_or_add_node (strip, entry->state_id());
2503 }
2504
2505 void
2506 ProcessorBox::update_gui_object_state (ProcessorEntry* entry)
2507 {
2508         XMLNode* proc = entry_gui_object_state (entry);
2509         if (!proc) {
2510                 return;
2511         }
2512
2513         /* XXX: this is a bit inefficient; we just remove all child nodes and re-add them */
2514         proc->remove_nodes_and_delete (X_("Object"));
2515         entry->add_control_state (proc);
2516 }
2517
2518 ProcessorWindowProxy::ProcessorWindowProxy (
2519         string const & name,
2520         XMLNode const * node,
2521         ProcessorBox* box,
2522         boost::weak_ptr<Processor> processor
2523         )
2524         : WindowProxy<Gtk::Window> (name, node)
2525         , marked (false)
2526         , _processor_box (box)
2527         , _processor (processor)
2528 {
2529
2530 }
2531
2532
2533 void
2534 ProcessorWindowProxy::show ()
2535 {
2536         boost::shared_ptr<Processor> p = _processor.lock ();
2537         if (!p) {
2538                 return;
2539         }
2540
2541         _processor_box->toggle_edit_processor (p);
2542 }
2543