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