2 Copyright (C) 2000-2004 Paul Davis
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.
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.
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.
21 #include "gtk2ardour-config.h"
28 #include <sigc++/bind.h>
30 #include "pbd/convert.h"
32 #include <glibmm/miscutils.h>
34 #include <gtkmm/messagedialog.h>
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>
42 #include "ardour/amp.h"
43 #include "ardour/ardour.h"
44 #include "ardour/audio_track.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/internal_send.h"
47 #include "ardour/internal_return.h"
48 #include "ardour/ladspa_plugin.h"
49 #include "ardour/meter.h"
50 #include "ardour/plugin_insert.h"
51 #include "ardour/port_insert.h"
52 #include "ardour/profile.h"
53 #include "ardour/return.h"
54 #include "ardour/route.h"
55 #include "ardour/send.h"
56 #include "ardour/session.h"
57 #include "ardour/dB.h"
60 #include "ardour_dialog.h"
61 #include "ardour_ui.h"
62 #include "gui_thread.h"
63 #include "io_selector.h"
66 #include "mixer_strip.h"
67 #include "plugin_selector.h"
68 #include "plugin_ui.h"
69 #include "port_insert_ui.h"
70 #include "processor_box.h"
71 #include "public_editor.h"
72 #include "return_ui.h"
73 #include "route_processor_selection.h"
79 #ifdef HAVE_AUDIOUNITS
84 using namespace ARDOUR
;
88 using namespace Gtkmm2ext
;
90 ProcessorBox
* ProcessorBox::_current_processor_box
= 0;
91 RefPtr
<Action
> ProcessorBox::paste_action
;
92 RefPtr
<Action
> ProcessorBox::cut_action
;
93 RefPtr
<Action
> ProcessorBox::rename_action
;
94 RefPtr
<Action
> ProcessorBox::edit_action
;
95 Glib::RefPtr
<Gdk::Pixbuf
> SendProcessorEntry::_slider
;
97 ProcessorEntry::ProcessorEntry (boost::shared_ptr
<Processor
> p
, Width w
)
98 : _position (PreFader
)
101 , _visual_state (Gtk::STATE_NORMAL
)
103 _hbox
.pack_start (_active
, false, false);
104 _event_box
.add (_name
);
105 _hbox
.pack_start (_event_box
, true, true);
106 _vbox
.pack_start (_hbox
);
109 /* without this, the border is mis-drawn on some systems */
110 _vbox
.set_border_width (1);
112 _name
.set_alignment (0, 0.5);
113 _name
.set_text (name ());
114 _name
.set_padding (2, 2);
116 if (boost::dynamic_pointer_cast
<Amp
> (p
)) {
117 /* Fader processor gets a special look */
118 _event_box
.set_name ("ProcessorFader");
119 _frame
.set_name ("ProcessorFaderFrame");
120 _name
.set_padding (2, 4);
123 _active
.set_active (_processor
->active ());
124 _active
.signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::active_toggled
));
133 _processor
->ActiveChanged
.connect (active_connection
, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed
, this), gui_context());
134 _processor
->PropertyChanged
.connect (name_connection
, invalidator (*this), ui_bind (&ProcessorEntry::processor_property_changed
, this, _1
), gui_context());
138 ProcessorEntry::action_widget ()
144 ProcessorEntry::widget ()
150 ProcessorEntry::drag_text () const
156 ProcessorEntry::set_visual_state (Gtk::StateType t
)
163 ProcessorEntry::set_position (Position p
)
170 ProcessorEntry::setup_visuals ()
174 _event_box
.set_name ("ProcessorPreFader");
175 if (_visual_state
== Gtk::STATE_NORMAL
) {
176 _frame
.set_name ("ProcessorPreFaderFrame");
181 _event_box
.set_name ("ProcessorFader");
182 if (_visual_state
== Gtk::STATE_NORMAL
) {
183 _frame
.set_name ("ProcessorFaderFrame");
188 _event_box
.set_name ("ProcessorPostFader");
189 if (_visual_state
== Gtk::STATE_NORMAL
) {
190 _frame
.set_name ("ProcessorPostFaderFrame");
195 switch (_visual_state
) {
196 case Gtk::STATE_NORMAL
:
197 /* _frame has been set up above */
198 _event_box
.set_state (Gtk::STATE_NORMAL
);
200 case Gtk::STATE_SELECTED
:
201 _frame
.set_name ("ProcessorFrameSelected");
202 /* don't change the background of the box when it is selected */
203 _event_box
.set_state (Gtk::STATE_NORMAL
);
205 case Gtk::STATE_ACTIVE
:
206 _frame
.set_name ("ProcessorFrameActiveSend");
207 _event_box
.set_state (Gtk::STATE_ACTIVE
);
215 boost::shared_ptr
<Processor
>
216 ProcessorEntry::processor () const
222 ProcessorEntry::set_enum_width (Width w
)
228 ProcessorEntry::active_toggled ()
230 if (_active
.get_active ()) {
231 if (!_processor
->active ()) {
232 _processor
->activate ();
235 if (_processor
->active ()) {
236 _processor
->deactivate ();
242 ProcessorEntry::processor_active_changed ()
244 if (_active
.get_active () != _processor
->active ()) {
245 _active
.set_active (_processor
->active ());
250 ProcessorEntry::processor_property_changed (const PropertyChange
& what_changed
)
252 if (what_changed
.contains (ARDOUR::Properties::name
)) {
253 _name
.set_text (name ());
258 ProcessorEntry::name () const
260 boost::shared_ptr
<Send
> send
;
263 if ((send
= boost::dynamic_pointer_cast
<Send
> (_processor
)) != 0 &&
264 !boost::dynamic_pointer_cast
<InternalSend
>(_processor
)) {
268 /* grab the send name out of its overall name */
270 string::size_type lbracket
, rbracket
;
271 lbracket
= send
->name().find ('[');
272 rbracket
= send
->name().find (']');
276 name_display
+= send
->name().substr (lbracket
+1, lbracket
-rbracket
-1);
279 name_display
+= PBD::short_version (send
->name().substr (lbracket
+1, lbracket
-rbracket
-1), 4);
287 name_display
+= _processor
->display_name();
290 name_display
+= PBD::short_version (_processor
->display_name(), 5);
299 SendProcessorEntry::SendProcessorEntry (boost::shared_ptr
<Send
> s
, Width w
)
300 : ProcessorEntry (s
, w
),
302 /* set the adjustment to a gain of 0dB so that the fader's default value is right */
303 _adjustment (0.781787, 0, 1, 0.01, 0.1),
304 _fader (_slider
, &_adjustment
, 0, false),
305 _ignore_gain_change (false)
307 _fader
.set_name ("SendFader");
308 _fader
.set_controllable (_send
->amp()->gain_control ());
309 _vbox
.pack_start (_fader
);
313 _adjustment
.signal_value_changed().connect (sigc::mem_fun (*this, &SendProcessorEntry::gain_adjusted
));
314 _send
->amp()->gain_control()->Changed
.connect (send_gain_connection
, invalidator (*this), boost::bind (&SendProcessorEntry::show_gain
, this), gui_context());
319 SendProcessorEntry::setup_slider_pix ()
321 _slider
= ::get_icon ("fader_belt_h_thin");
326 SendProcessorEntry::show_gain ()
328 ENSURE_GUI_THREAD (*this, &SendProcessorEntry::show_gain
)
330 float const value
= gain_to_slider_position (_send
->amp()->gain ());
332 if (_adjustment
.get_value() != value
) {
333 _ignore_gain_change
= true;
334 _adjustment
.set_value (value
);
335 _ignore_gain_change
= false;
339 s
.setf (ios::fixed
, ios::floatfield
);
340 s
<< accurate_coefficient_to_dB (_send
->amp()->gain ()) << _("dB");
341 _fader
.set_tooltip_text (s
.str ());
346 SendProcessorEntry::gain_adjusted ()
348 if (_ignore_gain_change
) {
352 _send
->amp()->set_gain (slider_position_to_gain (_adjustment
.get_value()), this);
356 SendProcessorEntry::set_pixel_width (int p
)
358 _fader
.set_fader_length (p
);
361 PluginInsertProcessorEntry::PluginInsertProcessorEntry (boost::shared_ptr
<ARDOUR::PluginInsert
> p
, Width w
)
362 : ProcessorEntry (p
, w
)
365 p
->SplittingChanged
.connect (
366 _splitting_connection
, invalidator (*this), ui_bind (&PluginInsertProcessorEntry::plugin_insert_splitting_changed
, this), gui_context()
369 _splitting_icon
.set_size_request (-1, 12);
371 _vbox
.pack_start (_splitting_icon
);
372 _vbox
.reorder_child (_splitting_icon
, 0);
374 plugin_insert_splitting_changed ();
378 PluginInsertProcessorEntry::plugin_insert_splitting_changed ()
380 if (_plugin_insert
->splitting ()) {
381 _splitting_icon
.show ();
383 _splitting_icon
.hide ();
388 PluginInsertProcessorEntry::hide_things ()
390 plugin_insert_splitting_changed ();
394 PluginInsertProcessorEntry::setup_visuals ()
398 _splitting_icon
.set_name ("ProcessorPreFader");
402 _splitting_icon
.set_name ("ProcessorFader");
406 _splitting_icon
.set_name ("ProcessorPostFader");
410 ProcessorEntry::setup_visuals ();
414 PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose
* ev
)
416 cairo_t
* cr
= gdk_cairo_create (get_window()->gobj());
418 cairo_set_line_width (cr
, 1);
420 double const width
= ev
->area
.width
;
421 double const height
= ev
->area
.height
;
423 Gdk::Color
const bg
= get_style()->get_bg (STATE_NORMAL
);
424 cairo_set_source_rgb (cr
, bg
.get_red_p (), bg
.get_green_p (), bg
.get_blue_p ());
426 cairo_rectangle (cr
, 0, 0, width
, height
);
429 Gdk::Color
const fg
= get_style()->get_fg (STATE_NORMAL
);
430 cairo_set_source_rgb (cr
, fg
.get_red_p (), fg
.get_green_p (), fg
.get_blue_p ());
432 cairo_move_to (cr
, width
* 0.3, height
);
433 cairo_line_to (cr
, width
* 0.3, height
* 0.5);
434 cairo_line_to (cr
, width
* 0.7, height
* 0.5);
435 cairo_line_to (cr
, width
* 0.7, height
);
436 cairo_move_to (cr
, width
* 0.5, height
* 0.5);
437 cairo_line_to (cr
, width
* 0.5, 0);
443 ProcessorBox::ProcessorBox (ARDOUR::Session
* sess
, boost::function
<PluginSelector
*()> get_plugin_selector
,
444 RouteRedirectSelection
& rsel
, MixerStrip
* parent
, bool owner_is_mixer
)
445 : _parent_strip (parent
)
446 , _owner_is_mixer (owner_is_mixer
)
447 , ab_direction (true)
448 , _get_plugin_selector (get_plugin_selector
)
449 , _placement(PreFader
)
450 , _rr_selection(rsel
)
456 send_action_menu
= 0;
457 no_processor_redisplay
= false;
459 processor_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
460 processor_scroller
.add (processor_display
);
461 pack_start (processor_scroller
, true, true);
463 processor_display
.set_flags (CAN_FOCUS
);
464 processor_display
.set_name ("ProcessorList");
465 processor_display
.set_size_request (48, -1);
466 processor_display
.set_data ("processorbox", this);
467 processor_display
.set_spacing (2);
469 processor_display
.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify
), false);
470 processor_display
.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify
), false);
472 processor_display
.signal_key_press_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_press_event
));
473 processor_display
.signal_key_release_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_release_event
));
475 processor_display
.ButtonPress
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event
));
476 processor_display
.ButtonRelease
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event
));
478 processor_display
.Reordered
.connect (sigc::mem_fun (*this, &ProcessorBox::reordered
));
479 processor_display
.DropFromAnotherBox
.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop
));
480 processor_display
.SelectionChanged
.connect (sigc::mem_fun (*this, &ProcessorBox::selection_changed
));
482 processor_scroller
.show ();
483 processor_display
.show ();
486 parent
->DeliveryChanged
.connect (
487 _mixer_strip_connections
, invalidator (*this), ui_bind (&ProcessorBox::mixer_strip_delivery_changed
, this, _1
), gui_context ()
492 ProcessorBox::~ProcessorBox ()
497 ProcessorBox::set_route (boost::shared_ptr
<Route
> r
)
503 _route_connections
.drop_connections();
505 /* new route: any existing block on processor redisplay must be meaningless */
506 no_processor_redisplay
= false;
509 _route
->processors_changed
.connect (
510 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_processors_changed
, this, _1
), gui_context()
513 _route
->DropReferences
.connect (
514 _route_connections
, invalidator (*this), boost::bind (&ProcessorBox::route_going_away
, this), gui_context()
517 _route
->PropertyChanged
.connect (
518 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_property_changed
, this, _1
), gui_context()
521 redisplay_processors ();
525 ProcessorBox::route_going_away ()
527 /* don't keep updating display as processors are deleted */
528 no_processor_redisplay
= true;
532 ProcessorBox::object_drop(DnDVBox
<ProcessorEntry
>* source
, ProcessorEntry
* position
, Glib::RefPtr
<Gdk::DragContext
> const & context
)
534 boost::shared_ptr
<Processor
> p
;
536 p
= position
->processor ();
539 list
<ProcessorEntry
*> children
= source
->selection ();
540 list
<boost::shared_ptr
<Processor
> > procs
;
541 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
542 procs
.push_back ((*i
)->processor ());
545 for (list
<boost::shared_ptr
<Processor
> >::const_iterator i
= procs
.begin(); i
!= procs
.end(); ++i
) {
546 XMLNode
& state
= (*i
)->get_state ();
548 nlist
.push_back (&state
);
549 paste_processor_state (nlist
, p
);
553 /* since the dndvbox doesn't take care of this properly, we have to delete the originals
557 if ((context
->get_suggested_action() == Gdk::ACTION_MOVE
) && source
) {
558 ProcessorBox
* other
= reinterpret_cast<ProcessorBox
*> (source
->get_data ("processorbox"));
560 cerr
<< "source was another processor box, delete the selected items\n";
561 other
->delete_dragged_processors (procs
);
567 ProcessorBox::update()
569 redisplay_processors ();
573 ProcessorBox::set_width (Width w
)
581 list
<ProcessorEntry
*> children
= processor_display
.children ();
582 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
583 (*i
)->set_enum_width (w
);
586 redisplay_processors ();
590 ProcessorBox::build_send_action_menu ()
592 using namespace Menu_Helpers
;
594 send_action_menu
= new Menu
;
595 send_action_menu
->set_name ("ArdourContextMenu");
596 MenuList
& items
= send_action_menu
->items();
598 items
.push_back (MenuElem (_("New send"), sigc::mem_fun(*this, &ProcessorBox::new_send
)));
599 items
.push_back (MenuElem (_("Show send controls"), sigc::mem_fun(*this, &ProcessorBox::show_send_controls
)));
603 ProcessorBox::build_possible_aux_menu ()
605 boost::shared_ptr
<RouteList
> rl
= _session
->get_routes_with_internal_returns();
611 using namespace Menu_Helpers
;
612 Menu
* menu
= manage (new Menu
);
613 MenuList
& items
= menu
->items();
615 for (RouteList::iterator r
= rl
->begin(); r
!= rl
->end(); ++r
) {
616 if (!_route
->internal_send_for (*r
) && *r
!= _route
) {
617 items
.push_back (MenuElem ((*r
)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux
), boost::weak_ptr
<Route
>(*r
))));
625 ProcessorBox::show_send_controls ()
630 ProcessorBox::new_send ()
635 ProcessorBox::show_processor_menu (gint arg
)
637 if (processor_menu
== 0) {
638 processor_menu
= build_processor_menu ();
641 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
643 if (plugin_menu_item
) {
644 plugin_menu_item
->set_submenu (*_get_plugin_selector()->plugin_menu());
647 Gtk::MenuItem
* aux_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/ProcessorMenu/newaux"));
650 Menu
* m
= build_possible_aux_menu();
651 if (m
&& !m
->items().empty()) {
652 aux_menu_item
->set_submenu (*m
);
653 aux_menu_item
->set_sensitive (true);
655 /* stupid gtkmm: we need to pass a null reference here */
656 gtk_menu_item_set_submenu (aux_menu_item
->gobj(), 0);
657 aux_menu_item
->set_sensitive (false);
661 cut_action
->set_sensitive (can_cut());
662 paste_action
->set_sensitive (!_rr_selection
.processors
.empty());
664 processor_menu
->popup (1, arg
);
668 ProcessorBox::enter_notify (GdkEventCrossing
*)
670 _current_processor_box
= this;
671 Keyboard::magic_widget_grab_focus ();
672 processor_display
.grab_focus ();
678 ProcessorBox::leave_notify (GdkEventCrossing
* ev
)
680 switch (ev
->detail
) {
681 case GDK_NOTIFY_INFERIOR
:
684 Keyboard::magic_widget_drop_focus ();
691 ProcessorBox::processor_key_press_event (GdkEventKey
*)
693 /* do real stuff on key release */
698 ProcessorBox::processor_key_release_event (GdkEventKey
*ev
)
701 ProcSelection targets
;
703 get_selected_processors (targets
);
705 if (targets
.empty()) {
708 processor_display
.get_pointer (x
, y
);
710 pair
<ProcessorEntry
*, double> const pointer
= processor_display
.get_child_at_position (y
);
713 targets
.push_back (pointer
.first
->processor ());
718 switch (ev
->keyval
) {
720 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
721 processor_display
.select_all ();
727 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
728 copy_processors (targets
);
734 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
735 cut_processors (targets
);
741 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
742 if (targets
.empty()) {
745 paste_processors (targets
.front());
759 delete_processors (targets
);
764 for (ProcSelection::iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
765 if ((*i
)->active()) {
787 ProcessorBox::processor_button_press_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
789 boost::shared_ptr
<Processor
> processor
;
791 processor
= child
->processor ();
795 bool selected
= processor_display
.selected (child
);
797 if (processor
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
799 if (_session
->engine().connected()) {
800 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
801 toggle_edit_processor (processor
);
805 } else if (processor
&& ev
->button
== 1 && selected
) {
807 // this is purely informational but necessary for route params UI
808 ProcessorSelected (processor
); // emit
810 } else if (!processor
&& ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
) {
813 _get_plugin_selector()->show_manager ();
820 ProcessorBox::processor_button_release_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
822 boost::shared_ptr
<Processor
> processor
;
824 processor
= child
->processor ();
829 if (processor
&& Keyboard::is_delete_event (ev
)) {
831 Glib::signal_idle().connect (sigc::bind (
832 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor
),
833 boost::weak_ptr
<Processor
>(processor
)));
836 } else if (Keyboard::is_context_menu_event (ev
)) {
838 /* figure out if we are above or below the fader/amp processor,
839 and set the next insert position appropriately.
843 if (_route
->processor_is_prefader (processor
)) {
844 _placement
= PreFader
;
846 _placement
= PostFader
;
849 _placement
= PostFader
;
852 show_processor_menu (ev
->time
);
855 } else if (processor
&& Keyboard::is_button2_event (ev
)
857 && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))
861 /* button2-click with no/appropriate modifiers */
863 if (processor
->active()) {
864 processor
->deactivate ();
866 processor
->activate ();
876 ProcessorBox::build_processor_menu ()
878 processor_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/ProcessorMenu") );
879 processor_menu
->set_name ("ArdourContextMenu");
880 return processor_menu
;
884 ProcessorBox::selection_changed ()
886 bool const sensitive
= (processor_display
.selection().empty()) ? false : true;
887 ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions
, sensitive
);
888 edit_action
->set_sensitive (one_processor_can_be_edited ());
890 /* disallow rename for multiple selections and for plugin inserts */
891 rename_action
->set_sensitive (
892 processor_display
.selection().size() == 1 && boost::dynamic_pointer_cast
<PluginInsert
> (processor_display
.selection().front()->processor()) == 0
897 ProcessorBox::select_all_processors ()
899 processor_display
.select_all ();
903 ProcessorBox::deselect_all_processors ()
905 processor_display
.select_none ();
909 ProcessorBox::choose_plugin ()
911 _get_plugin_selector()->set_interested_object (*this);
914 /** @return true if an error occurred, otherwise false */
916 ProcessorBox::use_plugins (const SelectedPlugins
& plugins
)
918 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
920 boost::shared_ptr
<Processor
> processor (new PluginInsert (*_session
, *p
));
922 Route::ProcessorStreams err_streams
;
924 if (_route
->add_processor (processor
, _placement
, &err_streams
, Config
->get_new_plugins_active ())) {
925 weird_plugin_dialog (**p
, err_streams
);
927 // XXX SHAREDPTR delete plugin here .. do we even need to care?
930 if (Profile
->get_sae()) {
931 processor
->activate ();
940 ProcessorBox::weird_plugin_dialog (Plugin
& p
, Route::ProcessorStreams streams
)
942 ArdourDialog
dialog (_("Plugin Incompatibility"));
945 string text
= string_compose(_("You attempted to add the plugin \"%1\" at index %2.\n"),
946 p
.name(), streams
.index
);
948 bool has_midi
= streams
.count
.n_midi() > 0 || p
.get_info()->n_inputs
.n_midi() > 0;
949 bool has_audio
= streams
.count
.n_audio() > 0 || p
.get_info()->n_inputs
.n_audio() > 0;
951 text
+= _("\nThis plugin has:\n");
953 uint32_t const n
= p
.get_info()->n_inputs
.n_midi ();
954 text
+= string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n
), n
);
957 uint32_t const n
= p
.get_info()->n_inputs
.n_audio ();
958 text
+= string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n
), n
);
961 text
+= _("\nbut at the insertion point, there are:\n");
963 uint32_t const n
= streams
.count
.n_midi ();
964 text
+= string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n
), n
);
967 uint32_t const n
= streams
.count
.n_audio ();
968 text
+= string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n
), n
);
971 text
+= string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME
);
972 label
.set_text(text
);
974 dialog
.get_vbox()->pack_start (label
);
975 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
977 dialog
.set_name (X_("PluginIODialog"));
978 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
979 dialog
.set_modal (true);
986 ProcessorBox::choose_insert ()
988 boost::shared_ptr
<Processor
> processor (new PortInsert (*_session
, _route
->pannable(), _route
->mute_master()));
989 _route
->add_processor (processor
, _placement
);
992 /* Caller must not hold process lock */
994 ProcessorBox::choose_send ()
996 boost::shared_ptr
<Send
> send (new Send (*_session
, _route
->pannable(), _route
->mute_master()));
998 /* make an educated guess at the initial number of outputs for the send */
999 ChanCount outs
= (_session
->master_out())
1000 ? _session
->master_out()->n_outputs()
1001 : _route
->n_outputs();
1003 /* XXX need processor lock on route */
1005 Glib::Mutex::Lock
lm (AudioEngine::instance()->process_lock());
1006 send
->output()->ensure_io (outs
, false, this);
1007 } catch (AudioEngine::PortRegistrationFailure
& err
) {
1008 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
1012 /* let the user adjust the IO setup before creation.
1014 Note: this dialog is NOT modal - we just leave it to run and it will
1015 return when its Finished signal is emitted - typically when the window
1019 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
->output(), true);
1022 /* keep a reference to the send so it doesn't get deleted while
1023 the IOSelectorWindow is doing its stuff
1025 _processor_being_created
= send
;
1027 ios
->selector().Finished
.connect (sigc::bind (
1028 sigc::mem_fun(*this, &ProcessorBox::send_io_finished
),
1029 boost::weak_ptr
<Processor
>(send
), ios
));
1034 ProcessorBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1036 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1038 /* drop our temporary reference to the new send */
1039 _processor_being_created
.reset ();
1046 case IOSelector::Cancelled
:
1047 // processor will go away when all shared_ptrs to it vanish
1050 case IOSelector::Accepted
:
1051 _route
->add_processor (processor
, _placement
);
1052 if (Profile
->get_sae()) {
1053 processor
->activate ();
1058 delete_when_idle (ios
);
1062 ProcessorBox::return_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1064 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1066 /* drop our temporary reference to the new return */
1067 _processor_being_created
.reset ();
1074 case IOSelector::Cancelled
:
1075 // processor will go away when all shared_ptrs to it vanish
1078 case IOSelector::Accepted
:
1079 _route
->add_processor (processor
, _placement
);
1080 if (Profile
->get_sae()) {
1081 processor
->activate ();
1086 delete_when_idle (ios
);
1090 ProcessorBox::choose_aux (boost::weak_ptr
<Route
> wr
)
1096 boost::shared_ptr
<Route
> target
= wr
.lock();
1102 boost::shared_ptr
<RouteList
> rlist (new RouteList
);
1103 rlist
->push_back (_route
);
1105 _session
->add_internal_sends (target
, PreFader
, rlist
);
1109 ProcessorBox::route_processors_changed (RouteProcessorChange c
)
1111 if (c
.type
== RouteProcessorChange::MeterPointChange
&& c
.meter_visibly_changed
== false) {
1112 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1116 redisplay_processors ();
1120 ProcessorBox::redisplay_processors ()
1122 ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors
)
1124 if (no_processor_redisplay
) {
1128 processor_display
.clear ();
1130 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display
));
1132 for (list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin(); i
!= _processor_window_proxies
.end(); ++i
) {
1133 (*i
)->marked
= false;
1136 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list
));
1138 /* trim dead wood from the processor window proxy list */
1140 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin();
1141 while (i
!= _processor_window_proxies
.end()) {
1142 list
<ProcessorWindowProxy
*>::iterator j
= i
;
1145 if (!(*i
)->marked
) {
1146 ARDOUR_UI::instance()->remove_window_proxy (*i
);
1148 _processor_window_proxies
.erase (i
);
1154 setup_entry_positions ();
1157 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
1158 * not already have one.
1161 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr
<Processor
> w
)
1163 boost::shared_ptr
<Processor
> p
= w
.lock ();
1168 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
1169 while (i
!= _processor_window_proxies
.end()) {
1171 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
1174 /* this processor is already on the list; done */
1175 (*i
)->marked
= true;
1182 /* not on the list; add it */
1185 if (_parent_strip
) {
1186 if (_parent_strip
->mixer_owned()) {
1195 ProcessorWindowProxy
* wp
= new ProcessorWindowProxy (
1196 string_compose ("%1-%2-%3", loc
, _route
->id(), p
->id()),
1197 _session
->extra_xml (X_("UI")),
1203 /* if the processor already has an existing UI,
1204 note that so that we don't recreate it
1207 void* existing_ui
= p
->get_ui ();
1210 wp
->set (static_cast<Gtk::Window
*>(existing_ui
));
1213 _processor_window_proxies
.push_back (wp
);
1214 ARDOUR_UI::instance()->add_window_proxy (wp
);
1218 ProcessorBox::add_processor_to_display (boost::weak_ptr
<Processor
> p
)
1220 boost::shared_ptr
<Processor
> processor (p
.lock ());
1222 if (!processor
|| !processor
->display_to_user()) {
1226 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (processor
);
1227 boost::shared_ptr
<PluginInsert
> plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
);
1228 ProcessorEntry
* e
= 0;
1230 e
= new SendProcessorEntry (send
, _width
);
1231 } else if (plugin_insert
) {
1232 e
= new PluginInsertProcessorEntry (plugin_insert
, _width
);
1234 e
= new ProcessorEntry (processor
, _width
);
1237 e
->set_pixel_width (get_allocation().get_width());
1238 processor_display
.add_child (e
);
1243 ProcessorBox::build_processor_tooltip (EventBox
& box
, string start
)
1247 list
<ProcessorEntry
*> children
= processor_display
.children ();
1248 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1250 tip
+= (*i
)->processor()->name();
1253 ARDOUR_UI::instance()->set_tip (box
, tip
);
1257 ProcessorBox::reordered ()
1259 compute_processor_sort_keys ();
1260 setup_entry_positions ();
1264 ProcessorBox::setup_entry_positions ()
1266 list
<ProcessorEntry
*> children
= processor_display
.children ();
1267 bool pre_fader
= true;
1269 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1270 if (boost::dynamic_pointer_cast
<Amp
>((*i
)->processor())) {
1272 (*i
)->set_position (ProcessorEntry::Fader
);
1275 (*i
)->set_position (ProcessorEntry::PreFader
);
1277 (*i
)->set_position (ProcessorEntry::PostFader
);
1284 ProcessorBox::compute_processor_sort_keys ()
1286 list
<ProcessorEntry
*> children
= processor_display
.children ();
1287 Route::ProcessorList our_processors
;
1289 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1290 our_processors
.push_back ((*iter
)->processor ());
1293 if (_route
->reorder_processors (our_processors
)) {
1294 /* Reorder failed, so report this to the user. As far as I can see this must be done
1295 in an idle handler: it seems that the redisplay_processors() that happens below destroys
1296 widgets that were involved in the drag-and-drop on the processor list, which causes problems
1297 when the drag is torn down after this handler function is finished.
1299 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder
));
1304 ProcessorBox::report_failed_reorder ()
1306 /* reorder failed, so redisplay */
1308 redisplay_processors ();
1310 /* now tell them about the problem */
1312 ArdourDialog
dialog (_("Plugin Incompatibility"));
1315 label
.set_text (_("\
1316 You cannot reorder these plugins/sends/inserts\n\
1317 in that way because the inputs and\n\
1318 outputs will not work correctly."));
1320 dialog
.get_vbox()->set_border_width (12);
1321 dialog
.get_vbox()->pack_start (label
);
1322 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
1324 dialog
.set_name (X_("PluginIODialog"));
1325 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1326 dialog
.set_modal (true);
1333 ProcessorBox::rename_processors ()
1335 ProcSelection to_be_renamed
;
1337 get_selected_processors (to_be_renamed
);
1339 if (to_be_renamed
.empty()) {
1343 for (ProcSelection::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
1344 rename_processor (*i
);
1349 ProcessorBox::can_cut () const
1351 vector
<boost::shared_ptr
<Processor
> > sel
;
1353 get_selected_processors (sel
);
1355 /* cut_processors () does not cut inserts */
1357 for (vector
<boost::shared_ptr
<Processor
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
1359 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1360 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1361 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1370 ProcessorBox::cut_processors ()
1372 ProcSelection to_be_removed
;
1374 get_selected_processors (to_be_removed
);
1378 ProcessorBox::cut_processors (const ProcSelection
& to_be_removed
)
1380 if (to_be_removed
.empty()) {
1384 XMLNode
* node
= new XMLNode (X_("cut"));
1385 Route::ProcessorList to_cut
;
1387 no_processor_redisplay
= true;
1388 for (ProcSelection::const_iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
1389 // Cut only plugins, sends and returns
1390 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1391 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1392 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1394 Window
* w
= get_processor_ui (*i
);
1400 XMLNode
& child ((*i
)->get_state());
1401 node
->add_child_nocopy (child
);
1402 to_cut
.push_back (*i
);
1406 if (_route
->remove_processors (to_cut
) != 0) {
1408 no_processor_redisplay
= false;
1412 _rr_selection
.set (node
);
1414 no_processor_redisplay
= false;
1415 redisplay_processors ();
1419 ProcessorBox::copy_processors ()
1421 ProcSelection to_be_copied
;
1422 get_selected_processors (to_be_copied
);
1423 copy_processors (to_be_copied
);
1427 ProcessorBox::copy_processors (const ProcSelection
& to_be_copied
)
1429 if (to_be_copied
.empty()) {
1433 XMLNode
* node
= new XMLNode (X_("copy"));
1435 for (ProcSelection::const_iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
1436 // Copy only plugins, sends, returns
1437 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1438 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1439 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1440 node
->add_child_nocopy ((*i
)->get_state());
1444 _rr_selection
.set (node
);
1448 ProcessorBox::delete_processors ()
1450 ProcSelection to_be_deleted
;
1451 get_selected_processors (to_be_deleted
);
1452 delete_processors (to_be_deleted
);
1456 ProcessorBox::delete_processors (const ProcSelection
& targets
)
1458 if (targets
.empty()) {
1462 no_processor_redisplay
= true;
1464 for (ProcSelection::const_iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
1466 Window
* w
= get_processor_ui (*i
);
1472 _route
->remove_processor(*i
);
1475 no_processor_redisplay
= false;
1476 redisplay_processors ();
1480 ProcessorBox::delete_dragged_processors (const list
<boost::shared_ptr
<Processor
> >& procs
)
1482 list
<boost::shared_ptr
<Processor
> >::const_iterator x
;
1484 no_processor_redisplay
= true;
1485 for (x
= procs
.begin(); x
!= procs
.end(); ++x
) {
1487 Window
* w
= get_processor_ui (*x
);
1493 _route
->remove_processor(*x
);
1496 no_processor_redisplay
= false;
1497 redisplay_processors ();
1501 ProcessorBox::idle_delete_processor (boost::weak_ptr
<Processor
> weak_processor
)
1503 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1509 /* NOT copied to _mixer.selection() */
1511 no_processor_redisplay
= true;
1512 _route
->remove_processor (processor
);
1513 no_processor_redisplay
= false;
1514 redisplay_processors ();
1520 ProcessorBox::rename_processor (boost::shared_ptr
<Processor
> processor
)
1522 ArdourPrompter
name_prompter (true);
1524 name_prompter
.set_title (_("Rename Processor"));
1525 name_prompter
.set_prompt (_("New name:"));
1526 name_prompter
.set_initial_text (processor
->name());
1527 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
1528 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1529 name_prompter
.show_all ();
1531 switch (name_prompter
.run ()) {
1533 case Gtk::RESPONSE_ACCEPT
:
1534 name_prompter
.get_result (result
);
1535 if (result
.length()) {
1538 string test
= result
;
1540 while (tries
< 100) {
1541 if (_session
->io_name_is_legal (test
)) {
1547 test
= string_compose ("%1-%2", result
, tries
);
1551 processor
->set_name (result
);
1554 ARDOUR_UI::instance()->popup_error
1555 (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result
));
1565 ProcessorBox::paste_processors ()
1567 if (_rr_selection
.processors
.empty()) {
1571 paste_processor_state (_rr_selection
.processors
.get_node().children(), boost::shared_ptr
<Processor
>());
1575 ProcessorBox::paste_processors (boost::shared_ptr
<Processor
> before
)
1578 if (_rr_selection
.processors
.empty()) {
1582 paste_processor_state (_rr_selection
.processors
.get_node().children(), before
);
1586 ProcessorBox::paste_processor_state (const XMLNodeList
& nlist
, boost::shared_ptr
<Processor
> p
)
1588 XMLNodeConstIterator niter
;
1589 list
<boost::shared_ptr
<Processor
> > copies
;
1591 if (nlist
.empty()) {
1595 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1597 XMLProperty
const * type
= (*niter
)->property ("type");
1600 boost::shared_ptr
<Processor
> p
;
1602 if (type
->value() == "meter" ||
1603 type
->value() == "main-outs" ||
1604 type
->value() == "amp" ||
1605 type
->value() == "intsend" || type
->value() == "intreturn") {
1606 /* do not paste meter, main outs, amp or internal send/returns */
1609 } else if (type
->value() == "send") {
1611 XMLNode
n (**niter
);
1612 Send::make_unique (n
, *_session
);
1613 Send
* s
= new Send (*_session
, _route
->pannable(), _route
->mute_master());
1614 if (s
->set_state (n
, Stateful::loading_state_version
)) {
1622 } else if (type
->value() == "return") {
1624 XMLNode
n (**niter
);
1625 Return::make_unique (n
, *_session
);
1626 Return
* r
= new Return (*_session
);
1628 if (r
->set_state (n
, Stateful::loading_state_version
)) {
1635 } else if (type
->value() == "port") {
1637 XMLNode
n (**niter
);
1638 p
.reset (new PortInsert (*_session
, _route
->pannable (), _route
->mute_master ()));
1639 if (p
->set_state (n
, Stateful::loading_state_version
)) {
1644 /* XXX its a bit limiting to assume that everything else
1648 p
.reset (new PluginInsert (*_session
));
1649 p
->set_state (**niter
, Stateful::current_state_version
);
1652 copies
.push_back (p
);
1656 cerr
<< "plugin insert constructor failed\n";
1660 if (copies
.empty()) {
1664 if (_route
->add_processors (copies
, p
)) {
1667 "Copying the set of processors on the clipboard failed,\n\
1668 probably because the I/O configuration of the plugins\n\
1669 could not match the configuration of this track.");
1670 MessageDialog
am (msg
);
1676 ProcessorBox::activate_processor (boost::shared_ptr
<Processor
> r
)
1682 ProcessorBox::deactivate_processor (boost::shared_ptr
<Processor
> r
)
1688 ProcessorBox::get_selected_processors (ProcSelection
& processors
) const
1690 const list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1691 for (list
<ProcessorEntry
*>::const_iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1692 processors
.push_back ((*i
)->processor ());
1697 ProcessorBox::for_selected_processors (void (ProcessorBox::*method
)(boost::shared_ptr
<Processor
>))
1699 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1700 for (list
<ProcessorEntry
*>::iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1701 (this->*method
) ((*i
)->processor ());
1706 ProcessorBox::all_processors_active (bool state
)
1708 _route
->all_processors_active (_placement
, state
);
1712 ProcessorBox::ab_plugins ()
1714 _route
->ab_plugins (ab_direction
);
1715 ab_direction
= !ab_direction
;
1720 ProcessorBox::clear_processors ()
1723 vector
<string
> choices
;
1725 prompt
= string_compose (_("Do you really want to remove all processors from %1?\n"
1726 "(this cannot be undone)"), _route
->name());
1728 choices
.push_back (_("Cancel"));
1729 choices
.push_back (_("Yes, remove them all"));
1731 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1733 if (prompter
.run () == 1) {
1734 _route
->clear_processors (PreFader
);
1735 _route
->clear_processors (PostFader
);
1740 ProcessorBox::clear_processors (Placement p
)
1743 vector
<string
> choices
;
1745 if (p
== PreFader
) {
1746 prompt
= string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1747 "(this cannot be undone)"), _route
->name());
1749 prompt
= string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1750 "(this cannot be undone)"), _route
->name());
1753 choices
.push_back (_("Cancel"));
1754 choices
.push_back (_("Yes, remove them all"));
1756 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1758 if (prompter
.run () == 1) {
1759 _route
->clear_processors (p
);
1764 ProcessorBox::processor_can_be_edited (boost::shared_ptr
<Processor
> processor
)
1766 boost::shared_ptr
<AudioTrack
> at
= boost::dynamic_pointer_cast
<AudioTrack
> (_route
);
1767 if (at
&& at
->freeze_state() == AudioTrack::Frozen
) {
1772 boost::dynamic_pointer_cast
<Send
> (processor
) ||
1773 boost::dynamic_pointer_cast
<Return
> (processor
) ||
1774 boost::dynamic_pointer_cast
<PluginInsert
> (processor
) ||
1775 boost::dynamic_pointer_cast
<PortInsert
> (processor
)
1784 ProcessorBox::one_processor_can_be_edited ()
1786 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1787 list
<ProcessorEntry
*>::iterator i
= selection
.begin();
1788 while (i
!= selection
.end() && processor_can_be_edited ((*i
)->processor()) == false) {
1792 return (i
!= selection
.end());
1796 ProcessorBox::toggle_edit_processor (boost::shared_ptr
<Processor
> processor
)
1798 boost::shared_ptr
<Send
> send
;
1799 boost::shared_ptr
<InternalSend
> internal_send
;
1800 boost::shared_ptr
<Return
> retrn
;
1801 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1802 boost::shared_ptr
<PortInsert
> port_insert
;
1805 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1807 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1812 if (boost::dynamic_pointer_cast
<Amp
> (processor
)) {
1814 _parent_strip
->revert_to_default_display ();
1816 } else if ((internal_send
= boost::dynamic_pointer_cast
<InternalSend
> (processor
)) != 0) {
1818 if (!_session
->engine().connected()) {
1822 if (_parent_strip
) {
1823 if (boost::dynamic_pointer_cast
<Send
> (_parent_strip
->current_delivery()) == internal_send
) {
1824 _parent_strip
->revert_to_default_display ();
1826 _parent_strip
->show_send (internal_send
);
1830 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
1832 if (!_session
->engine().connected()) {
1836 SendUIWindow
* w
= new SendUIWindow (send
, _session
);
1839 } else if ((retrn
= boost::dynamic_pointer_cast
<Return
> (processor
)) != 0) {
1841 if (boost::dynamic_pointer_cast
<InternalReturn
> (retrn
)) {
1842 /* no GUI for these */
1846 if (!_session
->engine().connected()) {
1850 boost::shared_ptr
<Return
> retrn
= boost::dynamic_pointer_cast
<Return
> (processor
);
1852 ReturnUIWindow
*return_ui
;
1853 Window
* w
= get_processor_ui (retrn
);
1857 return_ui
= new ReturnUIWindow (retrn
, _session
);
1858 return_ui
->set_title (retrn
->name ());
1859 set_processor_ui (send
, return_ui
);
1862 return_ui
= dynamic_cast<ReturnUIWindow
*> (w
);
1867 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
1869 PluginUIWindow
*plugin_ui
;
1871 /* these are both allowed to be null */
1873 Container
* toplevel
= get_toplevel();
1874 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1876 Window
* w
= get_processor_ui (plugin_insert
);
1880 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1881 plugin_ui
->set_title (generate_processor_title (plugin_insert
));
1882 set_processor_ui (plugin_insert
, plugin_ui
);
1885 plugin_ui
= dynamic_cast<PluginUIWindow
*> (w
);
1886 plugin_ui
->set_parent (win
);
1891 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (processor
)) != 0) {
1893 if (!_session
->engine().connected()) {
1894 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1899 PortInsertWindow
*io_selector
;
1901 Window
* w
= get_processor_ui (port_insert
);
1904 io_selector
= new PortInsertWindow (_session
, port_insert
);
1905 set_processor_ui (port_insert
, io_selector
);
1908 io_selector
= dynamic_cast<PortInsertWindow
*> (w
);
1911 gidget
= io_selector
;
1915 if (gidget
->is_visible()) {
1918 gidget
->show_all ();
1925 ProcessorBox::register_actions ()
1927 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("ProcessorMenu"));
1928 Glib::RefPtr
<Action
> act
;
1931 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"),
1932 sigc::ptr_fun (ProcessorBox::rb_choose_plugin
));
1934 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"),
1935 sigc::ptr_fun (ProcessorBox::rb_choose_insert
));
1936 ActionManager::jack_sensitive_actions
.push_back (act
);
1937 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."),
1938 sigc::ptr_fun (ProcessorBox::rb_choose_send
));
1939 ActionManager::jack_sensitive_actions
.push_back (act
);
1941 ActionManager::register_action (popup_act_grp
, X_("newaux"), _("New Aux Send ..."));
1943 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear (all)"),
1944 sigc::ptr_fun (ProcessorBox::rb_clear
));
1945 ActionManager::register_action (popup_act_grp
, X_("clear_pre"), _("Clear (pre-fader)"),
1946 sigc::ptr_fun (ProcessorBox::rb_clear_pre
));
1947 ActionManager::register_action (popup_act_grp
, X_("clear_post"), _("Clear (post-fader)"),
1948 sigc::ptr_fun (ProcessorBox::rb_clear_post
));
1950 /* standard editing stuff */
1951 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"),
1952 sigc::ptr_fun (ProcessorBox::rb_cut
));
1953 ActionManager::plugin_selection_sensitive_actions
.push_back(cut_action
);
1954 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"),
1955 sigc::ptr_fun (ProcessorBox::rb_copy
));
1956 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1958 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"),
1959 sigc::ptr_fun (ProcessorBox::rb_delete
));
1960 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1962 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"),
1963 sigc::ptr_fun (ProcessorBox::rb_paste
));
1964 rename_action
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"),
1965 sigc::ptr_fun (ProcessorBox::rb_rename
));
1966 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"),
1967 sigc::ptr_fun (ProcessorBox::rb_select_all
));
1968 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"),
1969 sigc::ptr_fun (ProcessorBox::rb_deselect_all
));
1971 /* activation etc. */
1973 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"),
1974 sigc::ptr_fun (ProcessorBox::rb_activate_all
));
1975 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"),
1976 sigc::ptr_fun (ProcessorBox::rb_deactivate_all
));
1977 ActionManager::register_action (popup_act_grp
, X_("ab_plugins"), _("A/B Plugins"),
1978 sigc::ptr_fun (ProcessorBox::rb_ab_plugins
));
1981 edit_action
= ActionManager::register_action (popup_act_grp
, X_("edit"), _("Edit..."),
1982 sigc::ptr_fun (ProcessorBox::rb_edit
));
1984 ActionManager::add_action_group (popup_act_grp
);
1988 ProcessorBox::rb_ab_plugins ()
1990 if (_current_processor_box
== 0) {
1994 _current_processor_box
->ab_plugins ();
1998 ProcessorBox::rb_choose_plugin ()
2000 if (_current_processor_box
== 0) {
2003 _current_processor_box
->choose_plugin ();
2007 ProcessorBox::rb_choose_insert ()
2009 if (_current_processor_box
== 0) {
2012 _current_processor_box
->choose_insert ();
2016 ProcessorBox::rb_choose_send ()
2018 if (_current_processor_box
== 0) {
2021 _current_processor_box
->choose_send ();
2025 ProcessorBox::rb_choose_aux (boost::weak_ptr
<Route
> wr
)
2027 if (_current_processor_box
== 0) {
2031 _current_processor_box
->choose_aux (wr
);
2035 ProcessorBox::rb_clear ()
2037 if (_current_processor_box
== 0) {
2041 _current_processor_box
->clear_processors ();
2046 ProcessorBox::rb_clear_pre ()
2048 if (_current_processor_box
== 0) {
2052 _current_processor_box
->clear_processors (PreFader
);
2057 ProcessorBox::rb_clear_post ()
2059 if (_current_processor_box
== 0) {
2063 _current_processor_box
->clear_processors (PostFader
);
2067 ProcessorBox::rb_cut ()
2069 if (_current_processor_box
== 0) {
2073 _current_processor_box
->cut_processors ();
2077 ProcessorBox::rb_delete ()
2079 if (_current_processor_box
== 0) {
2083 _current_processor_box
->delete_processors ();
2087 ProcessorBox::rb_copy ()
2089 if (_current_processor_box
== 0) {
2092 _current_processor_box
->copy_processors ();
2096 ProcessorBox::rb_paste ()
2098 if (_current_processor_box
== 0) {
2102 _current_processor_box
->paste_processors ();
2106 ProcessorBox::rb_rename ()
2108 if (_current_processor_box
== 0) {
2111 _current_processor_box
->rename_processors ();
2115 ProcessorBox::rb_select_all ()
2117 if (_current_processor_box
== 0) {
2121 _current_processor_box
->select_all_processors ();
2125 ProcessorBox::rb_deselect_all ()
2127 if (_current_processor_box
== 0) {
2131 _current_processor_box
->deselect_all_processors ();
2135 ProcessorBox::rb_activate_all ()
2137 if (_current_processor_box
== 0) {
2141 _current_processor_box
->all_processors_active (true);
2145 ProcessorBox::rb_deactivate_all ()
2147 if (_current_processor_box
== 0) {
2150 _current_processor_box
->all_processors_active (false);
2154 ProcessorBox::rb_edit ()
2156 if (_current_processor_box
== 0) {
2160 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_edit_processor
);
2164 ProcessorBox::route_property_changed (const PropertyChange
& what_changed
)
2166 if (!what_changed
.contains (ARDOUR::Properties::name
)) {
2170 ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed
, what_changed
);
2172 boost::shared_ptr
<Processor
> processor
;
2173 boost::shared_ptr
<PluginInsert
> plugin_insert
;
2174 boost::shared_ptr
<Send
> send
;
2176 list
<ProcessorEntry
*> children
= processor_display
.children();
2178 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
2180 processor
= (*iter
)->processor ();
2182 Window
* w
= get_processor_ui (processor
);
2188 /* rename editor windows for sends and plugins */
2190 if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
2191 w
->set_title (send
->name ());
2192 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
2193 w
->set_title (generate_processor_title (plugin_insert
));
2199 ProcessorBox::generate_processor_title (boost::shared_ptr
<PluginInsert
> pi
)
2201 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
2202 string::size_type email_pos
;
2204 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
2205 maker
= maker
.substr (0, email_pos
- 1);
2208 if (maker
.length() > 32) {
2209 maker
= maker
.substr (0, 32);
2213 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);
2217 ProcessorBox::on_size_allocate (Allocation
& a
)
2219 HBox::on_size_allocate (a
);
2221 list
<ProcessorEntry
*> children
= processor_display
.children ();
2222 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
2223 (*i
)->set_pixel_width (a
.get_width ());
2227 /** @param p Processor.
2228 * @return the UI window for \a p.
2231 ProcessorBox::get_processor_ui (boost::shared_ptr
<Processor
> p
) const
2233 list
<ProcessorWindowProxy
*>::const_iterator i
= _processor_window_proxies
.begin ();
2234 while (i
!= _processor_window_proxies
.end()) {
2235 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2237 return (*i
)->get ();
2243 /* we shouldn't get here, because the ProcessorUIList should always contain
2244 an entry for each processor.
2250 /** Make a note of the UI window that a processor is using.
2251 * @param p Processor.
2252 * @param w UI window.
2255 ProcessorBox::set_processor_ui (boost::shared_ptr
<Processor
> p
, Gtk::Window
* w
)
2257 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
2261 while (i
!= _processor_window_proxies
.end()) {
2262 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2271 /* we shouldn't get here, because the ProcessorUIList should always contain
2272 an entry for each processor.
2278 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr
<Delivery
> w
)
2280 boost::shared_ptr
<Delivery
> d
= w
.lock ();
2285 list
<ProcessorEntry
*> children
= processor_display
.children ();
2286 list
<ProcessorEntry
*>::const_iterator i
= children
.begin();
2287 while (i
!= children
.end() && (*i
)->processor() != d
) {
2291 if (i
== children
.end()) {
2292 processor_display
.set_active (0);
2294 processor_display
.set_active (*i
);
2299 ProcessorBox::hide_things ()
2301 list
<ProcessorEntry
*> c
= processor_display
.children ();
2302 for (list
<ProcessorEntry
*>::iterator i
= c
.begin(); i
!= c
.end(); ++i
) {
2303 (*i
)->hide_things ();
2307 ProcessorWindowProxy::ProcessorWindowProxy (
2308 string
const & name
,
2309 XMLNode
const * node
,
2311 boost::weak_ptr
<Processor
> processor
2313 : WindowProxy
<Gtk::Window
> (name
, node
)
2315 , _processor_box (box
)
2316 , _processor (processor
)
2323 ProcessorWindowProxy::show ()
2325 boost::shared_ptr
<Processor
> p
= _processor
.lock ();
2330 _processor_box
->toggle_edit_processor (p
);