Prevent adding aux-sends to master or monitor
[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 <glibmm/miscutils.h>
31 #include <glibmm/fileutils.h>
32
33 #include <gtkmm/messagedialog.h>
34
35 #include "gtkmm2ext/colors.h"
36 #include "gtkmm2ext/gtk_ui.h"
37 #include "gtkmm2ext/menu_elems.h"
38 #include "gtkmm2ext/utils.h"
39 #include "gtkmm2ext/doi.h"
40 #include "gtkmm2ext/rgb_macros.h"
41
42 #include "widgets/choice.h"
43 #include "widgets/prompter.h"
44 #include "widgets/tooltips.h"
45
46 #include "ardour/amp.h"
47 #include "ardour/audio_track.h"
48 #include "ardour/audioengine.h"
49 #include "ardour/internal_return.h"
50 #include "ardour/internal_send.h"
51 #include "ardour/luaproc.h"
52 #include "ardour/luascripting.h"
53 #include "ardour/meter.h"
54 #include "ardour/panner_shell.h"
55 #include "ardour/plugin_insert.h"
56 #include "ardour/pannable.h"
57 #include "ardour/port_insert.h"
58 #include "ardour/profile.h"
59 #include "ardour/return.h"
60 #include "ardour/route.h"
61 #include "ardour/send.h"
62 #include "ardour/session.h"
63 #include "ardour/types.h"
64 #include "ardour/value_as_string.h"
65
66 #include "LuaBridge/LuaBridge.h"
67
68 #include "actions.h"
69 #include "ardour_dialog.h"
70 #include "ardour_ui.h"
71 #include "gui_thread.h"
72 #include "io_selector.h"
73 #include "keyboard.h"
74 #include "luainstance.h"
75 #include "mixer_ui.h"
76 #include "mixer_strip.h"
77 #include "plugin_pin_dialog.h"
78 #include "plugin_selector.h"
79 #include "plugin_ui.h"
80 #include "port_insert_ui.h"
81 #include "processor_box.h"
82 #include "processor_selection.h"
83 #include "public_editor.h"
84 #include "return_ui.h"
85 #include "script_selector.h"
86 #include "send_ui.h"
87 #include "timers.h"
88 #include "new_plugin_preset_dialog.h"
89
90 #include "pbd/i18n.h"
91
92 #ifdef AUDIOUNIT_SUPPORT
93 class AUPluginUI;
94 #endif
95
96 #ifndef NDEBUG
97 bool ProcessorBox::show_all_processors = false;
98 #endif
99
100 using namespace std;
101 using namespace ARDOUR;
102 using namespace PBD;
103 using namespace Gtk;
104 using namespace Glib;
105 using namespace Gtkmm2ext;
106 using namespace ArdourWidgets;
107
108 ProcessorBox*  ProcessorBox::_current_processor_box = 0;
109 RefPtr<Action> ProcessorBox::paste_action;
110 RefPtr<Action> ProcessorBox::cut_action;
111 RefPtr<Action> ProcessorBox::copy_action;
112 RefPtr<Action> ProcessorBox::rename_action;
113 RefPtr<Action> ProcessorBox::delete_action;
114 RefPtr<Action> ProcessorBox::backspace_action;
115 RefPtr<Action> ProcessorBox::manage_pins_action;
116 RefPtr<Action> ProcessorBox::disk_io_action;
117 RefPtr<Action> ProcessorBox::edit_action;
118 RefPtr<Action> ProcessorBox::edit_generic_action;
119 RefPtr<ActionGroup> ProcessorBox::processor_box_actions;
120 Gtkmm2ext::ActionMap ProcessorBox::myactions (X_("processor box"));
121 Gtkmm2ext::Bindings* ProcessorBox::bindings = 0;
122
123
124 // TODO consolidate with PluginPinDialog::set_color
125 static void set_routing_color (cairo_t* cr, bool midi)
126 {
127         static const uint32_t audio_port_color = 0x4A8A0EFF; // Green
128         static const uint32_t midi_port_color = 0x960909FF; //Red
129
130         if (midi) {
131                 cairo_set_source_rgb (cr,
132                                 UINT_RGBA_R_FLT(midi_port_color),
133                                 UINT_RGBA_G_FLT(midi_port_color),
134                                 UINT_RGBA_B_FLT(midi_port_color));
135         } else {
136                 cairo_set_source_rgb (cr,
137                                 UINT_RGBA_R_FLT(audio_port_color),
138                                 UINT_RGBA_G_FLT(audio_port_color),
139                                 UINT_RGBA_B_FLT(audio_port_color));
140         }
141 }
142
143 ProcessorEntry::ProcessorEntry (ProcessorBox* parent, boost::shared_ptr<Processor> p, Width w)
144         : _button (ArdourButton::led_default_elements)
145         , _position (PreFader)
146         , _position_num(0)
147         , _parent (parent)
148         , _selectable(true)
149         , _unknown_processor(false)
150         , _processor (p)
151         , _width (w)
152         , input_icon(true)
153         , output_icon(false)
154         , routing_icon(true)
155         , output_routing_icon(false)
156         , _plugin_display(0)
157 {
158         _vbox.show ();
159
160         _button.set_distinct_led_click (true);
161         _button.set_fallthrough_to_parent(true);
162         _button.set_led_left (true);
163         _button.signal_led_clicked.connect (sigc::mem_fun (*this, &ProcessorEntry::led_clicked));
164         _button.set_text (name (_width));
165
166         if (boost::dynamic_pointer_cast<PeakMeter> (_processor)) {
167                 _button.set_elements(ArdourButton::Element(_button.elements() & ~ArdourButton::Indicator));
168         }
169         if (boost::dynamic_pointer_cast<UnknownProcessor> (_processor)) {
170                 _button.set_elements(ArdourButton::Element(_button.elements() & ~ArdourButton::Indicator));
171                 _unknown_processor = true;
172         }
173         {
174                 boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
175                 if (pi && pi->plugin()) {
176                         _plugin_preset_pointer = PluginPresetPtr (new PluginPreset (pi->plugin()->get_info()));
177                 }
178         }
179         if (_processor) {
180
181                 _vbox.pack_start (routing_icon);
182                 _vbox.pack_start (input_icon);
183                 _vbox.pack_start (_button, true, true);
184
185                 boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
186                 if (pi && pi->plugin() && pi->plugin()->has_inline_display()) {
187                         if (pi->plugin()->get_info()->type != ARDOUR::Lua) {
188                                 _plugin_display = new PluginInlineDisplay (*this, pi->plugin(),
189                                                 std::max (60.f, rintf(112.f * UIConfiguration::instance().get_ui_scale())));
190                         } else {
191                                 assert (boost::dynamic_pointer_cast<LuaProc>(pi->plugin()));
192                                 _plugin_display = new LuaPluginDisplay (*this, boost::dynamic_pointer_cast<LuaProc>(pi->plugin()),
193                                                 std::max (60.f, rintf(112.f * UIConfiguration::instance().get_ui_scale())));
194                         }
195                         _vbox.pack_start (*_plugin_display);
196                         _plugin_display->set_no_show_all (true);
197                         if (UIConfiguration::instance().get_show_inline_display_by_default ()) {
198                                 _plugin_display->show ();
199                         }
200                 }
201                 _vbox.pack_end (output_routing_icon);
202                 _vbox.pack_end (output_icon);
203
204                 _button.set_active (_processor->enabled ());
205
206                 input_icon.set_no_show_all(true);
207                 routing_icon.set_no_show_all(true);
208                 output_icon.set_no_show_all(true);
209                 output_routing_icon.set_no_show_all(true);
210
211                 _button.show ();
212                 input_icon.hide();
213                 output_icon.show();
214                 routing_icon.hide();
215                 output_routing_icon.hide();
216
217                 _processor->ActiveChanged.connect (active_connection, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed, this), gui_context());
218                 _processor->PropertyChanged.connect (name_connection, invalidator (*this), boost::bind (&ProcessorEntry::processor_property_changed, this, _1), gui_context());
219                 _processor->ConfigurationChanged.connect (config_connection, invalidator (*this), boost::bind (&ProcessorEntry::processor_configuration_changed, this, _1, _2), gui_context());
220
221                 set<Evoral::Parameter> p = _processor->what_can_be_automated ();
222                 for (set<Evoral::Parameter>::iterator i = p.begin(); i != p.end(); ++i) {
223
224                         std::string label = _processor->describe_parameter (*i);
225
226                         if (boost::dynamic_pointer_cast<Send> (_processor)) {
227                                 label = _("Send");
228                         } else if (boost::dynamic_pointer_cast<Return> (_processor)) {
229                                 label = _("Return");
230                         }
231
232                         Control* c = new Control (_processor->automation_control (*i), label);
233
234                         _controls.push_back (c);
235
236                         if (boost::dynamic_pointer_cast<Amp> (_processor) == 0) {
237                                 /* Add non-Amp (Fader & Trim) controls to the processor box */
238                                 _vbox.pack_start (c->box);
239                         }
240                 }
241
242                 setup_tooltip ();
243                 setup_visuals ();
244         } else {
245                 _vbox.set_size_request (-1, _button.size_request().height);
246         }
247 }
248
249 ProcessorEntry::~ProcessorEntry ()
250 {
251         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
252                 delete *i;
253         }
254         delete _plugin_display;
255 }
256
257 EventBox&
258 ProcessorEntry::action_widget ()
259 {
260         return _button;
261 }
262
263 Gtk::Widget&
264 ProcessorEntry::widget ()
265 {
266         return _vbox;
267 }
268
269 string
270 ProcessorEntry::drag_text () const
271 {
272         return name (Wide);
273 }
274
275 bool
276 ProcessorEntry::can_copy_state (Gtkmm2ext::DnDVBoxChild* o) const
277 {
278         ProcessorEntry *other = dynamic_cast<ProcessorEntry*> (o);
279         if (!other) {
280                 return false;
281         }
282         boost::shared_ptr<ARDOUR::Processor> otherproc = other->processor();
283         boost::shared_ptr<PluginInsert> my_pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
284         boost::shared_ptr<PluginInsert> ot_pi = boost::dynamic_pointer_cast<PluginInsert> (otherproc);
285         if (boost::dynamic_pointer_cast<UnknownProcessor> (_processor)) {
286                 return false;
287         }
288         if (boost::dynamic_pointer_cast<UnknownProcessor> (otherproc)) {
289                 return false;
290         }
291         if (!my_pi || !ot_pi) {
292                 return false;
293         }
294         if (my_pi->type() != ot_pi->type()) {
295                 return false;
296         }
297         boost::shared_ptr<Plugin> my_p = my_pi->plugin();
298         boost::shared_ptr<Plugin> ot_p = ot_pi->plugin();
299         if (!my_p || !ot_p) {
300                 return false;
301         }
302         if (my_p->unique_id() != ot_p->unique_id()) {
303                 return false;
304         }
305         return true;
306 }
307
308 bool
309 ProcessorEntry::drag_data_get (Glib::RefPtr<Gdk::DragContext> const, Gtk::SelectionData &data)
310 {
311         if (data.get_target() == "PluginPresetPtr") {
312                 boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
313
314                 if (!_plugin_preset_pointer || !pi) {
315                         data.set (data.get_target(), 8, NULL, 0);
316                         return true;
317                 }
318
319                 boost::shared_ptr<ARDOUR::Plugin> plugin = pi->plugin();
320                 assert (plugin);
321
322                 PluginManager& manager (PluginManager::instance());
323                 bool fav = manager.get_status (_plugin_preset_pointer->_pip) == PluginManager::Favorite;
324
325                 NewPluginPresetDialog d (plugin,
326                                 string_compose(_("New Favorite Preset for \"%1\""),_plugin_preset_pointer->_pip->name), !fav);
327
328                 _plugin_preset_pointer->_preset.valid = false;
329
330                 switch (d.run ()) {
331                         case Gtk::RESPONSE_CANCEL:
332                                 data.set (data.get_target(), 8, NULL, 0);
333                                 return true;
334                                 break;
335
336                         case Gtk::RESPONSE_NO:
337                                 break;
338
339                         case Gtk::RESPONSE_ACCEPT:
340                                 if (d.name().empty()) {
341                                         break;
342                                 }
343
344                                 if (d.replace ()) {
345                                         plugin->remove_preset (d.name ());
346                                 }
347
348                                 Plugin::PresetRecord const r = plugin->save_preset (d.name());
349
350                                 if (!r.uri.empty ()) {
351                                         _plugin_preset_pointer->_preset.uri   = r.uri;
352                                         _plugin_preset_pointer->_preset.label = r.label;
353                                         _plugin_preset_pointer->_preset.user  = r.user;
354                                         _plugin_preset_pointer->_preset.valid = r.valid;
355                                 }
356                 }
357                 data.set (data.get_target(), 8, (const guchar *) &_plugin_preset_pointer, sizeof (PluginPresetPtr));
358                 return true;
359         }
360         return false;
361 }
362
363 void
364 ProcessorEntry::set_position (Position p, uint32_t num)
365 {
366         _position = p;
367         _position_num = num;
368         setup_visuals ();
369 }
370
371 void
372 ProcessorEntry::set_visual_state (Gtkmm2ext::VisualState s, bool yn)
373 {
374         if (yn) {
375                 _button.set_visual_state (Gtkmm2ext::VisualState (_button.visual_state() | s));
376         } else {
377                 _button.set_visual_state (Gtkmm2ext::VisualState (_button.visual_state() & ~s));
378         }
379 }
380
381 void
382 ProcessorEntry::setup_visuals ()
383 {
384         if (_unknown_processor) {
385                 _button.set_name ("processor stub");
386                 return;
387         }
388         boost::shared_ptr<Send> send;
389         if ((send = boost::dynamic_pointer_cast<Send> (_processor))) {
390                 if (send->remove_on_disconnect ()) {
391                         _button.set_name ("processor sidechain");
392                         return;
393                 }
394         }
395
396         boost::shared_ptr<InternalSend> aux;
397         if ((aux = boost::dynamic_pointer_cast<InternalSend> (_processor))) {
398                 if (aux->allow_feedback ()) {
399                         _button.set_name ("processor auxfeedback");
400                         return;
401                 }
402         }
403
404         switch (_position) {
405         case PreFader:
406                 if (_plugin_display) { _plugin_display->set_name ("processor prefader"); }
407                 _button.set_name ("processor prefader");
408                 break;
409
410         case Fader:
411                 _button.set_name ("processor fader");
412                 break;
413
414         case PostFader:
415                 if (_plugin_display) { _plugin_display->set_name ("processor postfader"); }
416                 _button.set_name ("processor postfader");
417                 break;
418         }
419 }
420
421
422 boost::shared_ptr<Processor>
423 ProcessorEntry::processor () const
424 {
425         if (!_processor) {
426                 return boost::shared_ptr<Processor>();
427         }
428         return _processor;
429 }
430
431 void
432 ProcessorEntry::set_enum_width (Width w)
433 {
434         _width = w;
435         _button.set_text (name (_width));
436 }
437
438 void
439 ProcessorEntry::led_clicked(GdkEventButton *ev)
440 {
441         bool ctrl_shift_pressed = false;
442         Keyboard::ModifierMask ctrl_shift_mask = Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier);
443
444         if (Keyboard::modifier_state_equals (ev->state, ctrl_shift_mask)) {
445                 ctrl_shift_pressed = true;
446         }
447
448         if (_processor) {
449                 if (_button.get_active ()) {
450                         if (ctrl_shift_pressed) {
451                                 _parent->all_visible_processors_active(false);
452
453                                 if (_position == Fader) {
454                                         _processor->enable (false);
455                                 }
456                         }
457                         else {
458                                 _processor->enable (false);
459                         }
460
461                 } else {
462                         if (ctrl_shift_pressed) {
463                                 _parent->all_visible_processors_active(true);
464
465                                 if (_position == Fader) {
466                                         _processor->enable (true);
467                                 }
468                         }
469                         else {
470                                 _processor->enable (true);
471                         }
472                 }
473         }
474 }
475
476 void
477 ProcessorEntry::processor_active_changed ()
478 {
479         if (_processor) {
480                 _button.set_active (_processor->enabled ());
481         }
482 }
483
484 void
485 ProcessorEntry::processor_property_changed (const PropertyChange& what_changed)
486 {
487         if (what_changed.contains (ARDOUR::Properties::name)) {
488                 _button.set_text (name (_width));
489                 setup_tooltip ();
490         }
491 }
492
493 void
494 ProcessorEntry::processor_configuration_changed (const ChanCount in, const ChanCount out)
495 {
496         _parent->setup_routing_feeds ();
497         input_icon.queue_draw();
498         output_icon.queue_draw();
499         routing_icon.queue_draw();
500         output_routing_icon.queue_draw();
501 }
502
503 void
504 ProcessorEntry::setup_tooltip ()
505 {
506         if (_processor) {
507                 boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
508                 if (pi) {
509                         std::string postfix = "";
510                         uint32_t replicated;
511
512                         if (pi->plugin()->has_inline_display()) {
513                                 postfix += string_compose(_("\n%1+double-click to toggle inline-display"), Keyboard::tertiary_modifier_name ());
514                         }
515
516                         if ((replicated = pi->get_count()) > 1) {
517                                 postfix += string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
518                         }
519
520                         if (pi->plugin()->has_editor()) {
521                                 set_tooltip (_button,
522                                                 string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), name (Wide), Keyboard::secondary_modifier_name (), postfix));
523                         } else {
524                                 set_tooltip (_button,
525                                                 string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), name (Wide), postfix));
526                         }
527                         return;
528                 }
529                 if(boost::dynamic_pointer_cast<UnknownProcessor> (_processor)) {
530                         ARDOUR_UI::instance()->set_tip (_button,
531                                         string_compose (_("<b>%1</b>\nThe Plugin is not available on this system\nand has been replaced by a stub."), name (Wide)));
532                         return;
533                 }
534                 boost::shared_ptr<Send> send;
535                 if ((send = boost::dynamic_pointer_cast<Send> (_processor)) != 0 &&
536                                 !boost::dynamic_pointer_cast<InternalSend>(_processor)) {
537                         if (send->remove_on_disconnect ()) {
538                                 set_tooltip (_button, string_compose ("<b>&gt; %1</b>\nThis (sidechain) send will be removed when disconnected.", _processor->name()));
539                         } else {
540                                 set_tooltip (_button, string_compose ("<b>&gt; %1</b>", _processor->name()));
541                         }
542                         return;
543                 }
544         }
545         set_tooltip (_button, string_compose ("<b>%1</b>", name (Wide)));
546 }
547
548 string
549 ProcessorEntry::name (Width w) const
550 {
551         boost::shared_ptr<Send> send;
552         string name_display;
553
554         if (!_processor) {
555                 return string();
556         }
557
558         if ((send = boost::dynamic_pointer_cast<Send> (_processor)) != 0 &&
559             !boost::dynamic_pointer_cast<InternalSend>(_processor)) {
560
561                 name_display += '>';
562                 std::string send_name;
563                 bool pretty_ok = true;
564
565                 if (send->remove_on_disconnect ()) {
566                         // assume it's a sidechain, find pretty name of connected port(s)
567                         PortSet& ps (send->output ()->ports ());
568                         for (PortSet::iterator i = ps.begin (); i != ps.end () && pretty_ok; ++i) {
569                                 vector<string> connections;
570                                 if (i->get_connections (connections)) {
571                                         vector<string>::const_iterator ci;
572                                         for (ci = connections.begin(); ci != connections.end(); ++ci) {
573                                                 std::string pn = AudioEngine::instance()->get_pretty_name_by_name (*ci);
574                                                 if (pn.empty ()) {
575                                                         continue;
576                                                 }
577                                                 if (send_name.empty ()) {
578                                                         send_name = pn;
579                                                 } else if (send_name != pn) {
580                                                         // pretty names don't match
581                                                         pretty_ok = false;
582                                                         break;
583                                                 }
584                                         }
585                                 }
586                         }
587                 }
588
589                 if (!pretty_ok) {
590                         send_name = "";
591                 }
592
593                 /* grab the send name out of its overall name */
594                 if (send_name.empty()) {
595                         send_name = send->name();
596                         string::size_type lbracket, rbracket;
597                         lbracket = send_name.find ('[');
598                         rbracket = send_name.find (']');
599                         send_name = send_name.substr (lbracket+1, lbracket-rbracket-1);
600                 }
601
602                 switch (w) {
603                 case Wide:
604                         name_display += send_name;
605                         break;
606                 case Narrow:
607                         name_display += PBD::short_version (send_name, 5);
608                         break;
609                 }
610
611         } else {
612                 boost::shared_ptr<ARDOUR::PluginInsert> pi;
613                 uint32_t replicated;
614                 if ((pi = boost::dynamic_pointer_cast<ARDOUR::PluginInsert> (_processor)) != 0
615                                 && (replicated = pi->get_count()) > 1)
616                 {
617                         name_display += string_compose(_("(%1x1) "), replicated);
618                 }
619
620                 switch (w) {
621                 case Wide:
622                         name_display += _processor->display_name();
623                         break;
624                 case Narrow:
625                         name_display += PBD::short_version (_processor->display_name(), 5);
626                         break;
627                 }
628
629         }
630
631         return name_display;
632 }
633
634 void
635 ProcessorEntry::show_all_controls ()
636 {
637         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
638                 (*i)->set_visible (true);
639         }
640
641         _parent->update_gui_object_state (this);
642 }
643
644 void
645 ProcessorEntry::hide_all_controls ()
646 {
647         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
648                 (*i)->set_visible (false);
649         }
650
651         _parent->update_gui_object_state (this);
652 }
653
654 void
655 ProcessorEntry::add_control_state (XMLNode* node) const
656 {
657         for (list<Control*>::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
658                 (*i)->add_state (node);
659         }
660
661         if (_plugin_display) {
662                 XMLNode* c = new XMLNode (X_("Object"));
663                 c->set_property (X_("id"), X_("InlineDisplay"));
664                 c->set_property (X_("visible"), _plugin_display->is_visible ());
665                 node->add_child_nocopy (*c);
666         }
667 }
668
669 void
670 ProcessorEntry::set_control_state (XMLNode const * node)
671 {
672         for (list<Control*>::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
673                 (*i)->set_state (node);
674         }
675
676         if (_plugin_display) {
677                 XMLNode* n = GUIObjectState::get_node (node, X_("InlineDisplay"));
678                 if (!n) return;
679
680                 bool visible;
681                 if (n->get_property (X_("visible"), visible)) {
682                         if (visible) {
683                                 _plugin_display->show ();
684                         } else {
685                                 _plugin_display->hide ();
686                         }
687                 }
688         }
689 }
690
691 string
692 ProcessorEntry::state_id () const
693 {
694         return string_compose ("processor %1", _processor->id().to_s());
695 }
696
697 void
698 ProcessorEntry::hide_things ()
699 {
700         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
701                 (*i)->hide_things ();
702         }
703 }
704
705
706 Menu *
707 ProcessorEntry::build_controls_menu ()
708 {
709         using namespace Menu_Helpers;
710         Menu* menu = manage (new Menu);
711         MenuList& items = menu->items ();
712
713         if (_plugin_display) {
714                 items.push_back (CheckMenuElem (_("Inline Display")));
715                 Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
716                 c->set_active (_plugin_display->is_visible ());
717                 c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_inline_display_visibility));
718                 items.push_back (SeparatorElem ());
719         }
720
721         items.push_back (
722                 MenuElem (_("Show All Controls"), sigc::mem_fun (*this, &ProcessorEntry::show_all_controls))
723                 );
724
725         items.push_back (
726                 MenuElem (_("Hide All Controls"), sigc::mem_fun (*this, &ProcessorEntry::hide_all_controls))
727                 );
728
729         if (!_controls.empty ()) {
730                 items.push_back (SeparatorElem ());
731         }
732
733         for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
734                 items.push_back (CheckMenuElemNoMnemonic ((*i)->name ()));
735                 Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
736                 c->set_active ((*i)->visible ());
737                 c->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ProcessorEntry::toggle_control_visibility), *i));
738         }
739
740         return menu;
741 }
742
743 void
744 ProcessorEntry::toggle_inline_display_visibility ()
745 {
746         if (_plugin_display->is_visible ()) {
747                 _plugin_display->hide();
748         } else {
749                 _plugin_display->show();
750         }
751         _parent->update_gui_object_state (this);
752 }
753
754 void
755 ProcessorEntry::toggle_control_visibility (Control* c)
756 {
757         c->set_visible (!c->visible ());
758         _parent->update_gui_object_state (this);
759 }
760
761 Menu *
762 ProcessorEntry::build_send_options_menu ()
763 {
764         using namespace Menu_Helpers;
765         Menu* menu = manage (new Menu);
766         MenuList& items = menu->items ();
767
768         if (!ARDOUR::Profile->get_mixbus()) {
769                 boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
770                 if (send) {
771                         items.push_back (CheckMenuElem (_("Link panner controls")));
772                         Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
773                         c->set_active (send->panner_shell()->is_linked_to_route());
774                         c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
775                 }
776         }
777
778         boost::shared_ptr<InternalSend> aux = boost::dynamic_pointer_cast<InternalSend> (_processor);
779         if (aux) {
780                 items.push_back (CheckMenuElem (_("Allow Feedback Loop")));
781                 Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
782                 c->set_active (aux->allow_feedback());
783                 c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_allow_feedback));
784         }
785         return menu;
786 }
787
788 void
789 ProcessorEntry::toggle_panner_link ()
790 {
791         boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
792         if (send) {
793                 send->panner_shell()->set_linked_to_route(!send->panner_shell()->is_linked_to_route());
794         }
795 }
796
797 void
798 ProcessorEntry::toggle_allow_feedback ()
799 {
800         boost::shared_ptr<InternalSend> aux = boost::dynamic_pointer_cast<InternalSend> (_processor);
801         if (aux) {
802                 aux->set_allow_feedback (!aux->allow_feedback ());
803         }
804 }
805
806 ProcessorEntry::Control::Control (boost::shared_ptr<AutomationControl> c, string const & n)
807         : _control (c)
808         , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
809         , _slider (&_adjustment, boost::shared_ptr<PBD::Controllable>(), 0, max(13.f, rintf(13.f * UIConfiguration::instance().get_ui_scale())))
810         , _slider_persistant_tooltip (&_slider)
811         , _button (ArdourButton::led_default_elements)
812         , _ignore_ui_adjustment (false)
813         , _visible (false)
814         , _name (n)
815 {
816         _slider.set_controllable (c);
817         box.set_padding(0, 0, 4, 4);
818
819         if (c->toggled()) {
820                 _button.set_text (_name);
821                 _button.set_led_left (true);
822                 _button.set_name ("processor control button");
823                 box.add (_button);
824                 _button.show ();
825
826                 _button.signal_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked));
827                 _button.signal_led_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked_event));
828                 c->Changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_changed, this), gui_context ());
829                 if (c->alist ()) {
830                         c->alist()->automation_state_changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_automation_state_changed, this), gui_context());
831                         control_automation_state_changed ();
832                 }
833
834         } else {
835
836                 _slider.set_name ("ProcessorControlSlider");
837                 _slider.set_text (_name);
838
839                 box.add (_slider);
840                 _slider.show ();
841
842                 const ARDOUR::ParameterDescriptor& desc = c->desc();
843                 double const lo        = c->internal_to_interface (desc.lower);
844                 double const up        = c->internal_to_interface (desc.upper);
845                 double const normal    = c->internal_to_interface (desc.normal);
846                 double const smallstep = c->internal_to_interface (desc.lower + desc.smallstep);
847                 double const largestep = c->internal_to_interface (desc.lower + desc.largestep);
848
849                 _adjustment.set_lower (lo);
850                 _adjustment.set_upper (up);
851                 _adjustment.set_step_increment (smallstep);
852                 _adjustment.set_page_increment (largestep);
853                 _slider.set_default_value (normal);
854
855                 _slider.StartGesture.connect(sigc::mem_fun(*this, &Control::start_touch));
856                 _slider.StopGesture.connect(sigc::mem_fun(*this, &Control::end_touch));
857
858                 _adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &Control::slider_adjusted));
859                 c->Changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_changed, this), gui_context ());
860                 if (c->alist ()) {
861                         c->alist()->automation_state_changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_automation_state_changed, this), gui_context());
862                         control_automation_state_changed ();
863                 }
864         }
865
866         control_changed ();
867         set_tooltip ();
868
869         /* We're providing our own PersistentTooltip */
870         set_no_tooltip_whatsoever (_slider);
871 }
872
873 ProcessorEntry::Control::~Control ()
874 {
875 }
876
877 void
878 ProcessorEntry::Control::set_tooltip ()
879 {
880         boost::shared_ptr<AutomationControl> c = _control.lock ();
881
882         if (!c) {
883                 return;
884         }
885         std::string tt = _name + ": " + ARDOUR::value_as_string (c->desc(), c->get_value ());
886         string sm = Gtkmm2ext::markup_escape_text (tt);
887         _slider_persistant_tooltip.set_tip (sm);
888         ArdourWidgets::set_tooltip (_button, Gtkmm2ext::markup_escape_text (sm));
889 }
890
891 void
892 ProcessorEntry::Control::slider_adjusted ()
893 {
894         if (_ignore_ui_adjustment) {
895                 return;
896         }
897
898         boost::shared_ptr<AutomationControl> c = _control.lock ();
899
900         if (!c) {
901                 return;
902         }
903
904         c->set_value ( c->interface_to_internal(_adjustment.get_value ()) , Controllable::NoGroup);
905         set_tooltip ();
906 }
907
908 void
909 ProcessorEntry::Control::start_touch ()
910 {
911         boost::shared_ptr<AutomationControl> c = _control.lock ();
912         if (!c) {
913                 return;
914         }
915         c->start_touch (c->session().transport_sample());
916 }
917
918 void
919 ProcessorEntry::Control::end_touch ()
920 {
921         boost::shared_ptr<AutomationControl> c = _control.lock ();
922         if (!c) {
923                 return;
924         }
925         c->stop_touch (c->session().transport_sample());
926 }
927
928 void
929 ProcessorEntry::Control::button_clicked ()
930 {
931         boost::shared_ptr<AutomationControl> c = _control.lock ();
932
933         if (!c) {
934                 return;
935         }
936
937         bool const n = _button.get_active ();
938
939         c->set_value (n ? 0 : 1, Controllable::NoGroup);
940         _button.set_active (!n);
941         set_tooltip ();
942 }
943
944 void
945 ProcessorEntry::Control::button_clicked_event (GdkEventButton *ev)
946 {
947         (void) ev;
948
949         button_clicked ();
950 }
951
952 void
953 ProcessorEntry::Control::control_automation_state_changed ()
954 {
955         boost::shared_ptr<AutomationControl> c = _control.lock ();
956         if (!c) {
957                 return;
958         }
959         bool x = c->alist()->automation_state() & Play;
960         if (c->toggled ()) {
961                 _button.set_sensitive (!x);
962         } else {
963                 _slider.set_sensitive (!x);
964         }
965 }
966
967 void
968 ProcessorEntry::Control::control_changed ()
969 {
970         boost::shared_ptr<AutomationControl> c = _control.lock ();
971         if (!c) {
972                 return;
973         }
974
975         _ignore_ui_adjustment = true;
976
977         if (c->toggled ()) {
978                 _button.set_active (c->get_value() > 0.5);
979         } else {
980                 // Note: the _slider watches the controllable by itself
981                 const double nval = c->internal_to_interface (c->get_value ());
982                 if (_adjustment.get_value() != nval) {
983                         _adjustment.set_value (nval);
984                         set_tooltip ();
985                 }
986         }
987
988         _ignore_ui_adjustment = false;
989 }
990
991 void
992 ProcessorEntry::Control::add_state (XMLNode* node) const
993 {
994         XMLNode* c = new XMLNode (X_("Object"));
995         c->set_property (X_("id"), state_id ());
996         c->set_property (X_("visible"), _visible);
997         node->add_child_nocopy (*c);
998 }
999
1000 void
1001 ProcessorEntry::Control::set_state (XMLNode const * node)
1002 {
1003         XMLNode* n = GUIObjectState::get_node (node, state_id ());
1004         if (n) {
1005                 bool visible;
1006                 if (n->get_property (X_("visible"), visible)) {
1007                         set_visible (visible);
1008                 }
1009         } else {
1010                 set_visible (false);
1011         }
1012 }
1013
1014 void
1015 ProcessorEntry::Control::set_visible (bool v)
1016 {
1017         if (v) {
1018                 box.show ();
1019         } else {
1020                 box.hide ();
1021         }
1022
1023         _visible = v;
1024 }
1025
1026 /** Called when the Editor might have re-shown things that
1027     we want hidden.
1028 */
1029 void
1030 ProcessorEntry::Control::hide_things ()
1031 {
1032         if (!_visible) {
1033                 box.hide ();
1034         }
1035 }
1036
1037 string
1038 ProcessorEntry::Control::state_id () const
1039 {
1040         boost::shared_ptr<AutomationControl> c = _control.lock ();
1041         assert (c);
1042
1043         return string_compose (X_("control %1"), c->id().to_s ());
1044 }
1045
1046 PluginInsertProcessorEntry::PluginInsertProcessorEntry (ProcessorBox* b, boost::shared_ptr<ARDOUR::PluginInsert> p, Width w)
1047         : ProcessorEntry (b, p, w)
1048         , _plugin_insert (p)
1049 {
1050         p->PluginIoReConfigure.connect (
1051                 _iomap_connection, invalidator (*this), boost::bind (&PluginInsertProcessorEntry::iomap_changed, this), gui_context()
1052                 );
1053         p->PluginMapChanged.connect (
1054                 _iomap_connection, invalidator (*this), boost::bind (&PluginInsertProcessorEntry::iomap_changed, this), gui_context()
1055                 );
1056         p->PluginConfigChanged.connect (
1057                 _iomap_connection, invalidator (*this), boost::bind (&PluginInsertProcessorEntry::iomap_changed, this), gui_context()
1058                 );
1059 }
1060
1061 void
1062 PluginInsertProcessorEntry::iomap_changed ()
1063 {
1064         _parent->setup_routing_feeds ();
1065         routing_icon.queue_draw();
1066         output_routing_icon.queue_draw();
1067 }
1068
1069 void
1070 PluginInsertProcessorEntry::hide_things ()
1071 {
1072         ProcessorEntry::hide_things ();
1073 }
1074
1075 ProcessorEntry::PortIcon::PortIcon(bool input) {
1076         _input = input;
1077         _ports = ARDOUR::ChanCount(ARDOUR::DataType::AUDIO, 1);
1078         set_size_request (-1, std::max (2.f, rintf(2.f * UIConfiguration::instance().get_ui_scale())));
1079 }
1080
1081 bool
1082 ProcessorEntry::PortIcon::on_expose_event (GdkEventExpose* ev)
1083 {
1084         cairo_t* cr = gdk_cairo_create (get_window()->gobj());
1085
1086         cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
1087         cairo_clip (cr);
1088
1089         Gtk::Allocation a = get_allocation();
1090         double const width = a.get_width();
1091         double const height = a.get_height();
1092
1093         Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
1094         cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
1095
1096         cairo_rectangle (cr, 0, 0, width, height);
1097         cairo_fill (cr);
1098
1099         const double dx = rint(max(2., 2. * UIConfiguration::instance().get_ui_scale()));
1100         for (uint32_t i = 0; i < _ports.n_total(); ++i) {
1101                 set_routing_color (cr, i < _ports.n_midi());
1102                 const double x = ProcessorEntry::RoutingIcon::pin_x_pos (i, width, _ports.n_total(), 0 , false);
1103                 cairo_rectangle (cr, x - .5 - dx * .5, 0, 1 + dx, height);
1104                 cairo_fill(cr);
1105         }
1106
1107         cairo_destroy(cr);
1108         return true;
1109 }
1110
1111 ProcessorEntry::RoutingIcon::RoutingIcon (bool input)
1112         : _fed_by (false)
1113         , _input (input)
1114 {
1115         set_terminal (false);
1116 }
1117
1118 void
1119 ProcessorEntry::RoutingIcon::set_terminal (bool b) {
1120         _terminal = b;
1121         int h = std::max (8.f, rintf(8.f * sqrt (UIConfiguration::instance().get_ui_scale())));
1122         if (_terminal) {
1123                 h += std::max (4.f, rintf(4.f * sqrt (UIConfiguration::instance().get_ui_scale())));
1124         }
1125         set_size_request (-1, h);
1126 }
1127
1128 void
1129 ProcessorEntry::RoutingIcon::set (
1130                 const ARDOUR::ChanCount& in,
1131                 const ARDOUR::ChanCount& out,
1132                 const ARDOUR::ChanCount& sinks,
1133                 const ARDOUR::ChanCount& sources,
1134                 const ARDOUR::ChanMapping& in_map,
1135                 const ARDOUR::ChanMapping& out_map,
1136                 const ARDOUR::ChanMapping& thru_map)
1137 {
1138         _in       = in;
1139         _out      = out;
1140         _sources  = sources;
1141         _sinks    = sinks;
1142         _in_map   = in_map;
1143         _out_map  = out_map;
1144         _thru_map = thru_map;
1145 }
1146
1147 bool
1148 ProcessorEntry::RoutingIcon::in_identity () const {
1149         if (_thru_map.n_total () > 0) {
1150                 return false;
1151         }
1152         if (!_in_map.is_monotonic () || !_in_map.is_identity ()) {
1153                 return false;
1154         }
1155         if (_in_map.n_total () != _sinks.n_total () || _in.n_total () != _sinks.n_total ()) {
1156                 return false;
1157         }
1158         return true;
1159 }
1160
1161 bool
1162 ProcessorEntry::RoutingIcon::out_identity () const {
1163         if (_thru_map.n_total () > 0) {
1164                 // TODO skip if trhu is not connected to any of next's inputs
1165                 return false;
1166         }
1167         if (!_out_map.is_monotonic () || !_out_map.is_identity ()) {
1168                 return false;
1169         }
1170         if (_out_map.n_total () != _sources.n_total () || _out.n_total () != _sources.n_total ()) {
1171                 return false;
1172         }
1173         return true;
1174 }
1175
1176 bool
1177 ProcessorEntry::RoutingIcon::can_coalesce () const {
1178         if (_thru_map.n_total () > 0) {
1179                 return false;
1180         }
1181         if (_fed_by && _f_out != _f_sources) {
1182                 return false;
1183         }
1184         if (_fed_by && !_f_out_map.is_identity () && !_in_map.is_identity ()) {
1185                 return false;
1186         }
1187         if (_input && _sinks == _in && (!_fed_by || _f_out == _in)) {
1188                 return true;
1189         }
1190         return false;
1191 }
1192
1193 void
1194 ProcessorEntry::RoutingIcon::set_fed_by (
1195                                 const ARDOUR::ChanCount& out,
1196                                 const ARDOUR::ChanCount& sources,
1197                                 const ARDOUR::ChanMapping& out_map,
1198                                 const ARDOUR::ChanMapping& thru_map)
1199 {
1200         _f_out      = out;
1201         _f_sources  = sources;
1202         _f_out_map  = out_map;
1203         _f_thru_map = thru_map;
1204         _fed_by     = true;
1205 }
1206
1207 void
1208 ProcessorEntry::RoutingIcon::set_feeding (
1209                                 const ARDOUR::ChanCount& in,
1210                                 const ARDOUR::ChanCount& sinks,
1211                                 const ARDOUR::ChanMapping& in_map,
1212                                 const ARDOUR::ChanMapping& thru_map)
1213 {
1214         _i_in       = in;
1215         _i_sinks    = sinks;
1216         _i_in_map   = in_map;
1217         _i_thru_map = thru_map;
1218         _feeding    = true;
1219 }
1220
1221 double
1222 ProcessorEntry::RoutingIcon::pin_x_pos (uint32_t i, double width, uint32_t n_total, uint32_t n_midi, bool midi)
1223 {
1224         if (!midi) { i += n_midi; }
1225         if (n_total == 1) {
1226                 assert (i == 0);
1227                 return rint (width * .5) +.5;
1228         }
1229         return rint (width * (.15 + .7 * i / (n_total - 1))) + .5;
1230 }
1231
1232 void
1233 ProcessorEntry::RoutingIcon::draw_gnd (cairo_t* cr, double x0, double y0, double height, bool midi)
1234 {
1235         const double dx = 1 + rint (max(2., 2. * UIConfiguration::instance().get_ui_scale()));
1236         const double y1 = rint (height * .66) + .5;
1237
1238         cairo_save (cr);
1239         cairo_translate (cr, x0, y0);
1240         cairo_move_to (cr, 0, height);
1241         cairo_line_to (cr, 0, y1);
1242         cairo_move_to (cr, 0 - dx, y1);
1243         cairo_line_to (cr, 0 + dx, y1);
1244
1245         set_routing_color (cr, midi);
1246         cairo_set_line_width (cr, 1.0);
1247         cairo_stroke (cr);
1248         cairo_restore (cr);
1249 }
1250
1251 void
1252 ProcessorEntry::RoutingIcon::draw_sidechain (cairo_t* cr, double x0, double y0, double height, bool midi)
1253 {
1254         const double dx = 1 + rint (max(2., 2. * UIConfiguration::instance().get_ui_scale()));
1255         const double y1 = rint (height * .5) - .5;
1256
1257         cairo_save (cr);
1258         cairo_translate (cr, x0, y0);
1259         cairo_move_to (cr, 0 - dx, height);
1260         cairo_line_to (cr, 0, y1);
1261         cairo_line_to (cr, 0 + dx, height);
1262         cairo_close_path (cr);
1263
1264         set_routing_color (cr, midi);
1265         cairo_fill (cr);
1266         cairo_restore (cr);
1267 }
1268
1269 void
1270 ProcessorEntry::RoutingIcon::draw_thru_src (cairo_t* cr, double x0, double y0, double height, bool midi)
1271 {
1272         const double rad = 1;
1273         const double y1 = height - rad - 1.5;
1274
1275         cairo_arc (cr, x0, y0 + y1, rad, 0, 2. * M_PI);
1276         cairo_move_to (cr, x0, y0 + height - 1.5);
1277         cairo_line_to (cr, x0, y0 + height);
1278         set_routing_color (cr, midi);
1279         cairo_set_line_width  (cr, 1.0);
1280         cairo_stroke (cr);
1281 }
1282
1283 void
1284 ProcessorEntry::RoutingIcon::draw_thru_sink (cairo_t* cr, double x0, double y0, double height, bool midi)
1285 {
1286         const double rad = 1;
1287         const double y1 = rad + 1;
1288
1289         cairo_arc (cr, x0, y0 + y1, rad, 0, 2. * M_PI);
1290         cairo_move_to (cr, x0, y0);
1291         cairo_line_to (cr, x0, y0 + 1);
1292         set_routing_color (cr, midi);
1293         cairo_set_line_width  (cr, 1.0);
1294         cairo_stroke (cr);
1295 }
1296
1297 void
1298 ProcessorEntry::RoutingIcon::draw_connection (cairo_t* cr, double x0, double x1, double y0, double y1, bool midi, bool dashed)
1299 {
1300         double bz = abs (y1 - y0);
1301
1302         cairo_move_to (cr, x0, y0);
1303         cairo_curve_to (cr, x0, y0 + bz, x1, y1 - bz, x1, y1);
1304         cairo_set_line_width  (cr, 1.0);
1305         cairo_set_line_cap  (cr,  CAIRO_LINE_CAP_ROUND);
1306         cairo_set_source_rgb (cr, 1, 0, 0);
1307         if (dashed) {
1308                 const double dashes[] = { 2, 3 };
1309                 cairo_set_dash (cr, dashes, 2, 0);
1310         }
1311         set_routing_color (cr, midi);
1312         cairo_stroke (cr);
1313         if (dashed) {
1314                 cairo_set_dash (cr, 0, 0, 0);
1315         }
1316 }
1317
1318 bool
1319 ProcessorEntry::RoutingIcon::on_expose_event (GdkEventExpose* ev)
1320 {
1321         cairo_t* cr = gdk_cairo_create (get_window()->gobj());
1322
1323         cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
1324         cairo_clip (cr);
1325
1326         cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
1327
1328         Gtk::Allocation a = get_allocation();
1329         double const width = a.get_width();
1330         double const height = a.get_height();
1331
1332         Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
1333         cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
1334
1335         cairo_rectangle (cr, 0, 0, width, height);
1336         cairo_fill (cr);
1337
1338         if (_input) {
1339                 if (can_coalesce ()) {
1340                         expose_coalesced_input_map (cr, width, height);
1341                 } else {
1342                         expose_input_map (cr, width, height);
1343                 }
1344         } else {
1345                 expose_output_map (cr, width, height);
1346         }
1347
1348         cairo_destroy(cr);
1349         return true;
1350 }
1351
1352 void
1353 ProcessorEntry::RoutingIcon::expose_coalesced_input_map (cairo_t* cr, const double width, const double height)
1354 {
1355         const uint32_t pc_in = _sinks.n_total();
1356         const uint32_t pc_in_midi = _sinks.n_midi();
1357
1358         for (uint32_t i = 0; i < pc_in; ++i) {
1359                 const bool is_midi = i < pc_in_midi;
1360                 bool valid_in;
1361                 uint32_t pn = is_midi ? i : i - pc_in_midi;
1362                 DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
1363                 uint32_t idx = _in_map.get (dt, pn, &valid_in);
1364                 if (!valid_in) {
1365                         double x = pin_x_pos (i, width, pc_in, 0, is_midi);
1366                         draw_gnd (cr, x, 0, height, is_midi);
1367                         continue;
1368                 }
1369                 if (idx >= _in.get (dt)) {
1370                         // side-chain, probably
1371                         double x = pin_x_pos (i, width, pc_in, 0, is_midi);
1372                         draw_sidechain (cr, x, 0, height, is_midi);
1373                         continue;
1374                 }
1375                 double c_x0;
1376                 double c_x1 = pin_x_pos (i, width, pc_in, 0, false);
1377
1378                 if (_fed_by) {
1379                         bool valid_src;
1380                         uint32_t src = _f_out_map.get_src (dt, idx, &valid_src);
1381                         if (!valid_src) {
1382                                 double x = pin_x_pos (i, width, pc_in, 0, false);
1383                                 bool valid_thru;
1384                                 _f_thru_map.get (dt, idx, &valid_thru);
1385                                 if (valid_thru) {
1386                                         draw_thru_src (cr, x, 0, height, is_midi);
1387                                 } else {
1388                                         draw_gnd (cr, x, 0, height, is_midi);
1389                                 }
1390                                 continue;
1391                         }
1392                         c_x0 = pin_x_pos (src, width, _f_sources.n_total(), _f_sources.n_midi(), is_midi);
1393                 } else {
1394                         c_x0 = pin_x_pos (idx, width, _in.n_total(), _in.n_midi(), is_midi);
1395                 }
1396                 draw_connection (cr, c_x0, c_x1, 0, height, is_midi);
1397         }
1398 }
1399
1400 void
1401 ProcessorEntry::RoutingIcon::expose_input_map (cairo_t* cr, const double width, const double height)
1402 {
1403         const uint32_t n_in = _in.n_total();
1404         const uint32_t n_in_midi = _in.n_midi();
1405         const uint32_t pc_in = _sinks.n_total();
1406         const uint32_t pc_in_midi = _sinks.n_midi();
1407
1408         // draw inputs to this
1409         for (uint32_t i = 0; i < pc_in; ++i) {
1410                 const bool is_midi = i < pc_in_midi;
1411                 bool valid_in;
1412                 uint32_t pn = is_midi ? i : i - pc_in_midi;
1413                 DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
1414                 uint32_t idx = _in_map.get (dt, pn, &valid_in);
1415                 // check if it's fed
1416                 bool valid_src = true;
1417                 if (valid_in && idx < _in.get (dt) && _fed_by) {
1418                         bool valid_out;
1419                         bool valid_thru;
1420                         _f_out_map.get_src (dt, idx, &valid_out);
1421                         _f_thru_map.get (dt, idx, &valid_thru);
1422                         if (!valid_out && !valid_thru) {
1423                                 valid_src = false;
1424                         }
1425                 }
1426                 if (!valid_in || !valid_src) {
1427                         double x = pin_x_pos (i, width, pc_in, 0, is_midi);
1428                         draw_gnd (cr, x, 0, height, is_midi);
1429                         continue;
1430                 }
1431                 if (idx >= _in.get (dt)) {
1432                         // side-chain, probably
1433                         double x = pin_x_pos (i, width, pc_in, 0, is_midi);
1434                         draw_sidechain (cr, x, 0, height, is_midi);
1435                         continue;
1436                 }
1437                 double c_x1 = pin_x_pos (i, width, pc_in, 0, false);
1438                 double c_x0 = pin_x_pos (idx, width, n_in, n_in_midi, is_midi);
1439                 draw_connection (cr, c_x0, c_x1, 0, height, is_midi);
1440         }
1441
1442         // draw reverse thru
1443         for (uint32_t i = 0; i < n_in; ++i) {
1444                 const bool is_midi = i < n_in_midi;
1445                 bool valid_thru;
1446                 uint32_t pn = is_midi ? i : i - n_in_midi;
1447                 DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
1448                 _thru_map.get_src (dt, pn, &valid_thru);
1449                 if (!valid_thru) {
1450                         continue;
1451                 }
1452                 double x = pin_x_pos (i, width, n_in, 0, is_midi);
1453                 draw_thru_sink (cr, x, 0, height, is_midi);
1454         }
1455 }
1456
1457 void
1458 ProcessorEntry::RoutingIcon::expose_output_map (cairo_t* cr, const double width, const double height)
1459 {
1460         int dh = std::max (4.f, rintf(4.f * UIConfiguration::instance().get_ui_scale()));
1461         double ht = _terminal ? height - dh : height;
1462
1463         // draw outputs of this
1464         const uint32_t pc_out = _sources.n_total();
1465         const uint32_t pc_out_midi = _sources.n_midi();
1466         const uint32_t n_out = _out.n_total();
1467         const uint32_t n_out_midi = _out.n_midi();
1468
1469         for (uint32_t i = 0; i < pc_out; ++i) {
1470                 const bool is_midi = i < pc_out_midi;
1471                 bool valid_out;
1472                 uint32_t pn = is_midi ? i : i - pc_out_midi;
1473                 DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
1474                 uint32_t idx = _out_map.get (dt, pn, &valid_out);
1475                 if (!valid_out) {
1476                         continue;
1477                 }
1478                 // skip connections that are not used in the next's input
1479                 if (_feeding) {
1480                         bool valid_thru, valid_sink;
1481                         _i_in_map.get_src (dt, idx, &valid_sink);
1482                         _i_thru_map.get_src (dt, idx, &valid_thru);
1483                         if (!valid_thru && !valid_sink) {
1484                                 if (!is_midi || i != 0) { // special case midi-bypass
1485                                         continue;
1486                                 }
1487                         }
1488                 }
1489                 double c_x0 = pin_x_pos (i, width, pc_out, 0, false);
1490                 double c_x1 = pin_x_pos (idx, width, n_out, n_out_midi, is_midi);
1491                 draw_connection (cr, c_x0, c_x1, 0, ht, is_midi);
1492         }
1493
1494         for (uint32_t i = 0; i < n_out; ++i) {
1495                 const bool is_midi = i < n_out_midi;
1496                 uint32_t pn = is_midi ? i : i - n_out_midi;
1497                 DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
1498                 double x = pin_x_pos (i, width, n_out, 0, is_midi);
1499
1500                 if (!_terminal) {
1501                         bool valid_thru_f = false;
1502                         // skip connections that are not used in the next's input
1503                         if (_feeding) {
1504                                 bool valid_sink;
1505                                 _i_in_map.get_src (dt, pn, &valid_sink);
1506                                 _i_thru_map.get_src (dt, pn, &valid_thru_f);
1507                                 if (!valid_thru_f && !valid_sink) {
1508                                         if (!is_midi || i != 0) { // special case midi-bypass
1509                                                 continue;
1510                                         }
1511                                 }
1512                         }
1513
1514                         bool valid_src;
1515                         _out_map.get_src (dt, pn, &valid_src);
1516                         if (!valid_src) {
1517                                 bool valid_thru;
1518                                 uint32_t idx = _thru_map.get (dt, pn, &valid_thru);
1519                                 if (valid_thru) {
1520                                         if (idx >= _in.get (dt)) {
1521                                                 draw_sidechain (cr, x, 0, height, is_midi);
1522                                         } else {
1523                                                 draw_thru_src (cr, x, 0, height, is_midi);
1524                                         }
1525                                 } else if (valid_thru_f){
1526                                         // gnd is part of input, unless it's a thru input
1527                                         // (also only true if !coalesced into one small display)
1528                                         draw_gnd (cr, x, 0, height, is_midi);
1529                                 }
1530                         }
1531                 } else {
1532                         // terminal node, add arrows
1533                         bool valid_src;
1534                         _out_map.get_src (dt, pn, &valid_src);
1535                         if (!valid_src) {
1536                                 bool valid_thru;
1537                                 uint32_t idx = _thru_map.get (dt, pn, &valid_thru);
1538                                 if (valid_thru) {
1539                                         if (idx >= _in.get (dt)) {
1540                                                 draw_sidechain (cr, x, 0, height - dh, is_midi);
1541                                         } else {
1542                                                 draw_thru_src (cr, x, 0, height - dh, is_midi);
1543                                         }
1544                                 } else {
1545                                         draw_gnd (cr, x, 0, height - dh, is_midi);
1546                                 }
1547                         }
1548
1549                         set_routing_color (cr, is_midi);
1550                         cairo_set_line_width (cr, 1.0);
1551                         cairo_move_to (cr, x, height - dh);
1552                         cairo_line_to (cr, x, height - 2);
1553                         cairo_stroke (cr);
1554
1555                         const double ar = dh - 1;
1556                         cairo_move_to (cr, x - ar, height - ar);
1557                         cairo_line_to (cr, x     , height - .5);
1558                         cairo_line_to (cr, x + ar, height - ar);
1559                         cairo_line_to (cr, x     , height - ar * .5);
1560                         cairo_close_path (cr);
1561                         cairo_fill_preserve (cr);
1562                         cairo_stroke (cr);
1563                 }
1564         }
1565 }
1566
1567 ProcessorEntry::PluginInlineDisplay::PluginInlineDisplay (ProcessorEntry& e, boost::shared_ptr<ARDOUR::Plugin> p, uint32_t max_height)
1568         : PluginDisplay (p, max_height)
1569         , _entry (e)
1570         , _scroll (false)
1571         , _given_max_height (max_height)
1572 {
1573         std::string postfix = string_compose(_("\n%1+double-click to toggle inline-display"), Keyboard::tertiary_modifier_name ());
1574
1575         if (_plug->has_editor()) {
1576                 set_tooltip (*this,
1577                                 string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), e.name (Wide), Keyboard::primary_modifier_name (), postfix));
1578         } else {
1579                 set_tooltip (*this,
1580                                 string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), e.name (Wide), postfix));
1581         }
1582 }
1583
1584
1585 bool
1586 ProcessorEntry::PluginInlineDisplay::on_button_press_event (GdkEventButton *ev)
1587 {
1588         assert (_entry.processor ());
1589
1590         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_entry.processor());
1591         // duplicated code :(
1592         // consider some tweaks to pass this up to the DnDVBox somehow:
1593         // select processor, then call (private)
1594         //_entry._parent->processor_button_press_event (ev, &_entry);
1595         if (pi && pi->plugin() && pi->plugin()->has_inline_display()
1596                         && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)
1597                         && ev->button == 1
1598                         && ev->type == GDK_2BUTTON_PRESS) {
1599                 _entry.toggle_inline_display_visibility ();
1600                 return true;
1601         }
1602         else if (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)) {
1603                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
1604                         _entry._parent->generic_edit_processor (_entry.processor ());
1605                 } else {
1606                         _entry._parent->edit_processor (_entry.processor ());
1607                 }
1608                 return true;
1609         }
1610         return false;
1611 }
1612
1613 void
1614 ProcessorEntry::PluginInlineDisplay::on_size_request (Requisition* req)
1615 {
1616         req->width = 56;
1617         req->height = _cur_height;
1618 }
1619
1620
1621 void
1622 ProcessorEntry::PluginInlineDisplay::update_height_alloc (uint32_t inline_height)
1623 {
1624         /* work-around scroll-bar + aspect ratio
1625          * show inline-view -> height changes -> scrollbar gets added
1626          * -> width changes -> inline-view, fixed aspect ratio -> height changes
1627          * -> scroll bar is removed [-> width changes ; repeat ]
1628          */
1629         uint32_t shm = std::min (_max_height, inline_height);
1630         bool sc = false;
1631         Gtk::Container* pr = get_parent();
1632         for (uint32_t i = 0; i < 4 && pr; ++i) {
1633                 // VBox, EventBox, ViewPort, ScrolledWindow
1634                 pr = pr->get_parent();
1635         }
1636         Gtk::ScrolledWindow* sw = dynamic_cast<Gtk::ScrolledWindow*> (pr);
1637         if (sw) {
1638                 const Gtk::VScrollbar* vsb = sw->get_vscrollbar();
1639                 sc = vsb && vsb->is_visible();
1640         }
1641
1642         if (shm != _cur_height) {
1643                 queue_resize ();
1644                 if (!_scroll && sc) {
1645                         _max_height = shm;
1646                 } else {
1647                         _max_height = _given_max_height;
1648                 }
1649                 _cur_height = shm;
1650         }
1651
1652         _scroll = sc;
1653 }
1654
1655 void
1656 ProcessorEntry::PluginInlineDisplay::display_sample (cairo_t* cr, double w, double h)
1657 {
1658         Gtkmm2ext::rounded_rectangle (cr, .5, -1.5, w - 1, h + 1, 7);
1659 }
1660
1661 ProcessorEntry::LuaPluginDisplay::LuaPluginDisplay (ProcessorEntry& e, boost::shared_ptr<ARDOUR::LuaProc> p, uint32_t max_height)
1662         : PluginInlineDisplay (e, p, max_height)
1663         , _luaproc (p)
1664         , _lua_render_inline (0)
1665 {
1666         p->setup_lua_inline_gui (&lua_gui);
1667
1668         lua_State* LG = lua_gui.getState ();
1669         LuaInstance::bind_cairo (LG);
1670         luabridge::LuaRef lua_render = luabridge::getGlobal (LG, "render_inline");
1671         assert (lua_render.isFunction ());
1672         _lua_render_inline = new luabridge::LuaRef (lua_render);
1673 }
1674
1675 ProcessorEntry::LuaPluginDisplay::~LuaPluginDisplay ()
1676 {
1677         delete (_lua_render_inline);
1678 }
1679
1680 uint32_t
1681 ProcessorEntry::LuaPluginDisplay::render_inline (cairo_t *cr, uint32_t width)
1682 {
1683         Cairo::Context ctx (cr);
1684         try {
1685                 luabridge::LuaRef rv = (*_lua_render_inline)((Cairo::Context *)&ctx, width, _max_height);
1686                 lua_gui.collect_garbage_step ();
1687                 if (rv.isTable ()) {
1688                         uint32_t h = rv[2];
1689                         return h;
1690                 }
1691         } catch (luabridge::LuaException const& e) {
1692 #ifndef NDEBUG
1693                 cerr << "LuaException:" << e.what () << endl;
1694 #endif
1695         } catch (...) { }
1696         return 0;
1697 }
1698
1699
1700 static std::list<Gtk::TargetEntry> drop_targets()
1701 {
1702         std::list<Gtk::TargetEntry> tmp;
1703         tmp.push_back (Gtk::TargetEntry ("processor")); // from processor-box to processor-box
1704         tmp.push_back (Gtk::TargetEntry ("PluginInfoPtr")); // from plugin-manager
1705         tmp.push_back (Gtk::TargetEntry ("PluginFavoritePtr")); // from sidebar
1706         return tmp;
1707 }
1708
1709 static std::list<Gtk::TargetEntry> drag_targets()
1710 {
1711         std::list<Gtk::TargetEntry> tmp;
1712         tmp.push_back (Gtk::TargetEntry ("PluginPresetPtr")); // to sidebar (optional preset)
1713         tmp.push_back (Gtk::TargetEntry ("processor")); // to processor-box (copy)
1714         return tmp;
1715 }
1716
1717 static std::list<Gtk::TargetEntry> drag_targets_noplugin()
1718 {
1719         std::list<Gtk::TargetEntry> tmp;
1720         tmp.push_back (Gtk::TargetEntry ("processor")); // to processor box (sends, faders re-order)
1721         return tmp;
1722 }
1723
1724 ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
1725                             ProcessorSelection& psel, MixerStrip* parent, bool owner_is_mixer)
1726         : _parent_strip (parent)
1727         , _owner_is_mixer (owner_is_mixer)
1728         , ab_direction (true)
1729         , _get_plugin_selector (get_plugin_selector)
1730         , _placement (-1)
1731         , _p_selection(psel)
1732         , processor_display (drop_targets())
1733         , _redisplay_pending (false)
1734 {
1735         set_session (sess);
1736
1737         /* ProcessorBox actions and bindings created statically by call to
1738          * ProcessorBox::register_actions(), made by ARDOUR_UI so that actions
1739          * are available for context menus.
1740          */
1741
1742         processor_display.set_data ("ardour-bindings", bindings);
1743
1744         _width = Wide;
1745         processor_menu = 0;
1746         no_processor_redisplay = false;
1747
1748         processor_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1749         processor_scroller.add (processor_display);
1750         pack_start (processor_scroller, true, true);
1751
1752         processor_display.set_flags (CAN_FOCUS);
1753         processor_display.set_name ("ProcessorList");
1754         processor_display.set_data ("processorbox", this);
1755         processor_display.set_size_request (48, -1);
1756         processor_display.set_spacing (0);
1757
1758         processor_display.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify), false);
1759         processor_display.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify), false);
1760
1761         processor_display.ButtonPress.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event));
1762         processor_display.ButtonRelease.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event));
1763
1764         processor_display.Reordered.connect (sigc::mem_fun (*this, &ProcessorBox::reordered));
1765         processor_display.DropFromAnotherBox.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop));
1766         processor_display.DropFromExternal.connect (sigc::mem_fun (*this, &ProcessorBox::plugin_drop));
1767
1768         processor_scroller.show ();
1769         processor_display.show ();
1770
1771         if (parent) {
1772                 parent->DeliveryChanged.connect (
1773                         _mixer_strip_connections, invalidator (*this), boost::bind (&ProcessorBox::mixer_strip_delivery_changed, this, _1), gui_context ()
1774                         );
1775         }
1776
1777         set_tooltip (processor_display, _("Right-click to add/remove/edit\nplugins,inserts,sends and more"));
1778 }
1779
1780 ProcessorBox::~ProcessorBox ()
1781 {
1782         /* it may appear as if we should delete processor_menu but that is a
1783          * pointer to a widget owned by the UI Manager, and has potentially
1784          * be returned to many other ProcessorBoxes. GTK doesn't really make
1785          * clear the ownership of this widget, which is a menu and thus is
1786          * never packed into any container other than an implict GtkWindow.
1787          *
1788          * For now, until or if we ever get clarification over the ownership
1789          * story just let it continue to exist. At worst, its a small memory leak.
1790          */
1791 }
1792
1793 void
1794 ProcessorBox::set_route (boost::shared_ptr<Route> r)
1795 {
1796         if (_route == r) {
1797                 return;
1798         }
1799
1800         _route_connections.drop_connections();
1801
1802         /* new route: any existing block on processor redisplay must be meaningless */
1803         no_processor_redisplay = false;
1804         _route = r;
1805
1806         _route->processors_changed.connect (
1807                 _route_connections, invalidator (*this), boost::bind (&ProcessorBox::route_processors_changed, this, _1), gui_context()
1808                 );
1809
1810         _route->DropReferences.connect (
1811                 _route_connections, invalidator (*this), boost::bind (&ProcessorBox::route_going_away, this), gui_context()
1812                 );
1813
1814         _route->PropertyChanged.connect (
1815                 _route_connections, invalidator (*this), boost::bind (&ProcessorBox::route_property_changed, this, _1), gui_context()
1816                 );
1817
1818         redisplay_processors ();
1819 }
1820
1821 void
1822 ProcessorBox::route_going_away ()
1823 {
1824         /* don't keep updating display as processors are deleted */
1825         no_processor_redisplay = true;
1826         _route.reset ();
1827 }
1828
1829 boost::shared_ptr<Processor>
1830 ProcessorBox::find_drop_position (ProcessorEntry* position)
1831 {
1832         boost::shared_ptr<Processor> p;
1833         if (position) {
1834                 p = position->processor ();
1835                 if (!p) {
1836                         /* dropped on the blank entry (which will be before the
1837                                  fader), so use the first non-blank child as our
1838                                  `dropped on' processor */
1839                         list<ProcessorEntry*> c = processor_display.children ();
1840                         list<ProcessorEntry*>::iterator i = c.begin ();
1841
1842                         assert (i != c.end ());
1843                         p = (*i)->processor ();
1844                         assert (p);
1845                 }
1846         }
1847         return p;
1848 }
1849
1850 void
1851 ProcessorBox::_drop_plugin_preset (Gtk::SelectionData const &data, Route::ProcessorList &pl)
1852 {
1853                 const void * d = data.get_data();
1854                 const Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr>* tv = reinterpret_cast<const Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr>*>(d);
1855
1856                 PluginPresetList nfos;
1857                 TreeView* source;
1858                 tv->get_object_drag_data (nfos, &source);
1859
1860                 for (list<PluginPresetPtr>::const_iterator i = nfos.begin(); i != nfos.end(); ++i) {
1861                         PluginPresetPtr ppp = (*i);
1862                         PluginInfoPtr pip = ppp->_pip;
1863                         PluginPtr p = pip->load (*_session);
1864                         if (!p) {
1865                                 continue;
1866                         }
1867
1868                         if (ppp->_preset.valid) {
1869                                 p->load_preset (ppp->_preset);
1870                         }
1871
1872                         boost::shared_ptr<Processor> processor (new PluginInsert (*_session, p));
1873                         if (Config->get_new_plugins_active ()) {
1874                                 processor->enable (true);
1875                         }
1876                         pl.push_back (processor);
1877                 }
1878 }
1879
1880 void
1881 ProcessorBox::_drop_plugin (Gtk::SelectionData const &data, Route::ProcessorList &pl)
1882 {
1883                 const void * d = data.get_data();
1884                 const Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr>* tv = reinterpret_cast<const Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr>*>(d);
1885                 PluginInfoList nfos;
1886
1887                 TreeView* source;
1888                 tv->get_object_drag_data (nfos, &source);
1889
1890                 for (list<PluginInfoPtr>::const_iterator i = nfos.begin(); i != nfos.end(); ++i) {
1891                         PluginPtr p = (*i)->load (*_session);
1892                         if (!p) {
1893                                 continue;
1894                         }
1895                         boost::shared_ptr<Processor> processor (new PluginInsert (*_session, p));
1896                         if (Config->get_new_plugins_active ()) {
1897                                 processor->enable (true);
1898                         }
1899                         pl.push_back (processor);
1900                 }
1901 }
1902
1903 void
1904 ProcessorBox::plugin_drop (Gtk::SelectionData const &data, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
1905 {
1906         if (!_session) {
1907                 return;
1908         }
1909
1910         boost::shared_ptr<Processor> p = find_drop_position (position);
1911         Route::ProcessorList pl;
1912
1913         if (data.get_target() == "PluginInfoPtr") {
1914                 _drop_plugin (data, pl);
1915         }
1916         else if (data.get_target() == "PluginFavoritePtr") {
1917                 _drop_plugin_preset (data, pl);
1918         }
1919         else {
1920                 return;
1921         }
1922
1923         Route::ProcessorStreams err;
1924         if (_route->add_processors (pl, p, &err)) {
1925                 string msg = _(
1926                                 "Processor Drag/Drop failed. Probably because\n\
1927 the I/O configuration of the plugins could\n\
1928 not match the configuration of this track.");
1929                 MessageDialog am (msg);
1930                 am.run ();
1931         }
1932 }
1933
1934 void
1935 ProcessorBox::object_drop (DnDVBox<ProcessorEntry>* source, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
1936 {
1937         if (Gdk::ACTION_LINK == context->get_selected_action()) {
1938                 list<ProcessorEntry*> children = source->selection ();
1939                 assert (children.size() == 1);
1940                 ProcessorEntry* other = *children.begin();
1941                 assert (other->can_copy_state (position));
1942                 boost::shared_ptr<ARDOUR::Processor> otherproc = other->processor();
1943                 boost::shared_ptr<ARDOUR::Processor> proc = position->processor();
1944                 boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (proc);
1945                 assert (otherproc && proc && pi);
1946
1947                 PBD::ID id = pi->id();
1948                 XMLNode& state = otherproc->get_state ();
1949                 /* strip side-chain state (processor inside processor must be a side-chain)
1950                  * otherwise we'll end up with duplicate ports-names.
1951                  * (this needs a better solution which retains connections)
1952                  */
1953                 state.remove_nodes_and_delete ("Processor");
1954                 proc->set_state (state, Stateful::loading_state_version);
1955                 boost::dynamic_pointer_cast<PluginInsert>(proc)->update_id (id);
1956                 return;
1957         }
1958
1959         boost::shared_ptr<Processor> p = find_drop_position (position);
1960
1961         list<ProcessorEntry*> children = source->selection (true);
1962         list<boost::shared_ptr<Processor> > procs;
1963         for (list<ProcessorEntry*>::const_iterator i = children.begin(); i != children.end(); ++i) {
1964                 if ((*i)->processor ()) {
1965                         if (boost::dynamic_pointer_cast<UnknownProcessor> ((*i)->processor())) {
1966                                 continue;
1967                         }
1968                         procs.push_back ((*i)->processor ());
1969                 }
1970         }
1971
1972         for (list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin(); i != procs.end(); ++i) {
1973                 XMLNode& state = (*i)->get_state ();
1974                 XMLNodeList nlist;
1975                 nlist.push_back (&state);
1976                 paste_processor_state (nlist, p);
1977                 delete &state;
1978         }
1979
1980         /* since the dndvbox doesn't take care of this properly, we have to delete the originals
1981            ourselves.
1982         */
1983
1984         if ((context->get_suggested_action() == Gdk::ACTION_MOVE) && source) {
1985                 ProcessorBox* other = reinterpret_cast<ProcessorBox*> (source->get_data ("processorbox"));
1986                 if (other) {
1987                         other->delete_dragged_processors (procs);
1988                 }
1989         }
1990 }
1991
1992 void
1993 ProcessorBox::set_width (Width w)
1994 {
1995         if (_width == w) {
1996                 return;
1997         }
1998
1999         _width = w;
2000
2001         list<ProcessorEntry*> children = processor_display.children ();
2002         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
2003                 (*i)->set_enum_width (w);
2004         }
2005
2006         queue_resize ();
2007 }
2008
2009 Gtk::Menu*
2010 ProcessorBox::build_possible_aux_menu ()
2011 {
2012         boost::shared_ptr<RouteList> rl = _session->get_routes_with_internal_returns();
2013
2014         if (rl->empty()) {
2015                 /* No aux sends if there are no busses */
2016                 return 0;
2017         }
2018
2019         if (_route->is_monitor ()) {
2020                 return 0;
2021         }
2022
2023         using namespace Menu_Helpers;
2024         Menu* menu = manage (new Menu);
2025         MenuList& items = menu->items();
2026
2027         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2028                 if ((*r)->is_master() || (*r)->is_monitor () || *r == _route) {
2029                         /* don't allow sending to master or monitor or to self */
2030                         continue;
2031                 }
2032                 if (_route->internal_send_for (*r)) {
2033                         /* aux-send to target already exists */
2034                         continue;
2035                 }
2036                 items.push_back (MenuElemNoMnemonic ((*r)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux), boost::weak_ptr<Route>(*r))));
2037         }
2038
2039         return menu;
2040 }
2041
2042 void
2043 ProcessorBox::show_processor_menu (int arg)
2044 {
2045         if (processor_menu == 0) {
2046                 processor_menu = build_processor_menu ();
2047                 processor_menu->signal_unmap().connect (sigc::mem_fun (*this, &ProcessorBox::processor_menu_unmapped));
2048         }
2049
2050         /* Sort out the plugin submenu */
2051
2052         Gtk::MenuItem* plugin_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
2053
2054         if (plugin_menu_item) {
2055                 plugin_menu_item->set_submenu (*_get_plugin_selector()->plugin_menu());
2056         }
2057
2058         /* And the aux submenu */
2059
2060         Gtk::MenuItem* aux_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newaux"));
2061
2062         if (aux_menu_item) {
2063                 Menu* m = build_possible_aux_menu();
2064                 if (m && !m->items().empty()) {
2065                         aux_menu_item->set_submenu (*m);
2066                         aux_menu_item->set_sensitive (true);
2067                 } else {
2068                         /* stupid gtkmm: we need to pass a null reference here */
2069                         gtk_menu_item_set_submenu (aux_menu_item->gobj(), 0);
2070                         aux_menu_item->set_sensitive (false);
2071                 }
2072         }
2073
2074         ActionManager::get_action (X_("ProcessorMenu"), "newinsert")->set_sensitive (!_route->is_monitor ());
2075         ActionManager::get_action (X_("ProcessorMenu"), "newsend")->set_sensitive (!_route->is_monitor ());
2076
2077         ProcessorEntry* single_selection = 0;
2078         if (processor_display.selection().size() == 1) {
2079                 single_selection = processor_display.selection().front();
2080         }
2081
2082         /* And the controls submenu */
2083
2084         Gtk::MenuItem* controls_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/controls"));
2085
2086         if (controls_menu_item) {
2087                 if (single_selection) {
2088                         Menu* m = single_selection->build_controls_menu ();
2089                         if (m && !m->items().empty()) {
2090                                 controls_menu_item->set_submenu (*m);
2091                                 controls_menu_item->set_sensitive (true);
2092                         } else {
2093                                 gtk_menu_item_set_submenu (controls_menu_item->gobj(), 0);
2094                                 controls_menu_item->set_sensitive (false);
2095                         }
2096                 } else {
2097                         controls_menu_item->set_sensitive (false);
2098                 }
2099         }
2100
2101
2102         Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
2103         if (send_menu_item) {
2104                 if (single_selection && !_route->is_monitor()) {
2105                         Menu* m = single_selection->build_send_options_menu ();
2106                         if (m && !m->items().empty()) {
2107                                 send_menu_item->set_submenu (*m);
2108                                 send_menu_item->set_sensitive (true);
2109                         } else {
2110                                 gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
2111                                 send_menu_item->set_sensitive (false);
2112                         }
2113                 } else {
2114                         send_menu_item->set_sensitive (false);
2115                 }
2116         }
2117
2118         /* Sensitise actions as approprioate */
2119
2120         const bool sensitive = !processor_display.selection().empty() && ! stub_processor_selected ();
2121
2122         paste_action->set_sensitive (!_p_selection.processors.empty());
2123         cut_action->set_sensitive (sensitive && can_cut ());
2124         copy_action->set_sensitive (sensitive);
2125         delete_action->set_sensitive (sensitive || stub_processor_selected ());
2126         backspace_action->set_sensitive (sensitive || stub_processor_selected ());
2127
2128         edit_action->set_sensitive (one_processor_can_be_edited ());
2129         edit_generic_action->set_sensitive (one_processor_can_be_edited ());
2130
2131         boost::shared_ptr<PluginInsert> pi;
2132         if (single_selection) {
2133                 pi = boost::dynamic_pointer_cast<PluginInsert> (single_selection->processor ());
2134         }
2135
2136         manage_pins_action->set_sensitive (pi != 0);
2137         if (boost::dynamic_pointer_cast<Track>(_route)) {
2138                 disk_io_action->set_sensitive (true);
2139         } else {
2140                 disk_io_action->set_sensitive (false);
2141         }
2142
2143         /* allow editing with an Ardour-generated UI for plugin inserts with editors */
2144         edit_action->set_sensitive (pi && pi->plugin()->has_editor ());
2145
2146         /* disallow rename for multiple selections, for plugin inserts and for the fader */
2147         rename_action->set_sensitive (single_selection
2148                         && !pi
2149                         && !boost::dynamic_pointer_cast<Amp> (single_selection->processor ())
2150                         && !boost::dynamic_pointer_cast<UnknownProcessor> (single_selection->processor ()));
2151
2152         processor_menu->popup (1, arg);
2153
2154         /* Add a placeholder gap to the processor list to indicate where a processor would be
2155            inserted were one chosen from the menu.
2156         */
2157         int x, y;
2158         processor_display.get_pointer (x, y);
2159         _placement = processor_display.add_placeholder (y);
2160 }
2161
2162 bool
2163 ProcessorBox::enter_notify (GdkEventCrossing*)
2164 {
2165         processor_display.grab_focus ();
2166         _current_processor_box = this;
2167         return false;
2168 }
2169
2170 bool
2171 ProcessorBox::leave_notify (GdkEventCrossing* ev)
2172 {
2173         if (ev->detail == GDK_NOTIFY_INFERIOR) {
2174                 return false;
2175         }
2176
2177         Widget* top = get_toplevel();
2178
2179         if (top->is_toplevel()) {
2180                 Window* win = dynamic_cast<Window*> (top);
2181                 gtk_window_set_focus (win->gobj(), 0);
2182         }
2183
2184         return false;
2185 }
2186
2187 bool
2188 ProcessorBox::processor_operation (ProcessorOperation op)
2189 {
2190         ProcSelection targets;
2191
2192         get_selected_processors (targets);
2193
2194 /*      if (targets.empty()) {
2195
2196                 int x, y;
2197                 processor_display.get_pointer (x, y);
2198
2199                 pair<ProcessorEntry *, double> const pointer = processor_display.get_child_at_position (y);
2200
2201                 if (pointer.first && pointer.first->processor()) {
2202                         targets.push_back (pointer.first->processor ());
2203                 }
2204         }
2205 */
2206
2207         if ((op == ProcessorsDelete) && targets.empty()) {
2208                 return false;  //nothing to delete.  return false so the editor-mixer, because the user was probably intending to delete something in the editor
2209         }
2210
2211         switch (op) {
2212         case ProcessorsSelectAll:
2213                 processor_display.select_all ();
2214                 break;
2215
2216         case ProcessorsSelectNone:
2217                 processor_display.select_none ();
2218                 break;
2219
2220         case ProcessorsCopy:
2221                 copy_processors (targets);
2222                 break;
2223
2224         case ProcessorsCut:
2225                 cut_processors (targets);
2226                 break;
2227
2228         case ProcessorsPaste:
2229                 // some processors are not selectable (e.g fader, meter), target is empty.
2230                 if (targets.empty() && _placement >= 0) {
2231                         assert (_route);
2232                         boost::shared_ptr<Processor> proc = _route->before_processor_for_index (_placement);
2233                         if (proc) {
2234                                 targets.push_back (proc);
2235                         }
2236                 }
2237                 if (targets.empty()) {
2238                         paste_processors ();
2239                 } else {
2240                         paste_processors (targets.front());
2241                 }
2242                 break;
2243
2244         case ProcessorsDelete:
2245                 delete_processors (targets);
2246                 break;
2247
2248         case ProcessorsToggleActive:
2249                 for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
2250                         if (!(*i)->display_to_user ()) {
2251                                 assert (0); // these should not be selectable to begin with.
2252                                 continue;
2253                         }
2254                         if (!boost::dynamic_pointer_cast<PluginInsert> (*i)) {
2255                                 continue;
2256                         }
2257 #ifdef MIXBUS
2258                         if (boost::dynamic_pointer_cast<PluginInsert> (*i)->is_channelstrip()) {
2259                                 continue;
2260                         }
2261 #endif
2262                         (*i)->enable (!(*i)->enabled ());
2263                 }
2264                 break;
2265
2266         case ProcessorsAB:
2267                 ab_plugins ();
2268                 break;
2269
2270         default:
2271                 break;
2272         }
2273
2274         return true;
2275 }
2276
2277 ProcessorWindowProxy*
2278 ProcessorBox::find_window_proxy (boost::shared_ptr<Processor> processor) const
2279 {
2280         return  processor->window_proxy();
2281 }
2282
2283
2284 bool
2285 ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* child)
2286 {
2287         boost::shared_ptr<Processor> processor;
2288         if (child) {
2289                 processor = child->processor ();
2290         }
2291
2292         int ret = false;
2293         bool selected = processor_display.selected (child);
2294
2295         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (processor);
2296         if (pi && pi->plugin() && pi->plugin()->has_inline_display()
2297                         && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)
2298                         && ev->button == 1
2299                         && ev->type == GDK_2BUTTON_PRESS) {
2300                 child->toggle_inline_display_visibility ();
2301                 return true;
2302         }
2303
2304         if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
2305
2306                 if (_session->engine().connected()) {
2307                         /* XXX giving an error message here is hard, because we may be in the midst of a button press */
2308
2309                         if (!one_processor_can_be_edited ()) {
2310                                 return true;
2311                         }
2312
2313                         if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
2314                                 generic_edit_processor (processor);
2315                         } else {
2316                                 edit_processor (processor);
2317                         }
2318                 }
2319
2320                 ret = true;
2321
2322         } else if (Keyboard::is_context_menu_event (ev)) {
2323
2324                 show_processor_menu (ev->time);
2325
2326                 ret = true;
2327
2328         } else if (processor && ev->button == 1 && selected) {
2329
2330                 // this is purely informational but necessary for route params UI
2331                 ProcessorSelected (processor); // emit
2332
2333         } else if (!processor && ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
2334
2335                 choose_plugin ();
2336                 _get_plugin_selector()->show_manager ();
2337         }
2338
2339         return ret;
2340 }
2341
2342 bool
2343 ProcessorBox::processor_button_release_event (GdkEventButton *ev, ProcessorEntry* child)
2344 {
2345         boost::shared_ptr<Processor> processor;
2346         if (child) {
2347                 processor = child->processor ();
2348         }
2349
2350         if (processor && Keyboard::is_delete_event (ev)) {
2351
2352                 Glib::signal_idle().connect (sigc::bind (
2353                                 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor),
2354                                 boost::weak_ptr<Processor>(processor)));
2355
2356         } else if (processor && Keyboard::is_button2_event (ev)
2357 #ifndef __APPLE__
2358                    && (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))
2359 #endif
2360                 ) {
2361
2362                 /* button2-click with no/appropriate modifiers */
2363                 processor->enable (!processor->enabled ());
2364         }
2365
2366         return false;
2367 }
2368
2369 Menu *
2370 ProcessorBox::build_processor_menu ()
2371 {
2372         processor_menu = dynamic_cast<Gtk::Menu*>(ActionManager::get_widget("/ProcessorMenu") );
2373         processor_menu->set_name ("ArdourContextMenu");
2374         return processor_menu;
2375 }
2376
2377 void
2378 ProcessorBox::select_all_processors ()
2379 {
2380         processor_display.select_all ();
2381 }
2382
2383 void
2384 ProcessorBox::deselect_all_processors ()
2385 {
2386         processor_display.select_none ();
2387 }
2388
2389 void
2390 ProcessorBox::choose_plugin ()
2391 {
2392         _get_plugin_selector()->set_interested_object (*this);
2393 }
2394
2395 /** @return true if an error occurred, otherwise false */
2396 bool
2397 ProcessorBox::use_plugins (const SelectedPlugins& plugins)
2398 {
2399         for (SelectedPlugins::const_iterator p = plugins.begin(); p != plugins.end(); ++p) {
2400
2401                 boost::shared_ptr<Processor> processor (new PluginInsert (*_session, *p));
2402
2403                 Route::ProcessorStreams err_streams;
2404
2405                 if (_route->add_processor_by_index (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
2406                         weird_plugin_dialog (**p, err_streams);
2407                         return true;
2408                         // XXX SHAREDPTR delete plugin here .. do we even need to care?
2409                 } else if (plugins.size() == 1 && UIConfiguration::instance().get_open_gui_after_adding_plugin()) {
2410                         if (processor->what_can_be_automated ().size () == 0) {
2411                                 ; /* plugin without controls, don't show ui */
2412                         }
2413                         else if (boost::dynamic_pointer_cast<PluginInsert>(processor)->plugin()->has_inline_display() && UIConfiguration::instance().get_prefer_inline_over_gui()) {
2414                                 ; /* only show inline display */
2415                         }
2416                         else if (_session->engine().connected () && processor_can_be_edited (processor)) {
2417                                 if ((*p)->has_editor ()) {
2418                                         edit_processor (processor);
2419                                 } else if (boost::dynamic_pointer_cast<PluginInsert>(processor)->plugin()->parameter_count() > 0) {
2420                                         generic_edit_processor (processor);
2421                                 }
2422                         }
2423                 }
2424                 /* add next processor below the currently added.
2425                  * Note: placement < 0: add the bottom */
2426                 if (_placement >= 0) {
2427                         ++_placement;
2428                 }
2429         }
2430
2431         return false;
2432 }
2433
2434 void
2435 ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams)
2436 {
2437         /* XXX this needs to be re-worked!
2438          *
2439          * With new pin-management "streams" is no longer correct.
2440          * p.get_info () is also incorrect for variable i/o plugins (always -1,-1).
2441          *
2442          * Since pin-management was added, this dialog will only show in a very rare
2443          * condition (non-replicated variable i/o configuration failed).
2444          *
2445          * TODO: simplify the message after the string-freeze is lifted.
2446          */
2447         ArdourDialog dialog (_("Plugin Incompatibility"));
2448         Label label;
2449
2450         string text = string_compose(_("You attempted to add the plugin \"%1\" in slot %2.\n"),
2451                         p.name(), streams.index);
2452
2453         bool has_midi  = streams.count.n_midi() > 0 || p.get_info()->n_inputs.n_midi() > 0;
2454         bool has_audio = streams.count.n_audio() > 0 || p.get_info()->n_inputs.n_audio() > 0;
2455
2456         text += _("\nThis plugin has:\n");
2457         if (has_midi) {
2458                 uint32_t const n = p.get_info()->n_inputs.n_midi ();
2459                 text += string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n), n);
2460         }
2461         if (has_audio) {
2462                 uint32_t const n = p.get_info()->n_inputs.n_audio ();
2463                 text += string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n), n);
2464         }
2465
2466         text += _("\nbut at the insertion point, there are:\n");
2467         if (has_midi) {
2468                 uint32_t const n = streams.count.n_midi ();
2469                 text += string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n), n);
2470         }
2471         if (has_audio) {
2472                 uint32_t const n = streams.count.n_audio ();
2473                 text += string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n), n);
2474         }
2475
2476         text += string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME);
2477         label.set_text(text);
2478
2479         dialog.get_vbox()->pack_start (label);
2480         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
2481
2482         dialog.set_name (X_("PluginIODialog"));
2483         dialog.set_modal (true);
2484         dialog.show_all ();
2485
2486         dialog.run ();
2487 }
2488
2489 void
2490 ProcessorBox::choose_insert ()
2491 {
2492         boost::shared_ptr<Processor> processor (new PortInsert (*_session, _route->pannable(), _route->mute_master()));
2493         _route->add_processor_by_index (processor, _placement);
2494 }
2495
2496 /* Caller must not hold process lock */
2497 void
2498 ProcessorBox::choose_send ()
2499 {
2500         boost::shared_ptr<Send> send (new Send (*_session, _route->pannable (), _route->mute_master()));
2501
2502         /* make an educated guess at the initial number of outputs for the send */
2503         ChanCount outs = (_route->n_outputs().n_audio() && _session->master_out())
2504                         ? _session->master_out()->n_outputs()
2505                         : _route->n_outputs();
2506
2507         /* XXX need processor lock on route */
2508         try {
2509                 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
2510                 send->output()->ensure_io (outs, false, this);
2511         } catch (AudioEngine::PortRegistrationFailure& err) {
2512                 error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
2513                 return;
2514         }
2515
2516         /* let the user adjust the IO setup before creation.
2517
2518            Note: this dialog is NOT modal - we just leave it to run and it will
2519            return when its Finished signal is emitted - typically when the window
2520            is closed.
2521          */
2522
2523         IOSelectorWindow *ios = new IOSelectorWindow (_session, send->output(), true);
2524         ios->show ();
2525
2526         /* keep a reference to the send so it doesn't get deleted while
2527            the IOSelectorWindow is doing its stuff
2528         */
2529         _processor_being_created = send;
2530
2531         ios->selector().Finished.connect (sigc::bind (
2532                         sigc::mem_fun(*this, &ProcessorBox::send_io_finished),
2533                         boost::weak_ptr<Processor>(send), ios));
2534
2535 }
2536
2537 void
2538 ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
2539 {
2540         boost::shared_ptr<Processor> processor (weak_processor.lock());
2541
2542         /* drop our temporary reference to the new send */
2543         _processor_being_created.reset ();
2544
2545         if (!processor) {
2546                 return;
2547         }
2548
2549         switch (r) {
2550         case IOSelector::Cancelled:
2551                 // processor will go away when all shared_ptrs to it vanish
2552                 break;
2553
2554         case IOSelector::Accepted:
2555                 _route->add_processor_by_index (processor, _placement);
2556                 break;
2557         }
2558
2559         delete_when_idle (ios);
2560 }
2561
2562 void
2563 ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
2564 {
2565         boost::shared_ptr<Processor> processor (weak_processor.lock());
2566
2567         /* drop our temporary reference to the new return */
2568         _processor_being_created.reset ();
2569
2570         if (!processor) {
2571                 return;
2572         }
2573
2574         switch (r) {
2575         case IOSelector::Cancelled:
2576                 // processor will go away when all shared_ptrs to it vanish
2577                 break;
2578
2579         case IOSelector::Accepted:
2580                 _route->add_processor_by_index (processor, _placement);
2581                 break;
2582         }
2583
2584         delete_when_idle (ios);
2585 }
2586
2587 void
2588 ProcessorBox::choose_aux (boost::weak_ptr<Route> wr)
2589 {
2590         if (!_route) {
2591                 return;
2592         }
2593
2594         boost::shared_ptr<Route> target = wr.lock();
2595
2596         if (!target) {
2597                 return;
2598         }
2599
2600         _session->add_internal_send (target, _placement, _route);
2601 }
2602
2603 void
2604 ProcessorBox::route_processors_changed (RouteProcessorChange c)
2605 {
2606         if (c.type == RouteProcessorChange::MeterPointChange && c.meter_visibly_changed == false) {
2607                 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
2608                 return;
2609         }
2610
2611         redisplay_processors ();
2612 }
2613
2614 void
2615 ProcessorBox::redisplay_processors ()
2616 {
2617         ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors);
2618
2619         if (no_processor_redisplay) {
2620                 return;
2621         }
2622
2623         processor_display.clear ();
2624
2625         _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display));
2626         _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list));
2627         _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_pin_mgr));
2628
2629         setup_entry_positions ();
2630 }
2631
2632 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
2633  *  not already have one.
2634  */
2635 void
2636 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
2637 {
2638         boost::shared_ptr<Processor> p = w.lock ();
2639         if (!p) {
2640                 return;
2641         }
2642         if (p->window_proxy()) {
2643                 return;
2644         }
2645
2646         /* see also ProcessorBox::get_editor_window */
2647         bool have_ui = false;
2648
2649         if (boost::dynamic_pointer_cast<PluginInsert> (p)) {
2650                 have_ui = true;
2651         }
2652         else if (boost::dynamic_pointer_cast<PortInsert> (p)) {
2653                 have_ui = true;
2654         }
2655         else if (boost::dynamic_pointer_cast<Send> (p)) {
2656                 if (!boost::dynamic_pointer_cast<InternalSend> (p)) {
2657                         have_ui = true;
2658                 }
2659         }
2660         else if (boost::dynamic_pointer_cast<Return> (p)) {
2661                 if (!boost::dynamic_pointer_cast<InternalReturn> (p)) {
2662                         have_ui = true;
2663                 }
2664         }
2665
2666         if (!have_ui) {
2667                 return;
2668         }
2669
2670         ProcessorWindowProxy* wp = new ProcessorWindowProxy (
2671                         string_compose ("P-%1-%2", _route->id(), p->id()),
2672                         this,
2673                         w);
2674
2675         const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
2676
2677         if (ui_xml) {
2678                 wp->set_state (*ui_xml, 0);
2679         }
2680
2681         p->set_window_proxy (wp);
2682         WM::Manager::instance().register_window (wp);
2683 }
2684
2685 void
2686 ProcessorBox::maybe_add_processor_pin_mgr (boost::weak_ptr<Processor> w)
2687 {
2688         boost::shared_ptr<Processor> p = w.lock ();
2689         if (!p || p->pinmgr_proxy ()) {
2690                 return;
2691         }
2692         if (!boost::dynamic_pointer_cast<PluginInsert> (p)) {
2693                 return;
2694         }
2695
2696         PluginPinWindowProxy* wp = new PluginPinWindowProxy (
2697                         string_compose ("PM-%1-%2", _route->id(), p->id()), w);
2698         wp->set_session (_session);
2699
2700         const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
2701         if (ui_xml) {
2702                 wp->set_state (*ui_xml, 0);
2703         }
2704
2705         p->set_pingmgr_proxy (wp);
2706         WM::Manager::instance().register_window (wp);
2707 }
2708
2709 void
2710 ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
2711 {
2712         boost::shared_ptr<Processor> processor (p.lock ());
2713
2714         if (!processor || ( !processor->display_to_user()
2715 #ifndef NDEBUG
2716                             && !show_all_processors
2717 #endif
2718                           )
2719            ) {
2720                 return;
2721         }
2722
2723         boost::shared_ptr<PluginInsert> plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor);
2724
2725         ProcessorEntry* e = 0;
2726         if (plugin_insert) {
2727                 e = new PluginInsertProcessorEntry (this, plugin_insert, _width);
2728         } else {
2729                 e = new ProcessorEntry (this, processor, _width);
2730         }
2731
2732         boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
2733         boost::shared_ptr<PortInsert> ext = boost::dynamic_pointer_cast<PortInsert> (processor);
2734         boost::shared_ptr<UnknownProcessor> stub = boost::dynamic_pointer_cast<UnknownProcessor> (processor);
2735
2736         //faders and meters are not deletable, copy/paste-able, so they shouldn't be selectable
2737         if (!send && !plugin_insert && !ext && !stub)
2738                 e->set_selectable(false);
2739
2740         bool mark_send_visible = false;
2741         if (send && _parent_strip) {
2742                 /* show controls of new sends by default */
2743                 GUIObjectState& st = _parent_strip->gui_object_state ();
2744                 XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
2745                 assert (strip);
2746                 /* check if state exists, if not it must be a new send */
2747                 if (!st.get_node(strip, e->state_id())) {
2748                         mark_send_visible = true;
2749                 }
2750         }
2751
2752         /* Set up this entry's state from the GUIObjectState */
2753         XMLNode* proc = entry_gui_object_state (e);
2754         if (proc) {
2755                 e->set_control_state (proc);
2756         }
2757
2758         if (mark_send_visible) {
2759                 e->show_all_controls ();
2760         }
2761
2762         if (plugin_insert
2763 #ifdef MIXBUS
2764                         && !plugin_insert->plugin(0)->is_channelstrip()
2765 #endif
2766                  )
2767         {
2768                 processor_display.add_child (e, drag_targets());
2769         } else {
2770                 processor_display.add_child (e, drag_targets_noplugin());
2771         }
2772 }
2773
2774 void
2775 ProcessorBox::reordered ()
2776 {
2777         compute_processor_sort_keys ();
2778         setup_entry_positions ();
2779 }
2780
2781 void
2782 ProcessorBox::setup_routing_feeds ()
2783 {
2784         list<ProcessorEntry*> children = processor_display.children ();
2785         /* first set the i/o maps for every processor */
2786         list<ProcessorEntry*>::iterator prev = children.begin();
2787
2788         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
2789                 boost::shared_ptr<ARDOUR::Processor> p = (*i)->processor();
2790                 boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (p);
2791
2792                 list<ProcessorEntry*>::iterator next = i;
2793                 next++;
2794
2795                 if (pi) {
2796                         ChanCount sinks = pi->natural_input_streams ();
2797                         ChanCount sources = pi->natural_output_streams ();
2798                         uint32_t count = pi->get_count ();
2799                         ChanCount in, out;
2800                         pi->configured_io (in, out);
2801
2802                         ChanCount midi_thru;
2803                         ChanCount midi_bypass;
2804                         ChanMapping input_map (pi->input_map ());
2805                         if (pi->has_midi_thru ()) {
2806                                  midi_thru.set(DataType::MIDI, 1);
2807                                  input_map.set (DataType::MIDI, 0, 0);
2808                         }
2809                         if (pi->has_midi_bypass ()) {
2810                                  midi_bypass.set(DataType::MIDI, 1);
2811                         }
2812
2813                         (*i)->input_icon.set_ports (sinks * count + midi_thru);
2814                         (*i)->output_icon.set_ports (sources * count + midi_bypass);
2815
2816                         (*i)->routing_icon.set (
2817                                         in, out,
2818                                         sinks * count + midi_thru,
2819                                         sources * count + midi_bypass,
2820                                         input_map,
2821                                         pi->output_map (),
2822                                         pi->thru_map ());
2823
2824                         if (next != children.end()) {
2825                                 (*next)->routing_icon.set_fed_by (out, sources * count + midi_bypass,
2826                                                 pi->output_map (), pi->thru_map ());
2827                         }
2828
2829                         if (prev != i) {
2830                                 (*prev)->routing_icon.set_feeding (in, sinks * count + midi_thru,
2831                                                 pi->input_map (), pi->thru_map ());
2832                         }
2833
2834                 } else {
2835                         (*i)->input_icon.set_ports (p->input_streams());
2836                         (*i)->output_icon.set_ports (p->output_streams());
2837                         ChanMapping inmap (p->input_streams ());
2838                         ChanMapping outmap (p->output_streams ());
2839                         ChanMapping thrumap;
2840                         (*i)->routing_icon.set (
2841                                         p->input_streams(),
2842                                         p->output_streams(),
2843                                         p->input_streams(),
2844                                         p->output_streams(),
2845                                         inmap, outmap, thrumap);
2846
2847                         if (next != children.end()) {
2848                                 (*next)->routing_icon.set_fed_by (
2849                                                 p->output_streams(),
2850                                                 p->output_streams(),
2851                                                 outmap, thrumap);
2852                         }
2853                         if (prev != i) {
2854                                 (*prev)->routing_icon.set_feeding (
2855                                                 p->input_streams(),
2856                                                 p->output_streams(),
2857                                                 inmap, thrumap);
2858                         }
2859                 }
2860
2861                 if (i == children.begin()) {
2862                         (*i)->routing_icon.unset_fed_by ();
2863                 }
2864                 prev = i;
2865                 (*i)->input_icon.hide();
2866         }
2867
2868         /* now set which icons need to be displayed */
2869         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
2870                 (*i)->output_routing_icon.copy_state ((*i)->routing_icon);
2871
2872                 if ((*i)->routing_icon.in_identity ()) {
2873                         (*i)->routing_icon.hide();
2874                         if (i == children.begin()) {
2875                                 (*i)->input_icon.show();
2876                         }
2877                 } else {
2878                         (*i)->routing_icon.show();
2879                         (*i)->routing_icon.queue_draw();
2880                         (*i)->input_icon.show();
2881                 }
2882
2883                 list<ProcessorEntry*>::iterator next = i;
2884                 if (++next == children.end()) {
2885                         // last processor in the chain
2886                         (*i)->output_routing_icon.set_terminal(true);
2887                         (*i)->output_routing_icon.unset_feeding ();
2888                         if ((*i)->routing_icon.out_identity ()) {
2889                                 (*i)->output_routing_icon.hide();
2890                         } else {
2891                                 (*i)->output_routing_icon.show();
2892                                 (*i)->output_routing_icon.queue_draw();
2893                         }
2894                 } else {
2895                         (*i)->output_routing_icon.set_terminal(false);
2896                         if (   !(*i)->routing_icon.out_identity ()
2897                                         && !(*next)->routing_icon.in_identity ()
2898                                         &&  (*next)->routing_icon.can_coalesce ()) {
2899                                 (*i)->output_routing_icon.hide();
2900                         } else if (!(*i)->routing_icon.out_identity ()) {
2901                                 (*i)->output_routing_icon.show();
2902                                 (*i)->output_routing_icon.queue_draw();
2903                                 (*next)->input_icon.show();
2904                         } else {
2905                                 (*i)->output_routing_icon.hide();
2906                         }
2907                 }
2908         }
2909 }
2910
2911 void
2912 ProcessorBox::setup_entry_positions ()
2913 {
2914         list<ProcessorEntry*> children = processor_display.children ();
2915         bool pre_fader = true;
2916
2917         uint32_t num = 0;
2918         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
2919                 if (boost::dynamic_pointer_cast<Amp>((*i)->processor()) &&
2920                     boost::dynamic_pointer_cast<Amp>((*i)->processor())->gain_control()->parameter().type() == GainAutomation) {
2921                         pre_fader = false;
2922                         (*i)->set_position (ProcessorEntry::Fader, num++);
2923                 } else {
2924                         if (pre_fader) {
2925                                 (*i)->set_position (ProcessorEntry::PreFader, num++);
2926                         } else {
2927                                 (*i)->set_position (ProcessorEntry::PostFader, num++);
2928                         }
2929                 }
2930         }
2931         setup_routing_feeds ();
2932 }
2933
2934 void
2935 ProcessorBox::compute_processor_sort_keys ()
2936 {
2937         list<ProcessorEntry*> children = processor_display.children ();
2938         Route::ProcessorList our_processors;
2939
2940         for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
2941                 if ((*i)->processor()) {
2942                         our_processors.push_back ((*i)->processor ());
2943                 }
2944         }
2945
2946         if (_route->reorder_processors (our_processors)) {
2947                 /* Reorder failed, so report this to the user.  As far as I can see this must be done
2948                    in an idle handler: it seems that the redisplay_processors() that happens below destroys
2949                    widgets that were involved in the drag-and-drop on the processor list, which causes problems
2950                    when the drag is torn down after this handler function is finished.
2951                 */
2952                 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder));
2953         }
2954 }
2955
2956 void
2957 ProcessorBox::report_failed_reorder ()
2958 {
2959         /* reorder failed, so redisplay */
2960
2961         redisplay_processors ();
2962
2963         /* now tell them about the problem */
2964
2965         ArdourDialog dialog (_("Plugin Incompatibility"));
2966         Label label;
2967
2968         label.set_text (_("\
2969 You cannot reorder these plugins/sends/inserts\n\
2970 in that way because the inputs and\n\
2971 outputs will not work correctly."));
2972
2973         dialog.get_vbox()->set_border_width (12);
2974         dialog.get_vbox()->pack_start (label);
2975         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
2976
2977         dialog.set_name (X_("PluginIODialog"));
2978         dialog.set_modal (true);
2979         dialog.show_all ();
2980
2981         dialog.run ();
2982 }
2983
2984 void
2985 ProcessorBox::rename_processors ()
2986 {
2987         ProcSelection to_be_renamed;
2988
2989         get_selected_processors (to_be_renamed);
2990
2991         if (to_be_renamed.empty()) {
2992                 return;
2993         }
2994
2995         for (ProcSelection::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
2996                 rename_processor (*i);
2997         }
2998 }
2999
3000 bool
3001 ProcessorBox::can_cut () const
3002 {
3003         vector<boost::shared_ptr<Processor> > sel;
3004
3005         get_selected_processors (sel);
3006
3007         /* cut_processors () does not cut inserts */
3008
3009         for (vector<boost::shared_ptr<Processor> >::const_iterator i = sel.begin (); i != sel.end (); ++i) {
3010
3011                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
3012                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
3013                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
3014                         return true;
3015                 }
3016         }
3017
3018         return false;
3019 }
3020
3021 bool
3022 ProcessorBox::stub_processor_selected () const
3023 {
3024         vector<boost::shared_ptr<Processor> > sel;
3025
3026         get_selected_processors (sel);
3027
3028         for (vector<boost::shared_ptr<Processor> >::const_iterator i = sel.begin (); i != sel.end (); ++i) {
3029                 if (boost::dynamic_pointer_cast<UnknownProcessor>((*i)) != 0) {
3030                         return true;
3031                 }
3032         }
3033
3034         return false;
3035 }
3036
3037 void
3038 ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
3039 {
3040         if (to_be_removed.empty()) {
3041                 return;
3042         }
3043
3044         XMLNode* node = new XMLNode (X_("cut"));
3045         Route::ProcessorList to_cut;
3046
3047         no_processor_redisplay = true;
3048         for (ProcSelection::const_iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
3049                 // Cut only plugins, sends and returns
3050                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
3051                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
3052                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
3053
3054                         Window* w = get_processor_ui (*i);
3055
3056                         if (w) {
3057                                 w->hide ();
3058                         }
3059
3060                         XMLNode& child ((*i)->get_state());
3061                         node->add_child_nocopy (child);
3062                         to_cut.push_back (*i);
3063                 }
3064         }
3065
3066         if (_route->remove_processors (to_cut) != 0) {
3067                 delete node;
3068                 no_processor_redisplay = false;
3069                 return;
3070         }
3071
3072         _p_selection.set (node);
3073
3074         no_processor_redisplay = false;
3075         redisplay_processors ();
3076 }
3077
3078 void
3079 ProcessorBox::copy_processors (const ProcSelection& to_be_copied)
3080 {
3081         if (to_be_copied.empty()) {
3082                 return;
3083         }
3084
3085         XMLNode* node = new XMLNode (X_("copy"));
3086
3087         for (ProcSelection::const_iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
3088                 // Copy only plugins, sends, returns
3089                 if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
3090                     (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
3091                     (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
3092                         node->add_child_nocopy ((*i)->get_state());
3093                 }
3094         }
3095
3096         _p_selection.set (node);
3097 }
3098
3099 void
3100 ProcessorBox::delete_processors (const ProcSelection& targets)
3101 {
3102         if (targets.empty()) {
3103                 return;
3104         }
3105
3106         no_processor_redisplay = true;
3107
3108         for (ProcSelection::const_iterator i = targets.begin(); i != targets.end(); ++i) {
3109
3110                 Window* w = get_processor_ui (*i);
3111
3112                 if (w) {
3113                         w->hide ();
3114                 }
3115
3116                 _route->remove_processor(*i);
3117         }
3118
3119         no_processor_redisplay = false;
3120         redisplay_processors ();
3121 }
3122
3123 void
3124 ProcessorBox::delete_dragged_processors (const list<boost::shared_ptr<Processor> >& procs)
3125 {
3126         list<boost::shared_ptr<Processor> >::const_iterator x;
3127
3128         no_processor_redisplay = true;
3129         for (x = procs.begin(); x != procs.end(); ++x) {
3130
3131                 Window* w = get_processor_ui (*x);
3132
3133                 if (w) {
3134                         w->hide ();
3135                 }
3136
3137                 _route->remove_processor(*x);
3138         }
3139
3140         no_processor_redisplay = false;
3141         redisplay_processors ();
3142 }
3143
3144 gint
3145 ProcessorBox::idle_delete_processor (boost::weak_ptr<Processor> weak_processor)
3146 {
3147         boost::shared_ptr<Processor> processor (weak_processor.lock());
3148
3149         if (!processor) {
3150                 return false;
3151         }
3152
3153         /* NOT copied to _mixer.selection() */
3154
3155         no_processor_redisplay = true;
3156         _route->remove_processor (processor);
3157         no_processor_redisplay = false;
3158         redisplay_processors ();
3159
3160         return false;
3161 }
3162
3163 void
3164 ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
3165 {
3166         Prompter name_prompter (true);
3167         string result;
3168         name_prompter.set_title (_("Rename Processor"));
3169         name_prompter.set_prompt (_("New name:"));
3170         name_prompter.set_initial_text (processor->name());
3171         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
3172         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
3173         name_prompter.show_all ();
3174
3175         switch (name_prompter.run ()) {
3176
3177         case Gtk::RESPONSE_ACCEPT:
3178                 name_prompter.get_result (result);
3179                 if (result.length()) {
3180
3181                         int tries = 0;
3182                         string test = result;
3183
3184                         while (tries < 100) {
3185                                 if (_session->io_name_is_legal (test)) {
3186                                         result = test;
3187                                         break;
3188                                 }
3189                                 tries++;
3190
3191                                 test = string_compose ("%1-%2", result, tries);
3192                         }
3193
3194                         if (tries < 100) {
3195                                 processor->set_name (result);
3196                         } else {
3197                                 /* unlikely! */
3198                                 ARDOUR_UI::instance()->popup_error
3199                                        (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result));
3200                         }
3201                 }
3202                 break;
3203         }
3204
3205         return;
3206 }
3207
3208 void
3209 ProcessorBox::paste_processors ()
3210 {
3211         if (_p_selection.processors.empty()) {
3212                 return;
3213         }
3214
3215         paste_processor_state (_p_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
3216 }
3217
3218 void
3219 ProcessorBox::paste_processors (boost::shared_ptr<Processor> before)
3220 {
3221
3222         if (_p_selection.processors.empty()) {
3223                 return;
3224         }
3225
3226         paste_processor_state (_p_selection.processors.get_node().children(), before);
3227 }
3228
3229 void
3230 ProcessorBox::paste_processor_state (const XMLNodeList& nlist, boost::shared_ptr<Processor> p)
3231 {
3232         XMLNodeConstIterator niter;
3233         list<boost::shared_ptr<Processor> > copies;
3234
3235         if (nlist.empty()) {
3236                 return;
3237         }
3238
3239         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
3240
3241                 XMLProperty const * type = (*niter)->property ("type");
3242                 XMLProperty const * role = (*niter)->property ("role");
3243                 assert (type);
3244
3245                 boost::shared_ptr<Processor> p;
3246                 try {
3247                         if (type->value() == "meter" ||
3248                             type->value() == "main-outs" ||
3249                             type->value() == "amp" ||
3250                             type->value() == "intreturn") {
3251                                 /* do not paste meter, main outs, amp or internal returns */
3252                                 continue;
3253
3254                         } else if (type->value() == "intsend") {
3255
3256                                 /* aux sends are OK, but those used for
3257                                  * other purposes, are not.
3258                                  */
3259
3260                                 assert (role);
3261
3262                                 if (role->value() != "Aux") {
3263                                         continue;
3264                                 }
3265
3266                                 boost::shared_ptr<Pannable> sendpan(new Pannable (*_session));
3267                                 XMLNode n (**niter);
3268                                 InternalSend* s = new InternalSend (*_session, sendpan, _route->mute_master(),
3269                                                 _route, boost::shared_ptr<Route>(), Delivery::Aux);
3270
3271                                 IOProcessor::prepare_for_reset (n, s->name());
3272
3273                                 if (s->set_state (n, Stateful::loading_state_version)) {
3274                                         delete s;
3275                                         return;
3276                                 }
3277
3278                                 p.reset (s);
3279
3280                         } else if (type->value() == "send") {
3281
3282                                 boost::shared_ptr<Pannable> sendpan(new Pannable (*_session));
3283                                 XMLNode n (**niter);
3284
3285                                 Send* s = new Send (*_session, _route->pannable(), _route->mute_master());
3286
3287                                 IOProcessor::prepare_for_reset (n, s->name());
3288
3289                                 if (s->set_state (n, Stateful::loading_state_version)) {
3290                                         delete s;
3291                                         return;
3292                                 }
3293
3294                                 p.reset (s);
3295
3296                         } else if (type->value() == "return") {
3297
3298                                 XMLNode n (**niter);
3299                                 Return* r = new Return (*_session);
3300
3301                                 IOProcessor::prepare_for_reset (n, r->name());
3302
3303                                 if (r->set_state (n, Stateful::loading_state_version)) {
3304                                         delete r;
3305                                         return;
3306                                 }
3307
3308                                 p.reset (r);
3309
3310                         } else if (type->value() == "port") {
3311
3312                                 XMLNode n (**niter);
3313                                 PortInsert* pi = new PortInsert (*_session, _route->pannable (), _route->mute_master ());
3314
3315                                 IOProcessor::prepare_for_reset (n, pi->name());
3316
3317                                 if (pi->set_state (n, Stateful::loading_state_version)) {
3318                                         return;
3319                                 }
3320
3321                                 p.reset (pi);
3322                         } else {
3323                                 /* XXX its a bit limiting to assume that everything else
3324                                    is a plugin.
3325                                 */
3326                                 p.reset (new PluginInsert (*_session));
3327                                 /* we can't use RAII Stateful::ForceIDRegeneration
3328                                  * because that'd void copying the state and wrongly bump
3329                                  * the state-version counter.
3330                                  * we need to load the state (incl external files) first and
3331                                  * only then update the ID)
3332                                  */
3333                                 PBD::ID id = p->id();
3334                                 /* strip side-chain state (processor inside processor must be a side-chain)
3335                                  * otherwise we'll end up with duplicate ports-names.
3336                                  * (this needs a better solution which retains connections)
3337                                  * We really would want Stateful::ForceIDRegeneration here :(
3338                                  */
3339                                 XMLNode state (**niter);
3340                                 state.remove_nodes_and_delete ("Processor");
3341
3342                                 p->set_state (state, Stateful::current_state_version);
3343                                 boost::dynamic_pointer_cast<PluginInsert>(p)->update_id (id);
3344                         }
3345
3346                         copies.push_back (p);
3347                 }
3348
3349                 catch (...) {
3350                         error << _("plugin insert constructor failed") << endmsg;
3351                 }
3352         }
3353
3354         if (copies.empty()) {
3355                 return;
3356         }
3357
3358         if (_route->add_processors (copies, p)) {
3359
3360                 string msg = _(
3361                         "Copying the set of processors on the clipboard failed,\n\
3362 probably because the I/O configuration of the plugins\n\
3363 could not match the configuration of this track.");
3364                 MessageDialog am (msg);
3365                 am.run ();
3366         }
3367 }
3368
3369 void
3370 ProcessorBox::get_selected_processors (ProcSelection& processors) const
3371 {
3372         const list<ProcessorEntry*> selection = processor_display.selection (true);
3373         for (list<ProcessorEntry*>::const_iterator i = selection.begin(); i != selection.end(); ++i) {
3374                 processors.push_back ((*i)->processor ());
3375         }
3376 }
3377
3378 void
3379 ProcessorBox::for_selected_processors (void (ProcessorBox::*method)(boost::shared_ptr<Processor>))
3380 {
3381         list<ProcessorEntry*> selection = processor_display.selection ();
3382         for (list<ProcessorEntry*>::iterator i = selection.begin(); i != selection.end(); ++i) {
3383                 (this->*method) ((*i)->processor ());
3384         }
3385 }
3386
3387 void
3388 ProcessorBox::all_visible_processors_active (bool state)
3389 {
3390         _route->all_visible_processors_active (state);
3391 }
3392
3393 void
3394 ProcessorBox::ab_plugins ()
3395 {
3396         _route->ab_plugins (ab_direction);
3397         ab_direction = !ab_direction;
3398 }
3399
3400 void
3401 ProcessorBox::set_disk_io_position (DiskIOPoint diop)
3402 {
3403         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (_route);
3404         if (t) {
3405                 t->set_disk_io_point (diop);
3406         }
3407 }
3408
3409 void
3410 ProcessorBox::clear_processors ()
3411 {
3412         string prompt;
3413         vector<string> choices;
3414
3415         prompt = string_compose (_("Do you really want to remove all processors from %1?\n"
3416                                    "(this cannot be undone)"), _route->name());
3417
3418         choices.push_back (_("Cancel"));
3419         choices.push_back (_("Yes, remove them all"));
3420
3421         ArdourWidgets::Choice prompter (_("Remove processors"), prompt, choices);
3422
3423         if (prompter.run () == 1) {
3424                 _route->clear_processors (PreFader);
3425                 _route->clear_processors (PostFader);
3426         }
3427 }
3428
3429 void
3430 ProcessorBox::clear_processors (Placement p)
3431 {
3432         string prompt;
3433         vector<string> choices;
3434
3435         if (p == PreFader) {
3436                 prompt = string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
3437                                            "(this cannot be undone)"), _route->name());
3438         } else {
3439                 prompt = string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
3440                                            "(this cannot be undone)"), _route->name());
3441         }
3442
3443         choices.push_back (_("Cancel"));
3444         choices.push_back (_("Yes, remove them all"));
3445
3446         ArdourWidgets::Choice prompter (_("Remove processors"), prompt, choices);
3447
3448         if (prompter.run () == 1) {
3449                 _route->clear_processors (p);
3450         }
3451 }
3452
3453 bool
3454 ProcessorBox::processor_can_be_edited (boost::shared_ptr<Processor> processor)
3455 {
3456         boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack> (_route);
3457         if (at && at->freeze_state() == AudioTrack::Frozen) {
3458                 return false;
3459         }
3460
3461         if (
3462                 boost::dynamic_pointer_cast<Send> (processor) ||
3463                 boost::dynamic_pointer_cast<Return> (processor) ||
3464                 boost::dynamic_pointer_cast<PluginInsert> (processor) ||
3465                 boost::dynamic_pointer_cast<PortInsert> (processor)
3466                 ) {
3467                 return true;
3468         }
3469
3470         return false;
3471 }
3472
3473 bool
3474 ProcessorBox::one_processor_can_be_edited ()
3475 {
3476         list<ProcessorEntry*> selection = processor_display.selection ();
3477         list<ProcessorEntry*>::iterator i = selection.begin();
3478         while (i != selection.end() && processor_can_be_edited ((*i)->processor()) == false) {
3479                 ++i;
3480         }
3481
3482         return (i != selection.end());
3483 }
3484
3485 Gtk::Window*
3486 ProcessorBox::get_editor_window (boost::shared_ptr<Processor> processor, bool use_custom)
3487 {
3488         boost::shared_ptr<Send> send;
3489         boost::shared_ptr<InternalSend> internal_send;
3490         boost::shared_ptr<Return> retrn;
3491         boost::shared_ptr<PluginInsert> plugin_insert;
3492         boost::shared_ptr<PortInsert> port_insert;
3493         Window* gidget = 0;
3494
3495         /* This method may or may not return a Window, but if it does not it
3496          * will modify the parent mixer strip appearance layout to allow
3497          * "editing" the @param processor that was passed in.
3498          *
3499          * So for example, if the processor is an Amp (gain), the parent strip
3500          * will be forced back into a model where the fader controls the main gain.
3501          * If the processor is a send, then we map the send controls onto the
3502          * strip.
3503          *
3504          * Plugins and others will return a window for control.
3505          */
3506
3507         if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
3508
3509                 if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) {
3510                         return 0;
3511                 }
3512         }
3513
3514         if (boost::dynamic_pointer_cast<Amp> (processor) && boost::dynamic_pointer_cast<Amp> (processor)->gain_control()->parameter().type() == GainAutomation) {
3515
3516                 if (_parent_strip) {
3517                         _parent_strip->revert_to_default_display ();
3518                 }
3519
3520         } else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
3521
3522                 if (!_session->engine().connected()) {
3523                         return 0;
3524                 }
3525
3526                 if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
3527
3528                         gidget = new SendUIWindow (send, _session);
3529                 }
3530
3531         } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
3532
3533                 if (boost::dynamic_pointer_cast<InternalReturn> (retrn)) {
3534                         /* no GUI for these */
3535                         return 0;
3536                 }
3537
3538                 if (!_session->engine().connected()) {
3539                         return 0;
3540                 }
3541
3542                 boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor);
3543
3544                 ReturnUIWindow *return_ui;
3545                 Window* w = get_processor_ui (retrn);
3546
3547                 if (w == 0) {
3548
3549                         return_ui = new ReturnUIWindow (retrn, _session);
3550                         return_ui->set_title (retrn->name ());
3551                         set_processor_ui (send, return_ui);
3552
3553                 } else {
3554                         return_ui = dynamic_cast<ReturnUIWindow *> (w);
3555                 }
3556
3557                 gidget = return_ui;
3558
3559         } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
3560
3561                 PluginUIWindow *plugin_ui;
3562
3563                 /* these are both allowed to be null */
3564
3565                 Window* w = get_processor_ui (plugin_insert);
3566
3567                 if (w == 0) {
3568                         plugin_ui = new PluginUIWindow (plugin_insert, false, use_custom);
3569                         plugin_ui->set_title (generate_processor_title (plugin_insert));
3570                         set_processor_ui (plugin_insert, plugin_ui);
3571
3572                 } else {
3573                         plugin_ui = dynamic_cast<PluginUIWindow *> (w);
3574                 }
3575
3576                 gidget = plugin_ui;
3577
3578         } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
3579
3580                 if (!_session->engine().connected()) {
3581                         MessageDialog msg ( _("Not connected to audio engine - no I/O changes are possible"));
3582                         msg.run ();
3583                         return 0;
3584                 }
3585
3586                 PortInsertWindow *io_selector;
3587
3588                 Window* w = get_processor_ui (port_insert);
3589
3590                 if (w == 0) {
3591                         io_selector = new PortInsertWindow (_session, port_insert);
3592                         set_processor_ui (port_insert, io_selector);
3593
3594                 } else {
3595                         io_selector = dynamic_cast<PortInsertWindow *> (w);
3596                 }
3597
3598                 gidget = io_selector;
3599         }
3600
3601         return gidget;
3602 }
3603
3604 Gtk::Window*
3605 ProcessorBox::get_generic_editor_window (boost::shared_ptr<Processor> processor)
3606 {
3607         boost::shared_ptr<PluginInsert> plugin_insert
3608                 = boost::dynamic_pointer_cast<PluginInsert>(processor);
3609
3610         if (!plugin_insert) {
3611                 return 0;
3612         }
3613
3614         PluginUIWindow* win = new PluginUIWindow (plugin_insert, true, false);
3615         win->set_title (generate_processor_title (plugin_insert));
3616
3617         return win;
3618 }
3619
3620 void
3621 ProcessorBox::register_actions ()
3622 {
3623         processor_box_actions = myactions.create_action_group (X_("ProcessorMenu"));
3624
3625         Glib::RefPtr<Action> act;
3626
3627         /* new stuff */
3628         myactions.register_action (processor_box_actions, X_("newplugin"), _("New Plugin"),
3629                         sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
3630
3631         act = myactions.register_action (processor_box_actions, X_("newinsert"), _("New Insert"),
3632                         sigc::ptr_fun (ProcessorBox::rb_choose_insert));
3633         ActionManager::engine_sensitive_actions.push_back (act);
3634         act = myactions.register_action (processor_box_actions, X_("newsend"), _("New External Send ..."),
3635                         sigc::ptr_fun (ProcessorBox::rb_choose_send));
3636         ActionManager::engine_sensitive_actions.push_back (act);
3637
3638         myactions.register_action (processor_box_actions, X_("newaux"), _("New Aux Send ..."));
3639
3640         myactions.register_action (processor_box_actions, X_("controls"), _("Controls"));
3641         myactions.register_action (processor_box_actions, X_("send_options"), _("Send Options"));
3642
3643         myactions.register_action (processor_box_actions, X_("clear"), _("Clear (all)"),
3644                         sigc::ptr_fun (ProcessorBox::rb_clear));
3645         myactions.register_action (processor_box_actions, X_("clear_pre"), _("Clear (pre-fader)"),
3646                         sigc::ptr_fun (ProcessorBox::rb_clear_pre));
3647         myactions.register_action (processor_box_actions, X_("clear_post"), _("Clear (post-fader)"),
3648                         sigc::ptr_fun (ProcessorBox::rb_clear_post));
3649
3650         /* standard editing stuff */
3651
3652         cut_action = myactions.register_action (processor_box_actions, X_("cut"), _("Cut"),
3653                                                             sigc::ptr_fun (ProcessorBox::rb_cut));
3654         copy_action = myactions.register_action (processor_box_actions, X_("copy"), _("Copy"),
3655                                                              sigc::ptr_fun (ProcessorBox::rb_copy));
3656         delete_action = myactions.register_action (processor_box_actions, X_("delete"), _("Delete"),
3657                                                                sigc::ptr_fun (ProcessorBox::rb_delete));
3658         backspace_action = myactions.register_action (processor_box_actions, X_("backspace"), _("Delete"),
3659                                                                sigc::ptr_fun (ProcessorBox::rb_delete));
3660
3661         ActionManager::plugin_selection_sensitive_actions.push_back (cut_action);
3662         ActionManager::plugin_selection_sensitive_actions.push_back (copy_action);
3663         ActionManager::plugin_selection_sensitive_actions.push_back (delete_action);
3664         ActionManager::plugin_selection_sensitive_actions.push_back (backspace_action);
3665
3666         paste_action = myactions.register_action (processor_box_actions, X_("paste"), _("Paste"),
3667                         sigc::ptr_fun (ProcessorBox::rb_paste));
3668         rename_action = myactions.register_action (processor_box_actions, X_("rename"), _("Rename"),
3669                         sigc::ptr_fun (ProcessorBox::rb_rename));
3670         myactions.register_action (processor_box_actions, X_("selectall"), _("Select All"),
3671                         sigc::ptr_fun (ProcessorBox::rb_select_all));
3672         myactions.register_action (processor_box_actions, X_("deselectall"), _("Deselect All"),
3673                         sigc::ptr_fun (ProcessorBox::rb_deselect_all));
3674
3675         /* activation etc. */
3676
3677         myactions.register_action (processor_box_actions, X_("activate_all"), _("Activate All"),
3678                         sigc::ptr_fun (ProcessorBox::rb_activate_all));
3679         myactions.register_action (processor_box_actions, X_("deactivate_all"), _("Deactivate All"),
3680                         sigc::ptr_fun (ProcessorBox::rb_deactivate_all));
3681         myactions.register_action (processor_box_actions, X_("ab_plugins"), _("A/B Plugins"),
3682                         sigc::ptr_fun (ProcessorBox::rb_ab_plugins));
3683
3684         manage_pins_action = myactions.register_action (
3685                 processor_box_actions, X_("manage-pins"), _("Pin Connections..."),
3686                 sigc::ptr_fun (ProcessorBox::rb_manage_pins));
3687
3688         /* Disk IO stuff */
3689         disk_io_action = myactions.register_action (processor_box_actions, X_("disk-io-menu"), _("Disk I/O ..."));
3690         myactions.register_action (processor_box_actions, X_("disk-io-prefader"), _("Pre-Fader."), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_set_disk_io_position), DiskIOPreFader));
3691         myactions.register_action (processor_box_actions, X_("disk-io-postfader"), _("Post-Fader."), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_set_disk_io_position), DiskIOPostFader));
3692         myactions.register_action (processor_box_actions, X_("disk-io-custom"), _("Custom."), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_set_disk_io_position), DiskIOCustom));
3693
3694         /* show editors */
3695         edit_action = myactions.register_action (
3696                 processor_box_actions, X_("edit"), _("Edit..."),
3697                 sigc::ptr_fun (ProcessorBox::rb_edit));
3698
3699         edit_generic_action = myactions.register_action (
3700                 processor_box_actions, X_("edit-generic"), _("Edit with generic controls..."),
3701                 sigc::ptr_fun (ProcessorBox::rb_edit_generic));
3702
3703         load_bindings ();
3704 }
3705
3706 void
3707 ProcessorBox::rb_edit_generic ()
3708 {
3709         if (_current_processor_box == 0) {
3710                 return;
3711         }
3712
3713         _current_processor_box->for_selected_processors (&ProcessorBox::generic_edit_processor);
3714 }
3715
3716 void
3717 ProcessorBox::rb_ab_plugins ()
3718 {
3719         if (_current_processor_box == 0) {
3720                 return;
3721         }
3722
3723         _current_processor_box->ab_plugins ();
3724 }
3725
3726 void
3727 ProcessorBox::rb_set_disk_io_position (DiskIOPoint diop)
3728 {
3729         if (_current_processor_box == 0) {
3730                 return;
3731         }
3732
3733         _current_processor_box->set_disk_io_position (diop);
3734 }
3735
3736 void
3737 ProcessorBox::rb_manage_pins ()
3738 {
3739         if (_current_processor_box == 0) {
3740                 return;
3741         }
3742
3743         _current_processor_box->for_selected_processors (&ProcessorBox::manage_pins);
3744 }
3745 void
3746 ProcessorBox::rb_choose_plugin ()
3747 {
3748         if (_current_processor_box == 0) {
3749                 return;
3750         }
3751         _current_processor_box->choose_plugin ();
3752 }
3753
3754 void
3755 ProcessorBox::rb_choose_insert ()
3756 {
3757         if (_current_processor_box == 0) {
3758                 return;
3759         }
3760         _current_processor_box->choose_insert ();
3761 }
3762
3763 void
3764 ProcessorBox::rb_choose_send ()
3765 {
3766         if (_current_processor_box == 0) {
3767                 return;
3768         }
3769         _current_processor_box->choose_send ();
3770 }
3771
3772 void
3773 ProcessorBox::rb_choose_aux (boost::weak_ptr<Route> wr)
3774 {
3775         if (_current_processor_box == 0) {
3776                 return;
3777         }
3778
3779         _current_processor_box->choose_aux (wr);
3780 }
3781
3782 void
3783 ProcessorBox::rb_clear ()
3784 {
3785         if (_current_processor_box == 0) {
3786                 return;
3787         }
3788
3789         _current_processor_box->clear_processors ();
3790 }
3791
3792
3793 void
3794 ProcessorBox::rb_clear_pre ()
3795 {
3796         if (_current_processor_box == 0) {
3797                 return;
3798         }
3799
3800         _current_processor_box->clear_processors (PreFader);
3801 }
3802
3803
3804 void
3805 ProcessorBox::rb_clear_post ()
3806 {
3807         if (_current_processor_box == 0) {
3808                 return;
3809         }
3810
3811         _current_processor_box->clear_processors (PostFader);
3812 }
3813
3814 void
3815 ProcessorBox::rb_cut ()
3816 {
3817         if (_current_processor_box == 0) {
3818                 return;
3819         }
3820
3821         _current_processor_box->processor_operation (ProcessorsCut);
3822 }
3823
3824 void
3825 ProcessorBox::rb_delete ()
3826 {
3827         if (_current_processor_box == 0) {
3828                 return;
3829         }
3830
3831         _current_processor_box->processor_operation (ProcessorsDelete);
3832 }
3833
3834 void
3835 ProcessorBox::rb_copy ()
3836 {
3837         if (_current_processor_box == 0) {
3838                 return;
3839         }
3840         _current_processor_box->processor_operation (ProcessorsCopy);
3841 }
3842
3843 void
3844 ProcessorBox::rb_paste ()
3845 {
3846         if (_current_processor_box == 0) {
3847                 return;
3848         }
3849
3850         _current_processor_box->processor_operation (ProcessorsPaste);
3851 }
3852
3853 void
3854 ProcessorBox::rb_rename ()
3855 {
3856         if (_current_processor_box == 0) {
3857                 return;
3858         }
3859         _current_processor_box->rename_processors ();
3860 }
3861
3862 void
3863 ProcessorBox::rb_select_all ()
3864 {
3865         if (_current_processor_box == 0) {
3866                 return;
3867         }
3868
3869         _current_processor_box->processor_operation (ProcessorsSelectAll);
3870 }
3871
3872 void
3873 ProcessorBox::rb_deselect_all ()
3874 {
3875         if (_current_processor_box == 0) {
3876                 return;
3877         }
3878
3879         _current_processor_box->deselect_all_processors ();
3880 }
3881
3882 void
3883 ProcessorBox::rb_activate_all ()
3884 {
3885         if (_current_processor_box == 0) {
3886                 return;
3887         }
3888
3889         _current_processor_box->all_visible_processors_active (true);
3890 }
3891
3892 void
3893 ProcessorBox::rb_deactivate_all ()
3894 {
3895         if (_current_processor_box == 0) {
3896                 return;
3897         }
3898         _current_processor_box->all_visible_processors_active (false);
3899 }
3900
3901 void
3902 ProcessorBox::rb_edit ()
3903 {
3904         if (_current_processor_box == 0) {
3905                 return;
3906         }
3907
3908         _current_processor_box->for_selected_processors (&ProcessorBox::edit_processor);
3909 }
3910
3911 bool
3912 ProcessorBox::edit_aux_send (boost::shared_ptr<Processor> processor)
3913 {
3914         if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
3915                 return false;
3916         }
3917
3918         if (_parent_strip) {
3919                 boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
3920                 if (_parent_strip->current_delivery() == send) {
3921                         _parent_strip->revert_to_default_display ();
3922                 } else {
3923                         _parent_strip->show_send(send);
3924                 }
3925         }
3926         return true;
3927 }
3928
3929 void
3930 ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
3931 {
3932         if (!processor) {
3933                 return;
3934         }
3935         if (edit_aux_send (processor)) {
3936                 return;
3937         }
3938         if (!_session->engine().connected()) {
3939                 return;
3940         }
3941
3942         ProcessorWindowProxy* proxy = find_window_proxy (processor);
3943
3944         if (proxy) {
3945                 proxy->set_custom_ui_mode (true);
3946                 proxy->show_the_right_window ();
3947         }
3948 }
3949
3950 void
3951 ProcessorBox::generic_edit_processor (boost::shared_ptr<Processor> processor)
3952 {
3953         if (!processor) {
3954                 return;
3955         }
3956         if (edit_aux_send (processor)) {
3957                 return;
3958         }
3959         if (!_session->engine().connected()) {
3960                 return;
3961         }
3962
3963         ProcessorWindowProxy* proxy = find_window_proxy (processor);
3964
3965         if (proxy) {
3966                 proxy->set_custom_ui_mode (false);
3967                 proxy->show_the_right_window ();
3968         }
3969 }
3970
3971 void
3972 ProcessorBox::manage_pins (boost::shared_ptr<Processor> processor)
3973 {
3974         if (!processor) {
3975                 return;
3976         }
3977         PluginPinWindowProxy* proxy = processor->pinmgr_proxy ();
3978         if (proxy) {
3979                 proxy->get (true);
3980                 proxy->present();
3981         }
3982 }
3983
3984
3985 void
3986 ProcessorBox::route_property_changed (const PropertyChange& what_changed)
3987 {
3988         if (!what_changed.contains (ARDOUR::Properties::name)) {
3989                 return;
3990         }
3991
3992         ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed, what_changed);
3993
3994         boost::shared_ptr<Processor> processor;
3995         boost::shared_ptr<PluginInsert> plugin_insert;
3996         boost::shared_ptr<Send> send;
3997
3998         list<ProcessorEntry*> children = processor_display.children();
3999
4000         for (list<ProcessorEntry*>::iterator iter = children.begin(); iter != children.end(); ++iter) {
4001
4002                 processor = (*iter)->processor ();
4003
4004                 if (!processor) {
4005                         continue;
4006                 }
4007
4008                 Window* w = get_processor_ui (processor);
4009
4010                 if (!w) {
4011                         continue;
4012                 }
4013
4014                 /* rename editor windows for sends and plugins */
4015
4016                 if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
4017                         w->set_title (send->name ());
4018                 } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
4019                         w->set_title (generate_processor_title (plugin_insert));
4020                 }
4021         }
4022 }
4023
4024 string
4025 ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
4026 {
4027         string maker = pi->plugin()->maker() ? pi->plugin()->maker() : "";
4028         string::size_type email_pos;
4029
4030         if ((email_pos = maker.find_first_of ('<')) != string::npos) {
4031                 maker = maker.substr (0, email_pos - 1);
4032         }
4033
4034         if (maker.length() > 32) {
4035                 maker = maker.substr (0, 32);
4036                 maker += " ...";
4037         }
4038
4039         SessionObject* owner = pi->owner();
4040
4041         if (owner) {
4042                 return string_compose(_("%1: %2 (by %3)"), owner->name(), pi->name(), maker);
4043         } else {
4044                 return string_compose(_("%1 (by %2)"), pi->name(), maker);
4045         }
4046 }
4047
4048 /** @param p Processor.
4049  *  @return the UI window for \a p.
4050  */
4051 Window *
4052 ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const
4053 {
4054         ProcessorWindowProxy* wp = p->window_proxy();
4055         if (wp) {
4056                 return wp->get ();
4057         }
4058         return 0;
4059 }
4060
4061 /** Make a note of the UI window that a processor is using.
4062  *  @param p Processor.
4063  *  @param w UI window.
4064  */
4065 void
4066 ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w)
4067 {
4068         assert (p->window_proxy());
4069         p->window_proxy()->use_window (*w);
4070 }
4071
4072 void
4073 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr<Delivery> w)
4074 {
4075         boost::shared_ptr<Delivery> d = w.lock ();
4076         if (!d) {
4077                 return;
4078         }
4079
4080         list<ProcessorEntry*> children = processor_display.children ();
4081         list<ProcessorEntry*>::const_iterator i = children.begin();
4082         while (i != children.end() && (*i)->processor() != d) {
4083                 ++i;
4084         }
4085
4086         if (i == children.end()) {
4087                 processor_display.set_active (0);
4088         } else {
4089                 processor_display.set_active (*i);
4090         }
4091 }
4092
4093 /** Called to repair the damage of Editor::show_window doing a show_all() */
4094 void
4095 ProcessorBox::hide_things ()
4096 {
4097         list<ProcessorEntry*> c = processor_display.children ();
4098         for (list<ProcessorEntry*>::iterator i = c.begin(); i != c.end(); ++i) {
4099                 (*i)->hide_things ();
4100         }
4101 }
4102
4103 void
4104 ProcessorBox::processor_menu_unmapped ()
4105 {
4106         processor_display.remove_placeholder ();
4107         /* make all possibly-desensitized actions sensitive again so that
4108            they be activated by other means (e.g. bindings)
4109         */
4110         ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions, true);
4111 }
4112
4113 XMLNode *
4114 ProcessorBox::entry_gui_object_state (ProcessorEntry* entry)
4115 {
4116         if (!_parent_strip) {
4117                 return 0;
4118         }
4119
4120         GUIObjectState& st = _parent_strip->gui_object_state ();
4121
4122         XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
4123         assert (strip);
4124         return st.get_or_add_node (strip, entry->state_id());
4125 }
4126
4127 void
4128 ProcessorBox::update_gui_object_state (ProcessorEntry* entry)
4129 {
4130         XMLNode* proc = entry_gui_object_state (entry);
4131         if (!proc) {
4132                 return;
4133         }
4134
4135         /* XXX: this is a bit inefficient; we just remove all child nodes and re-add them */
4136         proc->remove_nodes_and_delete (X_("Object"));
4137         entry->add_control_state (proc);
4138 }
4139
4140 bool
4141 ProcessorBox::is_editor_mixer_strip() const
4142 {
4143         return _parent_strip && !_parent_strip->mixer_owned();
4144 }
4145
4146 ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* box, boost::weak_ptr<Processor> processor)
4147         : WM::ProxyBase (name, string())
4148         , _processor_box (box)
4149         , _processor (processor)
4150         , is_custom (true)
4151         , want_custom (true)
4152 {
4153         boost::shared_ptr<Processor> p = _processor.lock ();
4154         if (!p) {
4155                 return;
4156         }
4157         p->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&ProcessorWindowProxy::processor_going_away, this), gui_context());
4158
4159         p->ToggleUI.connect (gui_connections, invalidator (*this), boost::bind (&ProcessorWindowProxy::show_the_right_window, this, false), gui_context());
4160         p->ShowUI.connect (gui_connections, invalidator (*this), boost::bind (&ProcessorWindowProxy::show_the_right_window, this, true), gui_context());
4161         p->HideUI.connect (gui_connections, invalidator (*this), boost::bind (&ProcessorWindowProxy::hide, this), gui_context());
4162 }
4163
4164 ProcessorWindowProxy::~ProcessorWindowProxy()
4165 {
4166         /* processor window proxies do not own the windows they create with
4167          * ::get(), so set _window to null before the normal WindowProxy method
4168          * deletes it.
4169          */
4170         _window = 0;
4171 }
4172
4173 void
4174 ProcessorWindowProxy::processor_going_away ()
4175 {
4176         gui_connections.drop_connections ();
4177         delete _window;
4178         _window = 0;
4179         WM::Manager::instance().remove (this);
4180         /* should be no real reason to do this, since the object that would
4181            send DropReferences is about to be deleted, but lets do it anyway.
4182         */
4183         going_away_connection.disconnect();
4184         delete this;
4185 }
4186
4187 ARDOUR::SessionHandlePtr*
4188 ProcessorWindowProxy::session_handle()
4189 {
4190         /* we don't care */
4191         return 0;
4192 }
4193
4194 XMLNode&
4195 ProcessorWindowProxy::get_state ()
4196 {
4197         XMLNode *node;
4198         node = &ProxyBase::get_state();
4199         node->set_property (X_("custom-ui"), is_custom);
4200         return *node;
4201 }
4202
4203 int
4204 ProcessorWindowProxy::set_state (const XMLNode& node, int /*version*/)
4205 {
4206         XMLNodeList children = node.children ();
4207         XMLNodeList::const_iterator i = children.begin ();
4208         while (i != children.end()) {
4209                 std::string name;
4210                 if ((*i)->name() == X_("Window") && (*i)->get_property (X_("name"), name) && name == _name) {
4211                         break;
4212                 }
4213                 ++i;
4214         }
4215
4216         if (i != children.end()) {
4217                 (*i)->get_property (X_("custom-ui"), want_custom);
4218         }
4219
4220         return ProxyBase::set_state (node, 0);
4221 }
4222
4223 Gtk::Window*
4224 ProcessorWindowProxy::get (bool create)
4225 {
4226         boost::shared_ptr<Processor> p = _processor.lock ();
4227
4228         if (!p) {
4229                 return 0;
4230         }
4231         if (_window && (is_custom != want_custom)) {
4232                 /* drop existing window - wrong type */
4233                 set_state_mask (Gtkmm2ext::WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
4234                 drop_window ();
4235         }
4236
4237         if (!_window) {
4238                 if (!create) {
4239                         return 0;
4240                 }
4241
4242                 is_custom = want_custom;
4243                 _window = _processor_box->get_editor_window (p, is_custom);
4244
4245                 if (_window) {
4246                         setup ();
4247                         _window->show_all ();
4248                 }
4249         }
4250         return _window;
4251 }
4252
4253 void
4254 ProcessorWindowProxy::show_the_right_window (bool show_not_toggle)
4255 {
4256         if (_window && (is_custom != want_custom)) {
4257                 /* drop existing window - wrong type */
4258                 set_state_mask (Gtkmm2ext::WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
4259                 drop_window ();
4260         }
4261         if (_window && fully_visible () && show_not_toggle) {
4262                 return;
4263         }
4264         toggle ();
4265 }
4266
4267
4268 PluginPinWindowProxy::PluginPinWindowProxy(std::string const &name, boost::weak_ptr<ARDOUR::Processor> processor)
4269         : WM::ProxyBase (name, string())
4270         , _processor (processor)
4271 {
4272         boost::shared_ptr<Processor> p = _processor.lock ();
4273         if (!p) {
4274                 return;
4275         }
4276         p->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&PluginPinWindowProxy::processor_going_away, this), gui_context());
4277 }
4278
4279 PluginPinWindowProxy::~PluginPinWindowProxy()
4280 {
4281         _window = 0;
4282 }
4283
4284 ARDOUR::SessionHandlePtr*
4285 PluginPinWindowProxy::session_handle ()
4286 {
4287         ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
4288         if (aw) { return aw; }
4289         return 0;
4290 }
4291
4292 Gtk::Window*
4293 PluginPinWindowProxy::get (bool create)
4294 {
4295         boost::shared_ptr<Processor> p = _processor.lock ();
4296         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (p);
4297         if (!p || !pi) {
4298                 return 0;
4299         }
4300
4301         if (!_window) {
4302                 if (!create) {
4303                         return 0;
4304                 }
4305                 _window = new PluginPinDialog (pi);
4306                 ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
4307                 if (aw) {
4308                         aw->set_session (_session);
4309                 }
4310                 _window->show_all ();
4311         }
4312         return _window;
4313 }
4314
4315 void
4316 PluginPinWindowProxy::processor_going_away ()
4317 {
4318         delete _window;
4319         _window = 0;
4320         WM::Manager::instance().remove (this);
4321         going_away_connection.disconnect();
4322         delete this;
4323 }
4324
4325 void
4326 ProcessorBox::load_bindings ()
4327 {
4328         bindings = Bindings::get_bindings (X_("Processor Box"), myactions);
4329 }