ardour
processor_box.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000-2004 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23 
24 #include <cmath>
25 #include <iostream>
26 #include <set>
27 
28 #include <sigc++/bind.h>
29 
30 #include "pbd/convert.h"
31 
32 #include <glibmm/miscutils.h>
33 
34 #include <gtkmm/messagedialog.h>
35 
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/utils.h>
38 #include <gtkmm2ext/choice.h>
39 #include <gtkmm2ext/utils.h>
40 #include <gtkmm2ext/doi.h>
41 #include <gtkmm2ext/rgb_macros.h>
42 
43 #include "ardour/amp.h"
44 #include "ardour/audio_track.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/internal_return.h"
47 #include "ardour/internal_send.h"
48 #include "ardour/panner_shell.h"
49 #include "ardour/plugin_insert.h"
50 #include "ardour/pannable.h"
51 #include "ardour/port_insert.h"
52 #include "ardour/profile.h"
53 #include "ardour/return.h"
54 #include "ardour/route.h"
55 #include "ardour/send.h"
56 #include "ardour/session.h"
57 #include "ardour/types.h"
58 
59 #include "actions.h"
60 #include "ardour_dialog.h"
61 #include "ardour_ui.h"
62 #include "gui_thread.h"
63 #include "io_selector.h"
64 #include "keyboard.h"
65 #include "mixer_ui.h"
66 #include "mixer_strip.h"
67 #include "plugin_selector.h"
68 #include "plugin_ui.h"
69 #include "port_insert_ui.h"
70 #include "processor_box.h"
71 #include "public_editor.h"
72 #include "return_ui.h"
74 #include "send_ui.h"
75 #include "timers.h"
76 
77 #include "i18n.h"
78 
79 #ifdef AUDIOUNIT_SUPPORT
80 class AUPluginUI;
81 #endif
82 
83 using namespace std;
84 using namespace ARDOUR;
85 using namespace PBD;
86 using namespace Gtk;
87 using namespace Glib;
88 using namespace Gtkmm2ext;
89 
91 RefPtr<Action> ProcessorBox::paste_action;
92 RefPtr<Action> ProcessorBox::cut_action;
93 RefPtr<Action> ProcessorBox::rename_action;
94 RefPtr<Action> ProcessorBox::edit_action;
96 
97 static const uint32_t audio_port_color = 0x4A8A0EFF; // Green
98 static const uint32_t midi_port_color = 0x960909FF; //Red
99 
101  : _button (ArdourButton::led_default_elements)
102  , _position (PreFader)
103  , _position_num(0)
104  , _selectable(true)
105  , _parent (parent)
106  , _processor (p)
107  , _width (w)
108  , _input_icon(true)
109  , _output_icon(false)
110 {
111  _vbox.show ();
112 
115  _button.set_led_left (true);
116  _button.signal_led_clicked.connect (sigc::mem_fun (*this, &ProcessorEntry::led_clicked));
118 
119  if (_processor) {
120 
121  _vbox.pack_start (_routing_icon);
122  _vbox.pack_start (_input_icon);
123  _vbox.pack_start (_button, true, true);
124  _vbox.pack_end (_output_icon);
125 
127 
128  _routing_icon.set_no_show_all(true);
129  _input_icon.set_no_show_all(true);
130 
131  _button.show ();
132  _routing_icon.set_visible(false);
133  _input_icon.hide();
134  _output_icon.show();
135 
139 
140  set<Evoral::Parameter> p = _processor->what_can_be_automated ();
141  for (set<Evoral::Parameter>::iterator i = p.begin(); i != p.end(); ++i) {
142 
143  std::string label = _processor->describe_parameter (*i);
144 
145  if (boost::dynamic_pointer_cast<Send> (_processor)) {
146  label = _("Send");
147  } else if (boost::dynamic_pointer_cast<Return> (_processor)) {
148  label = _("Return");
149  }
150 
151  Control* c = new Control (_processor->automation_control (*i), label);
152 
153  _controls.push_back (c);
154 
155  if (boost::dynamic_pointer_cast<Amp> (_processor) == 0) {
156  /* Add non-Amp controls to the processor box */
157  _vbox.pack_start (c->box);
158  }
159  }
160 
163 
166 
167  setup_tooltip ();
168  setup_visuals ();
169  } else {
170  _vbox.set_size_request (-1, _button.size_request().height);
171  }
172 }
173 
175 {
176  for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
177  delete *i;
178  }
179 }
180 
181 EventBox&
183 {
184  return _button;
185 }
186 
187 Gtk::Widget&
189 {
190  return _vbox;
191 }
192 
193 string
195 {
196  return name (Wide);
197 }
198 
199 void
201 {
202  _position = p;
203  _position_num = num;
204 
205  if (_position_num == 0 || _routing_icon.get_visible()) {
206  _input_icon.show();
207  } else {
208  _input_icon.hide();
209  }
210 
211  setup_visuals ();
212 }
213 
214 void
215 ProcessorEntry::set_visual_state (Gtkmm2ext::VisualState s, bool yn)
216 {
217  if (yn) {
218  _button.set_visual_state (Gtkmm2ext::VisualState (_button.visual_state() | s));
219  } else {
220  _button.set_visual_state (Gtkmm2ext::VisualState (_button.visual_state() & ~s));
221  }
222 }
223 
224 void
226 {
227  switch (_position) {
228  case PreFader:
229  _button.set_name ("processor prefader");
230  break;
231 
232  case Fader:
233  _button.set_name ("processor fader");
234  break;
235 
236  case PostFader:
237  _button.set_name ("processor postfader");
238  break;
239  }
240 }
241 
242 
245 {
246  return _processor;
247 }
248 
249 void
251 {
252  _width = w;
254 }
255 
256 void
258 {
259  if (_processor) {
260  if (_button.get_active ()) {
262  } else {
263  _processor->activate ();
264  }
265  }
266 }
267 
268 void
270 {
271  if (_processor) {
273  }
274 }
275 
276 void
278 {
279  if (what_changed.contains (ARDOUR::Properties::name)) {
281  setup_tooltip ();
282  }
283 }
284 
285 void
287 {
289  _output_icon.set_ports(out);
292  _input_icon.queue_draw();
293  _output_icon.queue_draw();
294  _routing_icon.queue_draw();
295 }
296 
297 void
299 {
300  if (_processor) {
302  if (pi) {
303  std::string postfix = "";
304  uint32_t replicated;
305  if ((replicated = pi->get_count()) > 1) {
306  postfix = string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
307  }
308  if (pi->plugin()->has_editor()) {
310  string_compose (_("<b>%1</b>\nDouble-click to show GUI.\nAlt+double-click to show generic GUI.%2"), name (Wide), postfix));
311  } else {
313  string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), name (Wide), postfix));
314  }
315  return;
316  }
317  }
319 }
320 
321 string
323 {
325  string name_display;
326 
327  if (!_processor) {
328  return string();
329  }
330 
331  if ((send = boost::dynamic_pointer_cast<Send> (_processor)) != 0 &&
332  !boost::dynamic_pointer_cast<InternalSend>(_processor)) {
333 
334  name_display += '>';
335 
336  /* grab the send name out of its overall name */
337 
338  string::size_type lbracket, rbracket;
339  lbracket = send->name().find ('[');
340  rbracket = send->name().find (']');
341 
342  switch (w) {
343  case Wide:
344  name_display += send->name().substr (lbracket+1, lbracket-rbracket-1);
345  break;
346  case Narrow:
347  name_display += PBD::short_version (send->name().substr (lbracket+1, lbracket-rbracket-1), 4);
348  break;
349  }
350 
351  } else {
353  uint32_t replicated;
354  if ((pi = boost::dynamic_pointer_cast<ARDOUR::PluginInsert> (_processor)) != 0
355  && (replicated = pi->get_count()) > 1)
356  {
357  name_display += string_compose(_("(%1x1) "), replicated);
358  }
359 
360  switch (w) {
361  case Wide:
362  name_display += _processor->display_name();
363  break;
364  case Narrow:
365  name_display += PBD::short_version (_processor->display_name(), 5);
366  break;
367  }
368 
369  }
370 
371  return name_display;
372 }
373 
374 void
376 {
377  for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
378  (*i)->set_visible (true);
379  }
380 
382 }
383 
384 void
386 {
387  for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
388  (*i)->set_visible (false);
389  }
390 
392 }
393 
394 void
396 {
397  for (list<Control*>::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
398  (*i)->add_state (node);
399  }
400 }
401 
402 void
404 {
405  for (list<Control*>::const_iterator i = _controls.begin(); i != _controls.end(); ++i) {
406  (*i)->set_state (node);
407  }
408 }
409 
410 string
412 {
413  return string_compose ("processor %1", _processor->id().to_s());
414 }
415 
416 void
418 {
419  for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
420  (*i)->hide_things ();
421  }
422 }
423 
424 
425 Menu *
427 {
428  using namespace Menu_Helpers;
429  Menu* menu = manage (new Menu);
430  MenuList& items = menu->items ();
431 
432  items.push_back (
433  MenuElem (_("Show All Controls"), sigc::mem_fun (*this, &ProcessorEntry::show_all_controls))
434  );
435 
436  items.push_back (
437  MenuElem (_("Hide All Controls"), sigc::mem_fun (*this, &ProcessorEntry::hide_all_controls))
438  );
439 
440  if (!_controls.empty ()) {
441  items.push_back (SeparatorElem ());
442  }
443 
444  for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
445  items.push_back (CheckMenuElem ((*i)->name ()));
446  Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
447  c->set_active ((*i)->visible ());
448  c->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ProcessorEntry::toggle_control_visibility), *i));
449  }
450 
451  return menu;
452 }
453 
454 void
456 {
457  c->set_visible (!c->visible ());
459 }
460 
461 Menu *
463 {
464  using namespace Menu_Helpers;
465  Menu* menu = manage (new Menu);
466  MenuList& items = menu->items ();
467 
469  if (send) {
470 
471  items.push_back (CheckMenuElem (_("Link panner controls")));
472  Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
473  c->set_active (send->panner_shell()->is_linked_to_route());
474  c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
475 
476  }
477  return menu;
478 }
479 
480 void
482 {
484  if (send) {
485  send->panner_shell()->set_linked_to_route(!send->panner_shell()->is_linked_to_route());
486  }
487 }
488 
490  : _control (c)
491  , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
492  , _slider (&_adjustment, boost::shared_ptr<PBD::Controllable>(), 0, max(13.f, rintf(13.f * ARDOUR_UI::ui_scale)))
493  , _slider_persistant_tooltip (&_slider)
494  , _button (ArdourButton::led_default_elements)
495  , _ignore_ui_adjustment (false)
496  , _visible (false)
497  , _name (n)
498 {
500  box.set_padding(0, 0, 4, 4);
501 
502  if (c->toggled()) {
504  _button.set_led_left (true);
505  _button.set_name ("processor control button");
506  box.add (_button);
507  _button.show ();
508 
509  _button.signal_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked));
510  _button.signal_led_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked));
511  c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
512 
513  } else {
514 
515  _slider.set_name ("ProcessorControlSlider");
517 
518  box.add (_slider);
519  _slider.show ();
520 
521  const ARDOUR::ParameterDescriptor& desc = c->desc();
522  double const lo = c->internal_to_interface(desc.lower);
523  double const up = c->internal_to_interface(desc.upper);
524  double const normal = c->internal_to_interface(desc.normal);
525  double smallstep = desc.smallstep;
526  double largestep = desc.largestep;
527 
528  if (smallstep == 0.0) {
529  smallstep = up / 1000.;
530  } else {
531  smallstep = c->internal_to_interface(desc.lower + smallstep);
532  }
533 
534  if (largestep == 0.0) {
535  largestep = up / 40.;
536  } else {
537  largestep = c->internal_to_interface(desc.lower + largestep);
538  }
539 
540  _adjustment.set_lower (lo);
541  _adjustment.set_upper (up);
542  _adjustment.set_step_increment (smallstep);
543  _adjustment.set_page_increment (largestep);
544  _slider.set_default_value (normal);
545 
546  _adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &Control::slider_adjusted));
547  c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
548  }
549 
550  Timers::rapid_connect (sigc::mem_fun (*this, &Control::control_changed));
551 
552  control_changed ();
553  set_tooltip ();
554 
555  /* We're providing our own PersistentTooltip */
557 }
558 
559 void
561 {
562  boost::shared_ptr<AutomationControl> c = _control.lock ();
563 
564  if (!c) {
565  return;
566  }
567 
568  stringstream s;
569  s << _name << ": ";
570  if (c->toggled ()) {
571  s << (c->get_value() > 0.5 ? _("on") : _("off"));
572  } else {
573  s << setprecision(2) << fixed;
574  s << c->internal_to_user (c->get_value ());
575  }
576 
577  string sm = Glib::Markup::escape_text (s.str());
578 
579  _slider_persistant_tooltip.set_tip (sm);
581 }
582 
583 void
585 {
586  if (_ignore_ui_adjustment) {
587  return;
588  }
589 
590  boost::shared_ptr<AutomationControl> c = _control.lock ();
591 
592  if (!c) {
593  return;
594  }
595 
596  c->set_value ( c->interface_to_internal(_adjustment.get_value ()) );
597  set_tooltip ();
598 }
599 
600 void
602 {
603  boost::shared_ptr<AutomationControl> c = _control.lock ();
604 
605  if (!c) {
606  return;
607  }
608 
609  bool const n = _button.get_active ();
610 
611  c->set_value (n ? 0 : 1);
612  _button.set_active (!n);
613  set_tooltip ();
614 }
615 
616 void
618 {
619  boost::shared_ptr<AutomationControl> c = _control.lock ();
620  if (!c) {
621  return;
622  }
623 
624  _ignore_ui_adjustment = true;
625 
626  if (c->toggled ()) {
627 
628  _button.set_active (c->get_value() > 0.5);
629 
630  } else {
631 
632  _adjustment.set_value (c->internal_to_interface(c->get_value ()));
633  set_tooltip ();
634  }
635 
636  _ignore_ui_adjustment = false;
637 }
638 
639 void
641 {
642  XMLNode* c = new XMLNode (X_("Object"));
643  c->add_property (X_("id"), state_id ());
644  c->add_property (X_("visible"), _visible);
645  node->add_child_nocopy (*c);
646 }
647 
648 void
650 {
651  XMLNode* n = GUIObjectState::get_node (node, state_id ());
652  if (n) {
653  XMLProperty* p = n->property (X_("visible"));
654  set_visible (p && string_is_affirmative (p->value ()));
655  } else {
656  set_visible (false);
657  }
658 }
659 
660 void
662 {
663  if (v) {
664  box.show ();
665  } else {
666  box.hide ();
667  }
668 
669  _visible = v;
670 }
671 
675 void
677 {
678  if (!_visible) {
679  box.hide ();
680  }
681 }
682 
683 string
685 {
686  boost::shared_ptr<AutomationControl> c = _control.lock ();
687  assert (c);
688 
689  return string_compose (X_("control %1"), c->id().to_s ());
690 }
691 
693  : ProcessorEntry (b, p, w)
694  , _plugin_insert (p)
695 {
696  p->PluginIoReConfigure.connect (
698  );
699 
701 }
702 
703 void
705 {
708 
711 
712  /* replicated instances */
713  if (!_plugin_insert->splitting () && _plugin_insert->get_count() > 1) {
714  for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
715  sinks.set(*t, sinks.get(*t) * _plugin_insert->get_count());
716  }
717  }
718  /* MIDI bypass */
721  sinks.set(DataType::MIDI, 1);
722  sources.set(DataType::MIDI, 1);
723  }
724 
725  _input_icon.set_ports(sinks);
726  _routing_icon.set_sinks(sinks);
727  _routing_icon.set_sources(sources);
728 
729  if (_plugin_insert->splitting () ||
731  )
732  {
733  _routing_icon.set_size_request (-1, std::max (7.f, rintf(7.f * ARDOUR_UI::ui_scale)));
734  _routing_icon.set_visible(true);
735  _input_icon.show();
736  } else {
737  _routing_icon.set_visible(false);
738  if (_position_num != 0) {
739  _input_icon.hide();
740  }
741  }
742 
743  _input_icon.queue_draw();
744  _output_icon.queue_draw();
745  _routing_icon.queue_draw();
746 }
747 
748 void
750 {
753 }
754 
756  _input = input;
758  set_size_request (-1, std::max (2.f, rintf(2.f * ARDOUR_UI::ui_scale)));
759 }
760 
761 bool
763 {
764  cairo_t* cr = gdk_cairo_create (get_window()->gobj());
765 
766  cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
767  cairo_clip (cr);
768 
769  Gtk::Allocation a = get_allocation();
770  double const width = a.get_width();
771  double const height = a.get_height();
772 
773  Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
774  cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
775 
776  cairo_rectangle (cr, 0, 0, width, height);
777  cairo_fill (cr);
778 
779  const double dx = rint(max(2., 2. * ARDOUR_UI::ui_scale));
780  if (_ports.n_total() > 1) {
781  for (uint32_t i = 0; i < _ports.n_total(); ++i) {
782  if (i < _ports.n_midi()) {
783  cairo_set_source_rgb (cr,
787  } else {
788  cairo_set_source_rgb (cr,
792  }
793  const float x = rintf(width * (.2f + .6f * i / (_ports.n_total() - 1.f)));
794  cairo_rectangle (cr, x-dx * .5, 0, 1+dx, height);
795  cairo_fill(cr);
796  }
797  } else if (_ports.n_total() == 1) {
798  if (_ports.n_midi() == 1) {
799  cairo_set_source_rgb (cr,
803  } else {
804  cairo_set_source_rgb (cr,
808  }
809  const float x = rintf(width * .5);
810  cairo_rectangle (cr, x-dx * .5, 0, 1+dx, height);
811  cairo_fill(cr);
812  cairo_stroke(cr);
813  }
814 
815  cairo_destroy(cr);
816  return true;
817 }
818 
819 bool
821 {
822  cairo_t* cr = gdk_cairo_create (get_window()->gobj());
823 
824  cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
825  cairo_clip (cr);
826 
827  cairo_set_line_width (cr, max (1.f, ARDOUR_UI::ui_scale));
828  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
829 
830  Gtk::Allocation a = get_allocation();
831  double const width = a.get_width();
832  double const height = a.get_height();
833 
834  Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
835  cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
836 
837  cairo_rectangle (cr, 0, 0, width, height);
838  cairo_fill (cr);
839 
840  Gdk::Color const fg = get_style()->get_fg (STATE_NORMAL);
841  cairo_set_source_rgb (cr, fg.get_red_p (), fg.get_green_p (), fg.get_blue_p ());
842 
843  const uint32_t sources = _sources.n_total();
844  const uint32_t sinks = _sinks.n_total();
845 
846  /* MIDI */
847  const uint32_t midi_sources = _sources.n_midi();
848  const uint32_t midi_sinks = _sinks.n_midi();
849 
850  cairo_set_source_rgb (cr,
854  if (midi_sources > 0 && midi_sinks > 0 && sinks > 1 && sources > 1) {
855  for (uint32_t i = 0 ; i < midi_sources; ++i) {
856  const float si_x = rintf(width * (.2f + .6f * i / (sinks - 1.f))) + .5f;
857  const float si_x0 = rintf(width * (.2f + .6f * i / (sources - 1.f))) + .5f;
858  cairo_move_to (cr, si_x, height);
859  cairo_curve_to (cr, si_x, 0, si_x0, height, si_x0, 0);
860  cairo_stroke (cr);
861  }
862  } else if (midi_sources == 1 && midi_sinks == 1 && sinks == 1 && sources == 1) {
863  const float si_x = rintf(width * .5f) + .5f;
864  cairo_move_to (cr, si_x, height);
865  cairo_line_to (cr, si_x, 0);
866  cairo_stroke (cr);
867  } else if (midi_sources == 1 && midi_sinks == 1) {
868  /* unusual cases -- removed synth, midi-track w/audio plugins */
869  const float si_x = rintf(width * (sinks > 1 ? .2f : .5f)) + .5f;
870  const float si_x0 = rintf(width * (sources > 1 ? .2f : .5f)) + .5f;
871  cairo_move_to (cr, si_x, height);
872  cairo_curve_to (cr, si_x, 0, si_x0, height, si_x0, 0);
873  cairo_stroke (cr);
874  }
875 
876  /* AUDIO */
877  const uint32_t audio_sources = _sources.n_audio();
878  const uint32_t audio_sinks = _sinks.n_audio();
879  cairo_set_source_rgb (cr,
883 
884  if (_splitting) {
885  assert(audio_sources < 2);
886  assert(audio_sinks > 1);
887  /* assume there is only ever one MIDI port */
888  const float si_x0 = rintf(width * (midi_sources > 0 ? .8f : .5f)) + .5f;
889  for (uint32_t i = midi_sinks; i < sinks; ++i) {
890  const float si_x = rintf(width * (.2f + .6f * i / (sinks - 1.f))) + .5f;
891  cairo_move_to (cr, si_x, height);
892  cairo_curve_to (cr, si_x, 0, si_x0, height, si_x0, 0);
893  cairo_stroke (cr);
894  }
895  } else if (audio_sources > 1) {
896  for (uint32_t i = 0 ; i < audio_sources; ++i) {
897  const float si_x = rintf(width * (.2f + .6f * (i + midi_sinks) / (sinks - 1.f))) + .5f;
898  const float si_x0 = rintf(width * (.2f + .6f * (i + midi_sources) / (sources - 1.f))) + .5f;
899  cairo_move_to (cr, si_x, height);
900  cairo_curve_to (cr, si_x, 0, si_x0, height, si_x0, 0);
901  cairo_stroke (cr);
902  }
903  } else if (audio_sources == 1 && audio_sinks == 1) {
904  const float si_x = rintf(width * .5f) + .5f;
905  cairo_move_to (cr, si_x, height);
906  cairo_line_to (cr, si_x, 0);
907  cairo_stroke (cr);
908  }
909  cairo_destroy(cr);
910  return true;
911 }
912 
913 ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
914  RouteProcessorSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
915  : _parent_strip (parent)
916  , _owner_is_mixer (owner_is_mixer)
917  , ab_direction (true)
918  , _get_plugin_selector (get_plugin_selector)
919  , _placement (-1)
920  , _visible_prefader_processors (0)
921  , _rr_selection(rsel)
922  , _redisplay_pending (false)
923 
924 {
925  set_session (sess);
926 
927  _width = Wide;
928  processor_menu = 0;
929  no_processor_redisplay = false;
930 
931  processor_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
933  pack_start (processor_scroller, true, true);
934 
935  processor_display.set_flags (CAN_FOCUS);
936  processor_display.set_name ("ProcessorList");
937  processor_display.set_data ("processorbox", this);
938  processor_display.set_size_request (48, -1);
940 
941  processor_display.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify), false);
942  processor_display.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify), false);
943 
946 
947  processor_display.Reordered.connect (sigc::mem_fun (*this, &ProcessorBox::reordered));
948  processor_display.DropFromAnotherBox.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop));
949 
950  processor_scroller.show ();
951  processor_display.show ();
952 
953  if (parent) {
954  parent->DeliveryChanged.connect (
956  );
957  }
958 
959  ARDOUR_UI::instance()->set_tip (processor_display, _("Right-click to add/remove/edit\nplugins,inserts,sends and more"));
960 }
961 
963 {
964  /* it may appear as if we should delete processor_menu but that is a
965  * pointer to a widget owned by the UI Manager, and has potentially
966  * be returned to many other ProcessorBoxes. GTK doesn't really make
967  * clear the ownership of this widget, which is a menu and thus is
968  * never packed into any container other than an implict GtkWindow.
969  *
970  * For now, until or if we ever get clarification over the ownership
971  * story just let it continue to exist. At worst, its a small memory leak.
972  */
973 }
974 
975 void
977 {
978  if (_route == r) {
979  return;
980  }
981 
983 
984  /* new route: any existing block on processor redisplay must be meaningless */
985  no_processor_redisplay = false;
986  _route = r;
987 
988  _route->processors_changed.connect (
990  );
991 
992  _route->DropReferences.connect (
994  );
995 
996  _route->PropertyChanged.connect (
998  );
999 
1001 }
1002 
1003 void
1005 {
1006  /* don't keep updating display as processors are deleted */
1007  no_processor_redisplay = true;
1008  _route.reset ();
1009 }
1010 
1011 void
1012 ProcessorBox::object_drop(DnDVBox<ProcessorEntry>* source, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
1013 {
1015  if (position) {
1016  p = position->processor ();
1017  if (!p) {
1018  /* dropped on the blank entry (which will be before the
1019  fader), so use the first non-blank child as our
1020  `dropped on' processor */
1021  list<ProcessorEntry*> c = processor_display.children ();
1022  list<ProcessorEntry*>::iterator i = c.begin ();
1023 
1024  assert (i != c.end ());
1025  p = (*i)->processor ();
1026  assert (p);
1027  }
1028  }
1029 
1030  list<ProcessorEntry*> children = source->selection ();
1031  list<boost::shared_ptr<Processor> > procs;
1032  for (list<ProcessorEntry*>::const_iterator i = children.begin(); i != children.end(); ++i) {
1033  if ((*i)->processor ()) {
1034  procs.push_back ((*i)->processor ());
1035  }
1036  }
1037 
1038  for (list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin(); i != procs.end(); ++i) {
1039  XMLNode& state = (*i)->get_state ();
1040  XMLNodeList nlist;
1041  nlist.push_back (&state);
1042  paste_processor_state (nlist, p);
1043  delete &state;
1044  }
1045 
1046  /* since the dndvbox doesn't take care of this properly, we have to delete the originals
1047  ourselves.
1048  */
1049 
1050  if ((context->get_suggested_action() == Gdk::ACTION_MOVE) && source) {
1051  ProcessorBox* other = reinterpret_cast<ProcessorBox*> (source->get_data ("processorbox"));
1052  if (other) {
1053  other->delete_dragged_processors (procs);
1054  }
1055  }
1056 }
1057 
1058 void
1060 {
1061  if (_width == w) {
1062  return;
1063  }
1064 
1065  _width = w;
1066 
1067  list<ProcessorEntry*> children = processor_display.children ();
1068  for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
1069  (*i)->set_enum_width (w);
1070  }
1071 
1072  queue_resize ();
1073 }
1074 
1075 Gtk::Menu*
1077 {
1079 
1080  if (rl->empty()) {
1081  /* No aux sends if there are no busses */
1082  return 0;
1083  }
1084 
1085  using namespace Menu_Helpers;
1086  Menu* menu = manage (new Menu);
1087  MenuList& items = menu->items();
1088 
1089  for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
1090  if (!_route->internal_send_for (*r) && *r != _route) {
1091  items.push_back (MenuElem ((*r)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux), boost::weak_ptr<Route>(*r))));
1092  }
1093  }
1094 
1095  return menu;
1096 }
1097 
1098 void
1100 {
1101  if (processor_menu == 0) {
1103  processor_menu->signal_unmap().connect (sigc::mem_fun (*this, &ProcessorBox::processor_menu_unmapped));
1104  }
1105 
1106  /* Sort out the plugin submenu */
1107 
1108  Gtk::MenuItem* plugin_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
1109 
1110  if (plugin_menu_item) {
1111  plugin_menu_item->set_submenu (*_get_plugin_selector()->plugin_menu());
1112  }
1113 
1114  /* And the aux submenu */
1115 
1116  Gtk::MenuItem* aux_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newaux"));
1117 
1118  if (aux_menu_item) {
1119  Menu* m = build_possible_aux_menu();
1120  if (m && !m->items().empty()) {
1121  aux_menu_item->set_submenu (*m);
1122  aux_menu_item->set_sensitive (true);
1123  } else {
1124  /* stupid gtkmm: we need to pass a null reference here */
1125  gtk_menu_item_set_submenu (aux_menu_item->gobj(), 0);
1126  aux_menu_item->set_sensitive (false);
1127  }
1128  }
1129 
1130  ProcessorEntry* single_selection = 0;
1131  if (processor_display.selection().size() == 1) {
1132  single_selection = processor_display.selection().front();
1133  }
1134 
1135  /* And the controls submenu */
1136 
1137  Gtk::MenuItem* controls_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/controls"));
1138 
1139  if (controls_menu_item) {
1140  if (single_selection) {
1141  Menu* m = single_selection->build_controls_menu ();
1142  if (m && !m->items().empty()) {
1143  controls_menu_item->set_submenu (*m);
1144  controls_menu_item->set_sensitive (true);
1145  } else {
1146  gtk_menu_item_set_submenu (controls_menu_item->gobj(), 0);
1147  controls_menu_item->set_sensitive (false);
1148  }
1149  } else {
1150  controls_menu_item->set_sensitive (false);
1151  }
1152  }
1153 
1154  Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
1155  if (send_menu_item) {
1156  if (single_selection) {
1157  Menu* m = single_selection->build_send_options_menu ();
1158  if (m && !m->items().empty()) {
1159  send_menu_item->set_submenu (*m);
1160  send_menu_item->set_sensitive (true);
1161  } else {
1162  gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
1163  send_menu_item->set_sensitive (false);
1164  }
1165  } else {
1166  send_menu_item->set_sensitive (false);
1167  }
1168  }
1169 
1170  /* Sensitise actions as approprioate */
1171 
1172  cut_action->set_sensitive (can_cut());
1173  paste_action->set_sensitive (!_rr_selection.processors.empty());
1174 
1175  const bool sensitive = !processor_display.selection().empty();
1177  edit_action->set_sensitive (one_processor_can_be_edited ());
1179 
1181  if (single_selection) {
1182  pi = boost::dynamic_pointer_cast<PluginInsert> (single_selection->processor ());
1183  }
1184 
1185  /* allow editing with an Ardour-generated UI for plugin inserts with editors */
1186  edit_action->set_sensitive (pi && pi->plugin()->has_editor ());
1187 
1188  /* disallow rename for multiple selections, for plugin inserts and for the fader */
1189  rename_action->set_sensitive (single_selection && !pi && !boost::dynamic_pointer_cast<Amp> (single_selection->processor ()));
1190 
1191  processor_menu->popup (1, arg);
1192 
1193  /* Add a placeholder gap to the processor list to indicate where a processor would be
1194  inserted were one chosen from the menu.
1195  */
1196  int x, y;
1197  processor_display.get_pointer (x, y);
1199 
1200  if (_visible_prefader_processors == 0 && _placement > 0) {
1201  --_placement;
1202  }
1203 }
1204 
1205 bool
1206 ProcessorBox::enter_notify (GdkEventCrossing*)
1207 {
1208  _current_processor_box = this;
1209  return false;
1210 }
1211 
1212 bool
1213 ProcessorBox::leave_notify (GdkEventCrossing*)
1214 {
1215  return false;
1216 }
1217 
1218 bool
1220 {
1221  ProcSelection targets;
1222 
1223  get_selected_processors (targets);
1224 
1225 /* if (targets.empty()) {
1226 
1227  int x, y;
1228  processor_display.get_pointer (x, y);
1229 
1230  pair<ProcessorEntry *, double> const pointer = processor_display.get_child_at_position (y);
1231 
1232  if (pointer.first && pointer.first->processor()) {
1233  targets.push_back (pointer.first->processor ());
1234  }
1235  }
1236 */
1237 
1238  if ( (op == ProcessorsDelete) && targets.empty() )
1239  return false; //nothing to delete. return false so the editor-mixer, because the user was probably intending to delete something in the editor
1240 
1241  switch (op) {
1242  case ProcessorsSelectAll:
1244  break;
1245 
1246  case ProcessorsSelectNone:
1248  break;
1249 
1250  case ProcessorsCopy:
1251  copy_processors (targets);
1252  break;
1253 
1254  case ProcessorsCut:
1255  cut_processors (targets);
1256  break;
1257 
1258  case ProcessorsPaste:
1259  if (targets.empty()) {
1260  paste_processors ();
1261  } else {
1262  paste_processors (targets.front());
1263  }
1264  break;
1265 
1266  case ProcessorsDelete:
1267  delete_processors (targets);
1268  break;
1269 
1271  for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
1272  if ((*i)->active()) {
1273  (*i)->deactivate ();
1274  } else {
1275  (*i)->activate ();
1276  }
1277  }
1278  break;
1279 
1280  case ProcessorsAB:
1281  ab_plugins ();
1282  break;
1283 
1284  default:
1285  break;
1286  }
1287 
1288  return true;
1289 }
1290 
1293 {
1294  return processor->window_proxy();
1295 }
1296 
1297 
1298 bool
1300 {
1301  boost::shared_ptr<Processor> processor;
1302  if (child) {
1303  processor = child->processor ();
1304  }
1305 
1306  int ret = false;
1307  bool selected = processor_display.selected (child);
1308 
1309  if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
1310 
1311  if (_session->engine().connected()) {
1312  /* XXX giving an error message here is hard, because we may be in the midst of a button press */
1313 
1314  if (!one_processor_can_be_edited ()) {
1315  return true;
1316  }
1317 
1318  if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
1319  generic_edit_processor (processor);
1320  } else {
1321  edit_processor (processor);
1322  }
1323  }
1324 
1325  ret = true;
1326 
1327  } else if (Keyboard::is_context_menu_event (ev)) {
1328 
1329  show_processor_menu (ev->time);
1330 
1331  ret = true;
1332 
1333  } else if (processor && ev->button == 1 && selected) {
1334 
1335  // this is purely informational but necessary for route params UI
1336  ProcessorSelected (processor); // emit
1337 
1338  } else if (!processor && ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
1339 
1340  choose_plugin ();
1341  _get_plugin_selector()->show_manager ();
1342  }
1343 
1344  return ret;
1345 }
1346 
1347 bool
1349 {
1350  boost::shared_ptr<Processor> processor;
1351  if (child) {
1352  processor = child->processor ();
1353  }
1354 
1355  if (processor && Keyboard::is_delete_event (ev)) {
1356 
1357  Glib::signal_idle().connect (sigc::bind (
1358  sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor),
1359  boost::weak_ptr<Processor>(processor)));
1360 
1361  } else if (processor && Keyboard::is_button2_event (ev)
1362 #ifndef GTKOSX
1363  && (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))
1364 #endif
1365  ) {
1366 
1367  /* button2-click with no/appropriate modifiers */
1368 
1369  if (processor->active()) {
1370  processor->deactivate ();
1371  } else {
1372  processor->activate ();
1373  }
1374  }
1375 
1376  return false;
1377 }
1378 
1379 Menu *
1381 {
1382  processor_menu = dynamic_cast<Gtk::Menu*>(ActionManager::get_widget("/ProcessorMenu") );
1383  processor_menu->set_name ("ArdourContextMenu");
1384  return processor_menu;
1385 }
1386 
1387 void
1389 {
1391 }
1392 
1393 void
1395 {
1397 }
1398 
1399 void
1401 {
1402  _get_plugin_selector()->set_interested_object (*this);
1403 }
1404 
1406 bool
1408 {
1409  for (SelectedPlugins::const_iterator p = plugins.begin(); p != plugins.end(); ++p) {
1410 
1411  boost::shared_ptr<Processor> processor (new PluginInsert (*_session, *p));
1412 
1413  Route::ProcessorStreams err_streams;
1414 
1415  if (_route->add_processor_by_index (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
1416  weird_plugin_dialog (**p, err_streams);
1417  return true;
1418  // XXX SHAREDPTR delete plugin here .. do we even need to care?
1419  } else {
1420 
1421  if (Profile->get_sae()) {
1422  processor->activate ();
1423  }
1424  }
1425  }
1426 
1427  return false;
1428 }
1429 
1430 void
1432 {
1433  ArdourDialog dialog (_("Plugin Incompatibility"));
1434  Label label;
1435 
1436  string text = string_compose(_("You attempted to add the plugin \"%1\" in slot %2.\n"),
1437  p.name(), streams.index);
1438 
1439  bool has_midi = streams.count.n_midi() > 0 || p.get_info()->n_inputs.n_midi() > 0;
1440  bool has_audio = streams.count.n_audio() > 0 || p.get_info()->n_inputs.n_audio() > 0;
1441 
1442  text += _("\nThis plugin has:\n");
1443  if (has_midi) {
1444  uint32_t const n = p.get_info()->n_inputs.n_midi ();
1445  text += string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n), n);
1446  }
1447  if (has_audio) {
1448  uint32_t const n = p.get_info()->n_inputs.n_audio ();
1449  text += string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n), n);
1450  }
1451 
1452  text += _("\nbut at the insertion point, there are:\n");
1453  if (has_midi) {
1454  uint32_t const n = streams.count.n_midi ();
1455  text += string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n), n);
1456  }
1457  if (has_audio) {
1458  uint32_t const n = streams.count.n_audio ();
1459  text += string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n), n);
1460  }
1461 
1462  text += string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME);
1463  label.set_text(text);
1464 
1465  dialog.get_vbox()->pack_start (label);
1466  dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
1467 
1468  dialog.set_name (X_("PluginIODialog"));
1469  dialog.set_modal (true);
1470  dialog.show_all ();
1471 
1472  dialog.run ();
1473 }
1474 
1475 void
1477 {
1480 }
1481 
1482 /* Caller must not hold process lock */
1483 void
1485 {
1487  boost::shared_ptr<Send> send (new Send (*_session, sendpan, _route->mute_master()));
1488 
1489  /* make an educated guess at the initial number of outputs for the send */
1490  ChanCount outs = (_session->master_out())
1491  ? _session->master_out()->n_outputs()
1492  : _route->n_outputs();
1493 
1494  /* XXX need processor lock on route */
1495  try {
1496  Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
1497  send->output()->ensure_io (outs, false, this);
1498  } catch (AudioEngine::PortRegistrationFailure& err) {
1499  error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
1500  return;
1501  }
1502 
1503  /* let the user adjust the IO setup before creation.
1504 
1505  Note: this dialog is NOT modal - we just leave it to run and it will
1506  return when its Finished signal is emitted - typically when the window
1507  is closed.
1508  */
1509 
1510  IOSelectorWindow *ios = new IOSelectorWindow (_session, send->output(), true);
1511  ios->show ();
1512 
1513  /* keep a reference to the send so it doesn't get deleted while
1514  the IOSelectorWindow is doing its stuff
1515  */
1516  _processor_being_created = send;
1517 
1518  ios->selector().Finished.connect (sigc::bind (
1519  sigc::mem_fun(*this, &ProcessorBox::send_io_finished),
1520  boost::weak_ptr<Processor>(send), ios));
1521 
1522 }
1523 
1524 void
1526 {
1527  boost::shared_ptr<Processor> processor (weak_processor.lock());
1528 
1529  /* drop our temporary reference to the new send */
1531 
1532  if (!processor) {
1533  return;
1534  }
1535 
1536  switch (r) {
1537  case IOSelector::Cancelled:
1538  // processor will go away when all shared_ptrs to it vanish
1539  break;
1540 
1541  case IOSelector::Accepted:
1543  if (Profile->get_sae()) {
1544  processor->activate ();
1545  }
1546  break;
1547  }
1548 
1549  delete_when_idle (ios);
1550 }
1551 
1552 void
1554 {
1555  boost::shared_ptr<Processor> processor (weak_processor.lock());
1556 
1557  /* drop our temporary reference to the new return */
1559 
1560  if (!processor) {
1561  return;
1562  }
1563 
1564  switch (r) {
1565  case IOSelector::Cancelled:
1566  // processor will go away when all shared_ptrs to it vanish
1567  break;
1568 
1569  case IOSelector::Accepted:
1571  if (Profile->get_sae()) {
1572  processor->activate ();
1573  }
1574  break;
1575  }
1576 
1577  delete_when_idle (ios);
1578 }
1579 
1580 void
1582 {
1583  if (!_route) {
1584  return;
1585  }
1586 
1587  boost::shared_ptr<Route> target = wr.lock();
1588 
1589  if (!target) {
1590  return;
1591  }
1592 
1594 }
1595 
1596 void
1598 {
1599  if (c.type == RouteProcessorChange::MeterPointChange && c.meter_visibly_changed == false) {
1600  /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1601  return;
1602  }
1603 
1605 }
1606 
1607 void
1609 {
1611  bool fader_seen;
1612 
1613  if (no_processor_redisplay) {
1614  return;
1615  }
1616 
1618 
1620  fader_seen = false;
1621 
1622  _route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &ProcessorBox::help_count_visible_prefader_processors),
1623  &_visible_prefader_processors, &fader_seen));
1624 
1628 }
1629 
1633 void
1635 {
1636  boost::shared_ptr<Processor> p = w.lock ();
1637  if (!p) {
1638  return;
1639  }
1640  if (p->window_proxy()) {
1641  return;
1642  }
1643 
1644  /* not on the list; add it */
1645 
1646  string loc;
1647 #if 0 // is this still needed? Why?
1648  if (_parent_strip) {
1649  if (_parent_strip->mixer_owned()) {
1650  loc = X_("M");
1651  } else {
1652  loc = X_("R");
1653  }
1654  } else {
1655  loc = X_("P");
1656  }
1657 #else
1658  loc = X_("P");
1659 #endif
1660 
1662  string_compose ("%1-%2-%3", loc, _route->id(), p->id()),
1663  this,
1664  w);
1665 
1666  const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
1667 
1668  if (ui_xml) {
1669  wp->set_state (*ui_xml);
1670  }
1671 
1672  void* existing_ui = p->get_ui ();
1673 
1674  if (existing_ui) {
1675  wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
1676  }
1677 
1678  p->set_window_proxy (wp);
1680 }
1681 
1682 void
1684 {
1685  boost::shared_ptr<Processor> processor (p.lock ());
1686 
1687  if (processor && processor->display_to_user()) {
1688 
1689  if (boost::dynamic_pointer_cast<Amp>(processor)) {
1690  *amp_seen = true;
1691  } else {
1692  if (!*amp_seen) {
1693  (*cnt)++;
1694  }
1695  }
1696  }
1697 }
1698 
1699 void
1701 {
1702  boost::shared_ptr<Processor> processor (p.lock ());
1703 
1704  if (!processor || !processor->display_to_user()) {
1705  return;
1706  }
1707 
1709 
1710  ProcessorEntry* e = 0;
1711  if (plugin_insert) {
1712  e = new PluginInsertProcessorEntry (this, plugin_insert, _width);
1713  } else {
1714  e = new ProcessorEntry (this, processor, _width);
1715  }
1716 
1719 
1720  //faders and meters are not deletable, copy/paste-able, so they shouldn't be selectable
1721  if (!send && !plugin_insert && !ext)
1722  e->set_selectable(false);
1723 
1724  bool mark_send_visible = false;
1725  if (send && _parent_strip) {
1726  /* show controls of new sends by default */
1728  XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
1729  assert (strip);
1730  /* check if state exists, if not it must be a new send */
1731  if (!st.get_node(strip, e->state_id())) {
1732  mark_send_visible = true;
1733  }
1734  }
1735 
1736  /* Set up this entry's state from the GUIObjectState */
1737  XMLNode* proc = entry_gui_object_state (e);
1738  if (proc) {
1739  e->set_control_state (proc);
1740  }
1741 
1742  if (mark_send_visible) {
1743  e->show_all_controls ();
1744  }
1745 
1747 }
1748 
1749 void
1751 {
1754 }
1755 
1756 void
1758 {
1759  list<ProcessorEntry*> children = processor_display.children ();
1760  bool pre_fader = true;
1761 
1762  uint32_t num = 0;
1763  for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
1764  if (boost::dynamic_pointer_cast<Amp>((*i)->processor())) {
1765  pre_fader = false;
1766  (*i)->set_position (ProcessorEntry::Fader, num++);
1767  } else {
1768  if (pre_fader) {
1769  (*i)->set_position (ProcessorEntry::PreFader, num++);
1770  } else {
1771  (*i)->set_position (ProcessorEntry::PostFader, num++);
1772  }
1773  }
1774  }
1775 }
1776 
1777 void
1779 {
1780  list<ProcessorEntry*> children = processor_display.children ();
1781  Route::ProcessorList our_processors;
1782 
1783  for (list<ProcessorEntry*>::iterator i = children.begin(); i != children.end(); ++i) {
1784  if ((*i)->processor()) {
1785  our_processors.push_back ((*i)->processor ());
1786  }
1787  }
1788 
1789  if (_route->reorder_processors (our_processors)) {
1790  /* Reorder failed, so report this to the user. As far as I can see this must be done
1791  in an idle handler: it seems that the redisplay_processors() that happens below destroys
1792  widgets that were involved in the drag-and-drop on the processor list, which causes problems
1793  when the drag is torn down after this handler function is finished.
1794  */
1795  Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder));
1796  }
1797 }
1798 
1799 void
1801 {
1802  /* reorder failed, so redisplay */
1803 
1805 
1806  /* now tell them about the problem */
1807 
1808  ArdourDialog dialog (_("Plugin Incompatibility"));
1809  Label label;
1810 
1811  label.set_text (_("\
1812 You cannot reorder these plugins/sends/inserts\n\
1813 in that way because the inputs and\n\
1814 outputs will not work correctly."));
1815 
1816  dialog.get_vbox()->set_border_width (12);
1817  dialog.get_vbox()->pack_start (label);
1818  dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
1819 
1820  dialog.set_name (X_("PluginIODialog"));
1821  dialog.set_modal (true);
1822  dialog.show_all ();
1823 
1824  dialog.run ();
1825 }
1826 
1827 void
1829 {
1830  ProcSelection to_be_renamed;
1831 
1832  get_selected_processors (to_be_renamed);
1833 
1834  if (to_be_renamed.empty()) {
1835  return;
1836  }
1837 
1838  for (ProcSelection::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
1839  rename_processor (*i);
1840  }
1841 }
1842 
1843 bool
1845 {
1846  vector<boost::shared_ptr<Processor> > sel;
1847 
1849 
1850  /* cut_processors () does not cut inserts */
1851 
1852  for (vector<boost::shared_ptr<Processor> >::const_iterator i = sel.begin (); i != sel.end (); ++i) {
1853 
1854  if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1855  (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1856  (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1857  return true;
1858  }
1859  }
1860 
1861  return false;
1862 }
1863 
1864 void
1866 {
1867  if (to_be_removed.empty()) {
1868  return;
1869  }
1870 
1871  XMLNode* node = new XMLNode (X_("cut"));
1872  Route::ProcessorList to_cut;
1873 
1874  no_processor_redisplay = true;
1875  for (ProcSelection::const_iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
1876  // Cut only plugins, sends and returns
1877  if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1878  (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1879  (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1880 
1881  Window* w = get_processor_ui (*i);
1882 
1883  if (w) {
1884  w->hide ();
1885  }
1886 
1887  XMLNode& child ((*i)->get_state());
1888  node->add_child_nocopy (child);
1889  to_cut.push_back (*i);
1890  }
1891  }
1892 
1893  if (_route->remove_processors (to_cut) != 0) {
1894  delete node;
1895  no_processor_redisplay = false;
1896  return;
1897  }
1898 
1899  _rr_selection.set (node);
1900 
1901  no_processor_redisplay = false;
1903 }
1904 
1905 void
1907 {
1908  if (to_be_copied.empty()) {
1909  return;
1910  }
1911 
1912  XMLNode* node = new XMLNode (X_("copy"));
1913 
1914  for (ProcSelection::const_iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
1915  // Copy only plugins, sends, returns
1916  if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
1917  (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
1918  (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
1919  node->add_child_nocopy ((*i)->get_state());
1920  }
1921  }
1922 
1923  _rr_selection.set (node);
1924 }
1925 
1926 void
1928 {
1929  if (targets.empty()) {
1930  return;
1931  }
1932 
1933  no_processor_redisplay = true;
1934 
1935  for (ProcSelection::const_iterator i = targets.begin(); i != targets.end(); ++i) {
1936 
1937  Window* w = get_processor_ui (*i);
1938 
1939  if (w) {
1940  w->hide ();
1941  }
1942 
1943  _route->remove_processor(*i);
1944  }
1945 
1946  no_processor_redisplay = false;
1948 }
1949 
1950 void
1952 {
1953  list<boost::shared_ptr<Processor> >::const_iterator x;
1954 
1955  no_processor_redisplay = true;
1956  for (x = procs.begin(); x != procs.end(); ++x) {
1957 
1958  Window* w = get_processor_ui (*x);
1959 
1960  if (w) {
1961  w->hide ();
1962  }
1963 
1964  _route->remove_processor(*x);
1965  }
1966 
1967  no_processor_redisplay = false;
1969 }
1970 
1971 gint
1973 {
1974  boost::shared_ptr<Processor> processor (weak_processor.lock());
1975 
1976  if (!processor) {
1977  return false;
1978  }
1979 
1980  /* NOT copied to _mixer.selection() */
1981 
1982  no_processor_redisplay = true;
1983  _route->remove_processor (processor);
1984  no_processor_redisplay = false;
1986 
1987  return false;
1988 }
1989 
1990 void
1992 {
1993  ArdourPrompter name_prompter (true);
1994  string result;
1995  name_prompter.set_title (_("Rename Processor"));
1996  name_prompter.set_prompt (_("New name:"));
1997  name_prompter.set_initial_text (processor->name());
1998  name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1999  name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
2000  name_prompter.show_all ();
2001 
2002  switch (name_prompter.run ()) {
2003 
2004  case Gtk::RESPONSE_ACCEPT:
2005  name_prompter.get_result (result);
2006  if (result.length()) {
2007 
2008  int tries = 0;
2009  string test = result;
2010 
2011  while (tries < 100) {
2012  if (_session->io_name_is_legal (test)) {
2013  result = test;
2014  break;
2015  }
2016  tries++;
2017 
2018  test = string_compose ("%1-%2", result, tries);
2019  }
2020 
2021  if (tries < 100) {
2022  processor->set_name (result);
2023  } else {
2024  /* unlikely! */
2026  (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result));
2027  }
2028  }
2029  break;
2030  }
2031 
2032  return;
2033 }
2034 
2035 void
2037 {
2038  if (_rr_selection.processors.empty()) {
2039  return;
2040  }
2041 
2043 }
2044 
2045 void
2047 {
2048 
2049  if (_rr_selection.processors.empty()) {
2050  return;
2051  }
2052 
2054 }
2055 
2056 void
2058 {
2059  XMLNodeConstIterator niter;
2060  list<boost::shared_ptr<Processor> > copies;
2061 
2062  if (nlist.empty()) {
2063  return;
2064  }
2065 
2066  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2067 
2068  XMLProperty const * type = (*niter)->property ("type");
2069  XMLProperty const * role = (*niter)->property ("role");
2070  assert (type);
2071 
2073  try {
2074  if (type->value() == "meter" ||
2075  type->value() == "main-outs" ||
2076  type->value() == "amp" ||
2077  type->value() == "intreturn") {
2078  /* do not paste meter, main outs, amp or internal returns */
2079  continue;
2080 
2081  } else if (type->value() == "intsend") {
2082 
2083  /* aux sends are OK, but those used for
2084  * other purposes, are not.
2085  */
2086 
2087  assert (role);
2088 
2089  if (role->value() != "Aux") {
2090  continue;
2091  }
2092 
2094  XMLNode n (**niter);
2095  InternalSend* s = new InternalSend (*_session, sendpan, _route->mute_master(),
2096  _route, boost::shared_ptr<Route>(), Delivery::Aux);
2097 
2098  IOProcessor::prepare_for_reset (n, s->name());
2099 
2100  if (s->set_state (n, Stateful::loading_state_version)) {
2101  delete s;
2102  return;
2103  }
2104 
2105  p.reset (s);
2106 
2107  } else if (type->value() == "send") {
2108 
2110  XMLNode n (**niter);
2111 
2112  Send* s = new Send (*_session, _route->pannable(), _route->mute_master());
2113 
2114  IOProcessor::prepare_for_reset (n, s->name());
2115 
2116  if (s->set_state (n, Stateful::loading_state_version)) {
2117  delete s;
2118  return;
2119  }
2120 
2121  p.reset (s);
2122 
2123  } else if (type->value() == "return") {
2124 
2125  XMLNode n (**niter);
2126  Return* r = new Return (*_session);
2127 
2128  IOProcessor::prepare_for_reset (n, r->name());
2129 
2130  if (r->set_state (n, Stateful::loading_state_version)) {
2131  delete r;
2132  return;
2133  }
2134 
2135  p.reset (r);
2136 
2137  } else if (type->value() == "port") {
2138 
2139  XMLNode n (**niter);
2141 
2142  IOProcessor::prepare_for_reset (n, pi->name());
2143 
2144  if (pi->set_state (n, Stateful::loading_state_version)) {
2145  return;
2146  }
2147 
2148  p.reset (pi);
2149 
2150  } else {
2151  /* XXX its a bit limiting to assume that everything else
2152  is a plugin.
2153  */
2154 
2155  p.reset (new PluginInsert (*_session));
2156  p->set_state (**niter, Stateful::current_state_version);
2157  }
2158 
2159  copies.push_back (p);
2160  }
2161 
2162  catch (...) {
2163  error << _("plugin insert constructor failed") << endmsg;
2164  }
2165  }
2166 
2167  if (copies.empty()) {
2168  return;
2169  }
2170 
2171  if (_route->add_processors (copies, p)) {
2172 
2173  string msg = _(
2174  "Copying the set of processors on the clipboard failed,\n\
2175 probably because the I/O configuration of the plugins\n\
2176 could not match the configuration of this track.");
2177  MessageDialog am (msg);
2178  am.run ();
2179  }
2180 }
2181 
2182 void
2184 {
2185  const list<ProcessorEntry*> selection = processor_display.selection ();
2186  for (list<ProcessorEntry*>::const_iterator i = selection.begin(); i != selection.end(); ++i) {
2187  processors.push_back ((*i)->processor ());
2188  }
2189 }
2190 
2191 void
2193 {
2194  list<ProcessorEntry*> selection = processor_display.selection ();
2195  for (list<ProcessorEntry*>::iterator i = selection.begin(); i != selection.end(); ++i) {
2196  (this->*method) ((*i)->processor ());
2197  }
2198 }
2199 
2200 void
2202 {
2204 }
2205 
2206 void
2208 {
2211 }
2212 
2213 
2214 void
2216 {
2217  string prompt;
2218  vector<string> choices;
2219 
2220  prompt = string_compose (_("Do you really want to remove all processors from %1?\n"
2221  "(this cannot be undone)"), _route->name());
2222 
2223  choices.push_back (_("Cancel"));
2224  choices.push_back (_("Yes, remove them all"));
2225 
2226  Gtkmm2ext::Choice prompter (_("Remove processors"), prompt, choices);
2227 
2228  if (prompter.run () == 1) {
2231  }
2232 }
2233 
2234 void
2236 {
2237  string prompt;
2238  vector<string> choices;
2239 
2240  if (p == PreFader) {
2241  prompt = string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
2242  "(this cannot be undone)"), _route->name());
2243  } else {
2244  prompt = string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
2245  "(this cannot be undone)"), _route->name());
2246  }
2247 
2248  choices.push_back (_("Cancel"));
2249  choices.push_back (_("Yes, remove them all"));
2250 
2251  Gtkmm2ext::Choice prompter (_("Remove processors"), prompt, choices);
2252 
2253  if (prompter.run () == 1) {
2254  _route->clear_processors (p);
2255  }
2256 }
2257 
2258 bool
2260 {
2262  if (at && at->freeze_state() == AudioTrack::Frozen) {
2263  return false;
2264  }
2265 
2266  if (
2267  boost::dynamic_pointer_cast<Send> (processor) ||
2268  boost::dynamic_pointer_cast<Return> (processor) ||
2269  boost::dynamic_pointer_cast<PluginInsert> (processor) ||
2271  ) {
2272  return true;
2273  }
2274 
2275  return false;
2276 }
2277 
2278 bool
2280 {
2281  list<ProcessorEntry*> selection = processor_display.selection ();
2282  list<ProcessorEntry*>::iterator i = selection.begin();
2283  while (i != selection.end() && processor_can_be_edited ((*i)->processor()) == false) {
2284  ++i;
2285  }
2286 
2287  return (i != selection.end());
2288 }
2289 
2290 Gtk::Window*
2292 {
2294  boost::shared_ptr<InternalSend> internal_send;
2296  boost::shared_ptr<PluginInsert> plugin_insert;
2297  boost::shared_ptr<PortInsert> port_insert;
2298  Window* gidget = 0;
2299 
2300  /* This method may or may not return a Window, but if it does not it
2301  * will modify the parent mixer strip appearance layout to allow
2302  * "editing" the @param processor that was passed in.
2303  *
2304  * So for example, if the processor is an Amp (gain), the parent strip
2305  * will be forced back into a model where the fader controls the main gain.
2306  * If the processor is a send, then we map the send controls onto the
2307  * strip.
2308  *
2309  * Plugins and others will return a window for control.
2310  */
2311 
2312  if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
2313 
2314  if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) {
2315  return 0;
2316  }
2317  }
2318 
2319  if (boost::dynamic_pointer_cast<Amp> (processor)) {
2320 
2321  if (_parent_strip) {
2323  }
2324 
2325  } else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
2326 
2327  if (!_session->engine().connected()) {
2328  return 0;
2329  }
2330 
2331  if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
2332 
2333  gidget = new SendUIWindow (send, _session);
2334  }
2335 
2336  } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
2337 
2338  if (boost::dynamic_pointer_cast<InternalReturn> (retrn)) {
2339  /* no GUI for these */
2340  return 0;
2341  }
2342 
2343  if (!_session->engine().connected()) {
2344  return 0;
2345  }
2346 
2348 
2349  ReturnUIWindow *return_ui;
2350  Window* w = get_processor_ui (retrn);
2351 
2352  if (w == 0) {
2353 
2354  return_ui = new ReturnUIWindow (retrn, _session);
2355  return_ui->set_title (retrn->name ());
2356  set_processor_ui (send, return_ui);
2357 
2358  } else {
2359  return_ui = dynamic_cast<ReturnUIWindow *> (w);
2360  }
2361 
2362  gidget = return_ui;
2363 
2364  } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
2365 
2366  PluginUIWindow *plugin_ui;
2367 
2368  /* these are both allowed to be null */
2369 
2370  Window* w = get_processor_ui (plugin_insert);
2371 
2372  if (w == 0) {
2373  plugin_ui = new PluginUIWindow (plugin_insert, false, use_custom);
2374  plugin_ui->set_title (generate_processor_title (plugin_insert));
2375  set_processor_ui (plugin_insert, plugin_ui);
2376 
2377  } else {
2378  plugin_ui = dynamic_cast<PluginUIWindow *> (w);
2379  }
2380 
2381  gidget = plugin_ui;
2382 
2383  } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
2384 
2385  if (!_session->engine().connected()) {
2386  MessageDialog msg ( _("Not connected to audio engine - no I/O changes are possible"));
2387  msg.run ();
2388  return 0;
2389  }
2390 
2391  PortInsertWindow *io_selector;
2392 
2393  Window* w = get_processor_ui (port_insert);
2394 
2395  if (w == 0) {
2396  io_selector = new PortInsertWindow (_session, port_insert);
2397  set_processor_ui (port_insert, io_selector);
2398 
2399  } else {
2400  io_selector = dynamic_cast<PortInsertWindow *> (w);
2401  }
2402 
2403  gidget = io_selector;
2404  }
2405 
2406  return gidget;
2407 }
2408 
2409 Gtk::Window*
2411 {
2412  boost::shared_ptr<PluginInsert> plugin_insert
2414 
2415  if (!plugin_insert) {
2416  return 0;
2417  }
2418 
2419  PluginUIWindow* win = new PluginUIWindow (plugin_insert, true, false);
2420  win->set_title (generate_processor_title (plugin_insert));
2421 
2422  return win;
2423 }
2424 
2425 void
2427 {
2428  Glib::RefPtr<Gtk::ActionGroup> popup_act_grp = Gtk::ActionGroup::create(X_("ProcessorMenu"));
2429  Glib::RefPtr<Action> act;
2430 
2431  /* new stuff */
2432  ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin"),
2433  sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
2434 
2435  act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"),
2436  sigc::ptr_fun (ProcessorBox::rb_choose_insert));
2438  act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New External Send ..."),
2439  sigc::ptr_fun (ProcessorBox::rb_choose_send));
2441 
2442  ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ..."));
2443 
2444  ActionManager::register_action (popup_act_grp, X_("controls"), _("Controls"));
2445  ActionManager::register_action (popup_act_grp, X_("send_options"), _("Send Options"));
2446 
2447  ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear (all)"),
2448  sigc::ptr_fun (ProcessorBox::rb_clear));
2449  ActionManager::register_action (popup_act_grp, X_("clear_pre"), _("Clear (pre-fader)"),
2450  sigc::ptr_fun (ProcessorBox::rb_clear_pre));
2451  ActionManager::register_action (popup_act_grp, X_("clear_post"), _("Clear (post-fader)"),
2452  sigc::ptr_fun (ProcessorBox::rb_clear_post));
2453 
2454  /* standard editing stuff */
2455  cut_action = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"),
2456  sigc::ptr_fun (ProcessorBox::rb_cut));
2458  act = ActionManager::register_action (popup_act_grp, X_("copy"), _("Copy"),
2459  sigc::ptr_fun (ProcessorBox::rb_copy));
2461 
2462  act = ActionManager::register_action (popup_act_grp, X_("delete"), _("Delete"),
2463  sigc::ptr_fun (ProcessorBox::rb_delete));
2465 
2466  paste_action = ActionManager::register_action (popup_act_grp, X_("paste"), _("Paste"),
2467  sigc::ptr_fun (ProcessorBox::rb_paste));
2468  rename_action = ActionManager::register_action (popup_act_grp, X_("rename"), _("Rename"),
2469  sigc::ptr_fun (ProcessorBox::rb_rename));
2470  ActionManager::register_action (popup_act_grp, X_("selectall"), _("Select All"),
2471  sigc::ptr_fun (ProcessorBox::rb_select_all));
2472  ActionManager::register_action (popup_act_grp, X_("deselectall"), _("Deselect All"),
2473  sigc::ptr_fun (ProcessorBox::rb_deselect_all));
2474 
2475  /* activation etc. */
2476 
2477  ActionManager::register_action (popup_act_grp, X_("activate_all"), _("Activate All"),
2478  sigc::ptr_fun (ProcessorBox::rb_activate_all));
2479  ActionManager::register_action (popup_act_grp, X_("deactivate_all"), _("Deactivate All"),
2480  sigc::ptr_fun (ProcessorBox::rb_deactivate_all));
2481  ActionManager::register_action (popup_act_grp, X_("ab_plugins"), _("A/B Plugins"),
2482  sigc::ptr_fun (ProcessorBox::rb_ab_plugins));
2483 
2484  /* show editors */
2486  popup_act_grp, X_("edit"), _("Edit..."),
2487  sigc::ptr_fun (ProcessorBox::rb_edit));
2488 
2490  popup_act_grp, X_("edit-generic"), _("Edit with generic controls..."),
2491  sigc::ptr_fun (ProcessorBox::rb_edit_generic));
2492 
2493  ActionManager::add_action_group (popup_act_grp);
2494 }
2495 
2496 void
2498 {
2499  if (_current_processor_box == 0) {
2500  return;
2501  }
2502 
2504 }
2505 
2506 void
2508 {
2509  if (_current_processor_box == 0) {
2510  return;
2511  }
2512 
2514 }
2515 
2516 void
2518 {
2519  if (_current_processor_box == 0) {
2520  return;
2521  }
2523 }
2524 
2525 void
2527 {
2528  if (_current_processor_box == 0) {
2529  return;
2530  }
2532 }
2533 
2534 void
2536 {
2537  if (_current_processor_box == 0) {
2538  return;
2539  }
2541 }
2542 
2543 void
2545 {
2546  if (_current_processor_box == 0) {
2547  return;
2548  }
2549 
2551 }
2552 
2553 void
2555 {
2556  if (_current_processor_box == 0) {
2557  return;
2558  }
2559 
2561 }
2562 
2563 
2564 void
2566 {
2567  if (_current_processor_box == 0) {
2568  return;
2569  }
2570 
2572 }
2573 
2574 
2575 void
2577 {
2578  if (_current_processor_box == 0) {
2579  return;
2580  }
2581 
2583 }
2584 
2585 void
2587 {
2588  if (_current_processor_box == 0) {
2589  return;
2590  }
2591 
2593 }
2594 
2595 void
2597 {
2598  if (_current_processor_box == 0) {
2599  return;
2600  }
2601 
2603 }
2604 
2605 void
2607 {
2608  if (_current_processor_box == 0) {
2609  return;
2610  }
2612 }
2613 
2614 void
2616 {
2617  if (_current_processor_box == 0) {
2618  return;
2619  }
2620 
2622 }
2623 
2624 void
2626 {
2627  if (_current_processor_box == 0) {
2628  return;
2629  }
2631 }
2632 
2633 void
2635 {
2636  if (_current_processor_box == 0) {
2637  return;
2638  }
2639 
2641 }
2642 
2643 void
2645 {
2646  if (_current_processor_box == 0) {
2647  return;
2648  }
2649 
2651 }
2652 
2653 void
2655 {
2656  if (_current_processor_box == 0) {
2657  return;
2658  }
2659 
2661 }
2662 
2663 void
2665 {
2666  if (_current_processor_box == 0) {
2667  return;
2668  }
2670 }
2671 
2672 void
2674 {
2675  if (_current_processor_box == 0) {
2676  return;
2677  }
2678 
2680 }
2681 
2682 bool
2684 {
2685  if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
2686  return false;
2687  }
2688 
2689  if (_parent_strip) {
2691  if (_parent_strip->current_delivery() == send) {
2693  } else {
2694  _parent_strip->show_send(send);
2695  }
2696  }
2697  return true;
2698 }
2699 
2700 void
2702 {
2703  if (!processor) {
2704  return;
2705  }
2706  if (edit_aux_send (processor)) {
2707  return;
2708  }
2709 
2710  ProcessorWindowProxy* proxy = find_window_proxy (processor);
2711 
2712  if (proxy) {
2713  proxy->set_custom_ui_mode (true);
2714  proxy->toggle ();
2715  }
2716 }
2717 
2718 void
2720 {
2721  if (!processor) {
2722  return;
2723  }
2724  if (edit_aux_send (processor)) {
2725  return;
2726  }
2727 
2728  ProcessorWindowProxy* proxy = find_window_proxy (processor);
2729 
2730  if (proxy) {
2731  proxy->set_custom_ui_mode (false);
2732  proxy->toggle ();
2733  }
2734 }
2735 
2736 void
2738 {
2739  if (!what_changed.contains (ARDOUR::Properties::name)) {
2740  return;
2741  }
2742 
2744 
2745  boost::shared_ptr<Processor> processor;
2746  boost::shared_ptr<PluginInsert> plugin_insert;
2748 
2749  list<ProcessorEntry*> children = processor_display.children();
2750 
2751  for (list<ProcessorEntry*>::iterator iter = children.begin(); iter != children.end(); ++iter) {
2752 
2753  processor = (*iter)->processor ();
2754 
2755  if (!processor) {
2756  continue;
2757  }
2758 
2759  Window* w = get_processor_ui (processor);
2760 
2761  if (!w) {
2762  continue;
2763  }
2764 
2765  /* rename editor windows for sends and plugins */
2766 
2767  if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
2768  w->set_title (send->name ());
2769  } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
2770  w->set_title (generate_processor_title (plugin_insert));
2771  }
2772  }
2773 }
2774 
2775 string
2777 {
2778  string maker = pi->plugin()->maker() ? pi->plugin()->maker() : "";
2779  string::size_type email_pos;
2780 
2781  if ((email_pos = maker.find_first_of ('<')) != string::npos) {
2782  maker = maker.substr (0, email_pos - 1);
2783  }
2784 
2785  if (maker.length() > 32) {
2786  maker = maker.substr (0, 32);
2787  maker += " ...";
2788  }
2789 
2790  SessionObject* owner = pi->owner();
2791 
2792  if (owner) {
2793  return string_compose(_("%1: %2 (by %3)"), owner->name(), pi->name(), maker);
2794  } else {
2795  return string_compose(_("%1 (by %2)"), pi->name(), maker);
2796  }
2797 }
2798 
2802 Window *
2804 {
2806  if (wp) {
2807  return wp->get ();
2808  }
2809  return 0;
2810 }
2811 
2816 void
2818 {
2819  assert (p->window_proxy());
2820  p->set_ui (w);
2821  p->window_proxy()->use_window (*w);
2822 }
2823 
2824 void
2826 {
2827  boost::shared_ptr<Delivery> d = w.lock ();
2828  if (!d) {
2829  return;
2830  }
2831 
2832  list<ProcessorEntry*> children = processor_display.children ();
2833  list<ProcessorEntry*>::const_iterator i = children.begin();
2834  while (i != children.end() && (*i)->processor() != d) {
2835  ++i;
2836  }
2837 
2838  if (i == children.end()) {
2840  } else {
2842  }
2843 }
2844 
2846 void
2848 {
2849  list<ProcessorEntry*> c = processor_display.children ();
2850  for (list<ProcessorEntry*>::iterator i = c.begin(); i != c.end(); ++i) {
2851  (*i)->hide_things ();
2852  }
2853 }
2854 
2855 void
2857 {
2859 }
2860 
2861 XMLNode *
2863 {
2864  if (!_parent_strip) {
2865  return 0;
2866  }
2867 
2869 
2870  XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
2871  assert (strip);
2872  return st.get_or_add_node (strip, entry->state_id());
2873 }
2874 
2875 void
2877 {
2878  XMLNode* proc = entry_gui_object_state (entry);
2879  if (!proc) {
2880  return;
2881  }
2882 
2883  /* XXX: this is a bit inefficient; we just remove all child nodes and re-add them */
2884  proc->remove_nodes_and_delete (X_("Object"));
2885  entry->add_control_state (proc);
2886 }
2887 
2888 bool
2890 {
2891  return _parent_strip && !_parent_strip->mixer_owned();
2892 }
2893 
2895  : WM::ProxyBase (name, string())
2896  , _processor_box (box)
2897  , _processor (processor)
2898  , is_custom (false)
2899  , want_custom (false)
2900 {
2902  if (!p) {
2903  return;
2904  }
2906 }
2907 
2909 {
2910  /* processor window proxies do not own the windows they create with
2911  * ::get(), so set _window to null before the normal WindowProxy method
2912  * deletes it.
2913  */
2914  _window = 0;
2915 }
2916 
2917 void
2919 {
2920  delete _window;
2921  _window = 0;
2922  WM::Manager::instance().remove (this);
2923  /* should be no real reason to do this, since the object that would
2924  send DropReferences is about to be deleted, but lets do it anyway.
2925  */
2927 }
2928 
2931 {
2932  /* we don't care */
2933  return 0;
2934 }
2935 
2936 XMLNode&
2938 {
2939  XMLNode *node;
2940  node = &ProxyBase::get_state();
2941  node->add_property (X_("custom-ui"), is_custom? X_("yes") : X_("no"));
2942  return *node;
2943 }
2944 
2945 void
2947 {
2948  XMLNodeList children = node.children ();
2949  XMLNodeList::const_iterator i = children.begin ();
2950  while (i != children.end()) {
2951  XMLProperty* prop = (*i)->property (X_("name"));
2952  if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
2953  break;
2954  }
2955  ++i;
2956  }
2957 
2958  if (i != children.end()) {
2959  XMLProperty* prop;
2960  if ((prop = (*i)->property (X_("custom-ui"))) != 0) {
2962  }
2963  }
2964 
2965  ProxyBase::set_state(node);
2966 }
2967 
2968 Gtk::Window*
2970 {
2972 
2973  if (!p) {
2974  return 0;
2975  }
2976  if (_window && (is_custom != want_custom)) {
2977  /* drop existing window - wrong type */
2978  drop_window ();
2979  }
2980 
2981  if (!_window) {
2982  if (!create) {
2983  return 0;
2984  }
2985 
2988 
2989  if (_window) {
2990  setup ();
2991  }
2992  }
2993 
2994  return _window;
2995 }
2996 
2997 void
2999 {
3000  if (_window && (is_custom != want_custom)) {
3001  /* drop existing window - wrong type */
3002  drop_window ();
3003  }
3005 
3007 }
bool processor_button_press_event(GdkEventButton *, ProcessorEntry *)
void set_control_state(XMLNode const *)
void compute_processor_sort_keys()
void show_all_controls()
static void rb_choose_insert()
void add_processor_to_display(boost::weak_ptr< ARDOUR::Processor >)
boost::shared_ptr< ARDOUR::Route > _route
void set_ports(ARDOUR::ChanCount const ports)
bool use_plugins(const SelectedPlugins &)
void object_drop(Gtkmm2ext::DnDVBox< ProcessorEntry > *, ProcessorEntry *, Glib::RefPtr< Gdk::DragContext > const &)
LIBGTKMM2EXT_API Gtk::Widget * get_widget(const char *name)
Definition: actions.cc:366
bool one_processor_can_be_edited()
void show_processor_menu(int)
PBD::ScopedConnection _splitting_connection
sigc::signal< void > signal_led_clicked
std::string name(Width) const
PBD::ScopedConnection going_away_connection
void all_visible_processors_active(bool state)
float lower
Minimum value (in Hz, for frequencies)
ChanCount natural_output_streams() const
bool get_sae() const
Definition: profile.h:48
std::list< T * > selection() const
Definition: dndvbox.h:117
PBD::Signal0< void > DropReferences
Definition: destructible.h:34
sigc::signal< void > signal_clicked
void show_send(boost::shared_ptr< ARDOUR::Send >)
PBD::ScopedConnectionList _mixer_strip_connections
const std::string & value() const
Definition: xml++.h:159
PBD::Signal1< void, const PropertyChange & > PropertyChanged
Definition: stateful.h:87
boost::shared_ptr< Send > internal_send_for(boost::shared_ptr< const Route > target) const
Definition: route.cc:3934
PBD::Signal0< void > PluginIoReConfigure
void processor_configuration_changed(const ARDOUR::ChanCount in, const ARDOUR::ChanCount out)
gint idle_delete_processor(boost::weak_ptr< ARDOUR::Processor >)
bool processor_operation(ProcessorOperation)
void processor_active_changed()
#define ngettext(Msgid1, Msgid2, N)
Definition: gettext.h:61
void weird_plugin_dialog(ARDOUR::Plugin &p, ARDOUR::Route::ProcessorStreams streams)
int add_processors(const ProcessorList &, boost::shared_ptr< Processor >, ProcessorStreams *err=0)
Definition: route.cc:1288
static Glib::RefPtr< Gtk::Action > edit_action
int add_processor_by_index(boost::shared_ptr< Processor >, int, ProcessorStreams *err=0, bool activation_allowed=true)
Definition: route.cc:1110
bool edit_aux_send(boost::shared_ptr< ARDOUR::Processor >)
void set_window_proxy(ProcessorWindowProxy *wp)
Definition: processor.cc:281
void set_distinct_led_click(bool yn)
boost::shared_ptr< ARDOUR::Processor > _processor_being_created
PluginInsertProcessorEntry(ProcessorBox *, boost::shared_ptr< ARDOUR::PluginInsert >, Width)
PBD::ScopedConnectionList _route_connections
Definition: ardour_ui.h:130
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
void send_io_finished(IOSelector::Result, boost::weak_ptr< ARDOUR::Processor >, IOSelectorWindow *)
#define UINT_RGBA_G_FLT(x)
Definition: rgb_macros.h:58
void revert_to_default_display()
boost::shared_ptr< Pannable > pannable() const
Definition: route.cc:4023
std::vector< Glib::RefPtr< Gtk::Action > > engine_sensitive_actions
Definition: actions.cc:61
static Glib::RefPtr< Gtk::Action > edit_generic_action
ArdourButton _button
static void rb_copy()
static void rb_choose_plugin()
static Manager & instance()
Gtk::Menu * build_processor_menu()
int set_state(const XMLNode &, int version)
Definition: send.cc:227
void clear_processors()
static void rb_select_all()
void edit_processor(boost::shared_ptr< ARDOUR::Processor >)
static Glib::RefPtr< Gtk::Action > cut_action
static void rb_choose_aux(boost::weak_ptr< ARDOUR::Route >)
void delete_dragged_processors(const std::list< boost::shared_ptr< ARDOUR::Processor > > &)
uint32_t n_audio() const
Definition: chan_count.h:63
void route_processors_changed(ARDOUR::RouteProcessorChange)
tuple f
Definition: signals.py:35
Definition: Beats.hpp:239
ProcessorBox * _processor_box
Definition: processor_box.h:98
LIBPBD_API Transmitter error
#define UINT_RGBA_B_FLT(x)
Definition: rgb_macros.h:59
boost::shared_ptr< ARDOUR::Delivery > current_delivery() const
Definition: mixer_strip.h:103
int remove_processor(boost::shared_ptr< Processor >, ProcessorStreams *err=0, bool need_process_lock=true)
Definition: route.cc:1574
const XMLNodeList & children(const std::string &str=std::string()) const
Definition: xml++.cc:329
Gtk::Window * get_generic_editor_window(boost::shared_ptr< ARDOUR::Processor >)
void processor_menu_unmapped()
PBD::ScopedConnection active_connection
void set_width(Width)
void * get_ui() const
Definition: processor.h:116
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
static void rb_cut()
void add_child(T *child)
Definition: dndvbox.h:84
PBD::Signal2< void, ChanCount, ChanCount > ConfigurationChanged
Definition: processor.h:113
boost::shared_ptr< Plugin > plugin(uint32_t num=0) const
boost::shared_ptr< MuteMaster > mute_master() const
Definition: route.h:418
static const uint32_t midi_port_color
void set_route(boost::shared_ptr< ARDOUR::Route >)
void set_visual_state(Gtkmm2ext::VisualState, bool)
void setup_entry_positions()
void set_enum_width(Width)
uint32_t get_count() const
Definition: plugin_insert.h:75
void register_window(ProxyBase *)
int set_state(const XMLNode &, int version)
Definition: processor.cc:173
static XMLNode * get_node(const XMLNode *, const std::string &)
Definition: gui_object.cc:37
ProcessorEntry(ProcessorBox *, boost::shared_ptr< ARDOUR::Processor >, Width)
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
static void rb_deselect_all()
Gtk::Window * get(bool create=false)
void add_internal_send(boost::shared_ptr< Route >, int, boost::shared_ptr< Route >)
Definition: session.cc:2848
Gtk::Menu * build_controls_menu()
#define invalidator(x)
Definition: gui_thread.h:40
uint32_t _visible_prefader_processors
uint32_t n_midi() const
Definition: chan_count.h:66
void set_initial_text(std::string txt)
Definition: prompter.h:50
void redisplay_processors()
void mixer_strip_delivery_changed(boost::weak_ptr< ARDOUR::Delivery >)
void use_window(Gtk::Window &)
void update_gui_object_state(ProcessorEntry *)
static void rb_clear_pre()
void select_none()
Definition: dndvbox.h:167
std::string state_id() const
void get_selected_processors(ProcSelection &) const
std::string _name
std::list< XMLNode * > XMLNodeList
Definition: xml++.h:44
void maybe_add_processor_to_ui_list(boost::weak_ptr< ARDOUR::Processor >)
sigc::signal< void, DnDVBox *, T *, Glib::RefPtr< Gdk::DragContext > const & > DropFromAnotherBox
Definition: dndvbox.h:222
sigc::signal< void, boost::shared_ptr< ARDOUR::Processor > > ProcessorSelected
std::vector< ARDOUR::PluginPtr > SelectedPlugins
Gtk::Menu * processor_menu
void set_position(Position, uint32_t)
XMLNode * entry_gui_object_state(ProcessorEntry *)
static void rb_clear()
#define _(Text)
Definition: i18n.h:11
void rename_processors()
virtual void deactivate()
Definition: processor.h:80
void processor_property_changed(const PBD::PropertyChange &)
ChanCount natural_input_streams() const
LIBGTKMM2EXT_API void set_sensitive(std::vector< Glib::RefPtr< Gtk::Action > > &actions, bool)
PortIcon _output_icon
boost::function< PluginSelector *()> _get_plugin_selector
virtual std::string display_name() const
Definition: processor.h:56
ProcessorBox(ARDOUR::Session *, boost::function< PluginSelector *()> get_plugin_selector, RouteProcessorSelection &, MixerStrip *parent, bool owner_is_mixer=false)
#define X_(Text)
Definition: i18n.h:13
bool io_name_is_legal(const std::string &)
Definition: session.cc:3226
void return_io_finished(IOSelector::Result, boost::weak_ptr< ARDOUR::Processor >, IOSelectorWindow *)
static void rb_ab_plugins()
ChanCount output_streams() const
XMLProperty * property(const char *)
Definition: xml++.cc:413
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
void route_property_changed(const PBD::PropertyChange &)
bool on_expose_event(GdkEventExpose *)
float upper
Maximum value (in Hz, for frequencies)
LIBGTKMM2EXT_API void set_no_tooltip_whatsoever(Gtk::Widget &)
Definition: utils.cc:797
void delete_when_idle(T *obj)
Definition: doi.h:34
void set_default_value(float)
Definition: pixfader.cc:635
void set_prompt(std::string prompt)
Definition: prompter.h:46
void set_sinks(ARDOUR::ChanCount const sinks)
void set_sources(ARDOUR::ChanCount const sources)
static void rb_rename()
XMLNode * get_or_add_node(const std::string &)
std::vector< boost::shared_ptr< ARDOUR::Processor > > ProcSelection
const ParameterDescriptor & desc() const
Gtkmm2ext::VisualState visual_state() const
Definition: cairo_widget.h:41
virtual double internal_to_interface(double i) const
Definition: controllable.h:71
virtual std::string describe_parameter(Evoral::Parameter param)
Definition: automatable.cc:160
XMLNode & get_state() const
bool string_is_affirmative(const std::string &str)
Definition: convert.cc:282
bool on_expose_event(GdkEventExpose *)
void select_all()
Definition: dndvbox.h:157
int set_state(const XMLNode &, int version)
Definition: return.cc:80
PortIcon _input_icon
Definition: amp.h:29
bool processor_can_be_edited(boost::shared_ptr< ARDOUR::Processor >)
boost::shared_ptr< Route > master_out() const
Definition: session.h:718
void set_active(T *c)
Definition: dndvbox.h:125
void hide_all_controls()
boost::shared_ptr< ARDOUR::PluginInsert > _plugin_insert
ChanCount input_streams() const
void choose_plugin()
Gtk::Menu * build_send_options_menu()
void all_visible_processors_active(bool)
Definition: route.cc:1934
const PBD::ID & id() const
Definition: stateful.h:68
virtual bool set_name(const std::string &str)
int add_placeholder(double y)
Definition: dndvbox.h:205
std::string to_s() const
Definition: id.cc:78
ARDOUR::SessionHandlePtr * session_handle()
const std::set< Evoral::Parameter > & what_can_be_automated() const
Definition: automatable.h:76
ProcessorBox * _parent
static void rb_choose_send()
void set_visual_state(Gtkmm2ext::VisualState)
ChanCount n_outputs() const
Definition: route.h:93
void set_text(const std::string &, bool centered=true, bool expose=true)
Definition: pixfader.cc:655
#define gui_context()
Definition: gui_thread.h:36
RouteProcessorSelection & _rr_selection
Control(boost::shared_ptr< ARDOUR::AutomationControl >, std::string const &)
PBD::ScopedConnection name_connection
void generic_edit_processor(boost::shared_ptr< ARDOUR::Processor >)
bool leave_notify(GdkEventCrossing *ev)
void toggle_panner_link()
static void rb_clear_post()
void foreach_processor(boost::function< void(boost::weak_ptr< Processor >)> method)
Definition: route.h:203
virtual void setup_visuals()
void choose_aux(boost::weak_ptr< ARDOUR::Route >)
void paste_processor_state(const XMLNodeList &, boost::shared_ptr< ARDOUR::Processor >)
static Glib::RefPtr< Gtk::Action > rename_action
static ProcessorBox * _current_processor_box
void deselect_all_processors()
std::string generate_processor_title(boost::shared_ptr< ARDOUR::PluginInsert > pi)
Gtk::VBox _vbox
static void rb_delete()
void route_going_away()
int remove_processors(const ProcessorList &, ProcessorStreams *err=0)
Definition: route.cc:1685
std::string state_id() const
void delete_processors(const ProcSelection &)
void toggle_control_visibility(Control *)
uint32_t _position_num
void set_title(const std::string &title)
Definition: plugin_ui.cc:207
Gtk::Window * get_editor_window(boost::shared_ptr< ARDOUR::Processor >, bool)
std::vector< Glib::RefPtr< Gtk::Action > > plugin_selection_sensitive_actions
Definition: actions.cc:52
void help_count_visible_prefader_processors(boost::weak_ptr< ARDOUR::Processor >, uint32_t *, bool *)
MixerStrip * _parent_strip
static GUIObjectState & gui_object_state()
Definition: axis_view.cc:98
void remove(const ProxyBase *)
LIBARDOUR_API RuntimeProfile * Profile
Definition: globals.cc:120
void get_result(std::string &str, bool strip=true)
Definition: prompter.cc:104
void set_fallthrough_to_parent(bool fall)
bool processor_button_release_event(GdkEventButton *, ProcessorEntry *)
PluginInfoPtr get_info() const
Definition: plugin.h:225
sigc::signal< void > Reordered
Definition: dndvbox.h:211
ProcessorWindowProxy * window_proxy() const
Definition: processor.h:118
void set_custom_ui_mode(bool use_custom)
Definition: processor_box.h:92
void cut_processors(const ProcSelection &)
void set_tip(Gtk::Widget &w, const gchar *tip)
static Glib::RefPtr< Gtk::Action > paste_action
ChanCount n_inputs
Definition: plugin.h:63
XMLProperty * add_property(const char *name, const std::string &value)
ChanCount count
Input requested of processor.
Definition: route.h:254
void set_ui(void *)
Definition: processor.cc:275
void for_selected_processors(void(ProcessorBox::*pmf)(boost::shared_ptr< ARDOUR::Processor >))
bool no_processor_redisplay
uint32_t index
Index of processor where configuration failed.
Definition: route.h:253
PBD::Signal1< void, RouteProcessorChange > processors_changed
Definition: route.h:312
LIBARDOUR_API double gain_to_slider_position_with_max(double g, double max_gain=2.0)
Definition: utils.cc:756
void copy_processors(const ProcSelection &)
const char * name
SessionObject * owner() const
Definition: processor.cc:293
void add_child_nocopy(XMLNode &)
Definition: xml++.cc:357
PBD::ScopedConnection config_connection
void remove_placeholder()
Definition: dndvbox.h:193
bool get_active()
Definition: cairo_widget.h:57
uint32_t get(DataType t) const
Definition: chan_count.h:59
std::list< T * > children()
Definition: dndvbox.h:100
std::list< Control * > _controls
void set_state(const XMLNode &)
void set_active(bool)
Gtk::Adjustment _adjustment
ProcessorWindowProxy * find_window_proxy(boost::shared_ptr< ARDOUR::Processor >) const
void set_spacing(int s)
Definition: dndvbox.h:189
Definition: xml++.h:95
Width
Definition: enums.h:25
static void rb_edit_generic()
std::string name() const
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
Definition: region.cc:65
boost::shared_ptr< IO > output()
Definition: io_processor.h:62
void set_processor_ui(boost::shared_ptr< ARDOUR::Processor >, Gtk::Window *)
void set_text(const std::string &)
void set(DataType t, uint32_t count)
Definition: chan_count.h:58
void choose_insert()
Gtk::EventBox & action_widget()
std::list< boost::shared_ptr< Processor > > ProcessorList
Definition: route.h:76
PBD::Signal1< void, boost::weak_ptr< ARDOUR::Delivery > > DeliveryChanged
Definition: mixer_strip.h:116
PBD::Signal0< void > Changed
Definition: controllable.h:94
boost::weak_ptr< ARDOUR::Processor > _processor
Definition: processor_box.h:99
bool can_cut() const
boost::shared_ptr< ARDOUR::Processor > processor() const
static void rb_activate_all()
ARDOUR::ChanCount _ports
PBD::Signal0< void > ActiveChanged
Definition: processor.h:112
int reorder_processors(const ProcessorList &new_order, ProcessorStreams *err=0)
Definition: route.cc:2075
WindowRef wr
Definition: au_pluginui.h:98
virtual const char * name() const =0
PBD::ScopedConnection _connection
virtual double interface_to_internal(double i) const
Definition: controllable.h:72
void select_all_processors()
void set_splitting(const bool splitting)
XMLNode * extra_xml(const std::string &str, bool add_if_missing=false)
Definition: stateful.cc:77
sigc::signal< void, Result > Finished
Definition: port_matrix.h:164
Definition: debug.h:30
string short_version(string orig, string::size_type target_length)
Definition: convert.cc:76
static void rb_paste()
void rename_processor(boost::shared_ptr< ARDOUR::Processor >)
void add_state(XMLNode *) const
boost::shared_ptr< AutomationControl > automation_control(const Evoral::Parameter &id, bool create_if_missing=false)
Definition: automatable.cc:475
bool splitting() const
static void rb_edit()
virtual void activate()
Definition: processor.h:79
FreezeState freeze_state() const
Definition: track.cc:175
virtual void toggle()
bool contains(PropertyDescriptor< T > p) const
IOSelector & selector()
Definition: io_selector.h:75
Position _position
void paste_processors()
Gtk::Widget & widget()
static void register_actions()
virtual void set_session(ARDOUR::Session *)
Gtkmm2ext::DnDVBox< ProcessorEntry > processor_display
void set_controllable(boost::shared_ptr< PBD::Controllable > c)
Gtk::Window * _window
void ab_plugins(bool forward)
Definition: route.cc:1452
std::string state_id() const
Gtk::ScrolledWindow processor_scroller
bool mixer_owned() const
Definition: mixer_strip.h:107
static float ui_scale
Definition: ardour_ui.h:189
sigc::signal< bool, GdkEventButton *, T * > ButtonRelease
Definition: dndvbox.h:217
int set_state(const XMLNode &node, int version)
Definition: enums.h:27
void remove_nodes_and_delete(const std::string &)
static const uint32_t audio_port_color
#define MISSING_INVALIDATOR
Definition: event_loop.h:86
boost::shared_ptr< ARDOUR::Processor > _processor
LIBGTKMM2EXT_API void add_action_group(Glib::RefPtr< Gtk::ActionGroup >)
RoutingIcon _routing_icon
sigc::connection rapid_connect(const sigc::slot< void > &slot)
Definition: timers.cc:183
XMLNodeList::const_iterator XMLNodeConstIterator
Definition: xml++.h:49
boost::shared_ptr< PannerShell > panner_shell() const
Definition: delivery.h:95
bool selected(T *child) const
Definition: dndvbox.h:139
ProcessorWindowProxy(std::string const &, ProcessorBox *, boost::weak_ptr< ARDOUR::Processor >)
Placement
Definition: types.h:375
boost::shared_ptr< RouteList > get_routes_with_internal_returns() const
Definition: session.cc:3212
virtual ChanCount input_streams() const
Definition: processor.h:88
Definition: enums.h:26
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::Action > register_action(Glib::RefPtr< Gtk::ActionGroup > group, const char *name, const char *label)
bool active() const
Definition: processor.h:61
bool connected() const
Definition: audioengine.cc:919
virtual double internal_to_user(double i) const
Definition: controllable.h:73
ARDOUR::Session * _session
void add_control_state(XMLNode *) const
sigc::signal< bool, GdkEventButton *, T * > ButtonPress
Definition: dndvbox.h:214
static void rb_deactivate_all()
AudioEngine & engine()
Definition: session.h:546
void set_led_left(bool yn)
virtual void hide_things()
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
bool is_editor_mixer_strip() const
std::string drag_text() const
Gtk::Window * get_processor_ui(boost::shared_ptr< ARDOUR::Processor >) const
Gtk::Menu * build_possible_aux_menu()
virtual ChanCount output_streams() const
Definition: processor.h:89
void report_failed_reorder()
Gtkmm2ext::HSliderController _slider
void popup_error(const std::string &text)
Definition: gtk_ui.cc:665
int set_state(const XMLNode &, int version)
Definition: port_insert.cc:177
void clear_processors(Placement)
Definition: route.cc:1501
void set_state(XMLNode const *)
bool enter_notify(GdkEventCrossing *ev)
const XMLNode & get_node() const
#define UINT_RGBA_R_FLT(x)
Definition: rgb_macros.h:57