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 RefPtr
<Action
> ProcessorBox::controls_action
;
96 Glib::RefPtr
<Gdk::Pixbuf
> SendProcessorEntry::_slider
;
98 ProcessorEntry::ProcessorEntry (boost::shared_ptr
<Processor
> p
, Width w
)
99 : _position (PreFader
)
102 , _visual_state (Gtk::STATE_NORMAL
)
104 _hbox
.pack_start (_active
, false, false);
105 _event_box
.add (_name
);
106 _hbox
.pack_start (_event_box
, true, true);
107 _vbox
.pack_start (_hbox
);
110 /* without this, the border is mis-drawn on some systems */
111 _vbox
.set_border_width (1);
113 _name
.set_alignment (0, 0.5);
114 _name
.set_text (name ());
115 _name
.set_padding (2, 2);
117 if (boost::dynamic_pointer_cast
<Amp
> (p
)) {
118 /* Fader processor gets a special look */
119 _event_box
.set_name ("ProcessorFader");
120 _frame
.set_name ("ProcessorFaderFrame");
121 _name
.set_padding (2, 4);
124 _active
.set_active (_processor
->active ());
125 _active
.signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::active_toggled
));
134 _processor
->ActiveChanged
.connect (active_connection
, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed
, this), gui_context());
135 _processor
->PropertyChanged
.connect (name_connection
, invalidator (*this), ui_bind (&ProcessorEntry::processor_property_changed
, this, _1
), gui_context());
139 ProcessorEntry::action_widget ()
145 ProcessorEntry::widget ()
151 ProcessorEntry::drag_text () const
157 ProcessorEntry::set_visual_state (Gtk::StateType t
)
164 ProcessorEntry::set_position (Position p
)
171 ProcessorEntry::setup_visuals ()
175 _event_box
.set_name ("ProcessorPreFader");
176 if (_visual_state
== Gtk::STATE_NORMAL
) {
177 _frame
.set_name ("ProcessorPreFaderFrame");
182 _event_box
.set_name ("ProcessorFader");
183 if (_visual_state
== Gtk::STATE_NORMAL
) {
184 _frame
.set_name ("ProcessorFaderFrame");
189 _event_box
.set_name ("ProcessorPostFader");
190 if (_visual_state
== Gtk::STATE_NORMAL
) {
191 _frame
.set_name ("ProcessorPostFaderFrame");
196 switch (_visual_state
) {
197 case Gtk::STATE_NORMAL
:
198 /* _frame has been set up above */
199 _event_box
.set_state (Gtk::STATE_NORMAL
);
201 case Gtk::STATE_SELECTED
:
202 _frame
.set_name ("ProcessorFrameSelected");
203 /* don't change the background of the box when it is selected */
204 _event_box
.set_state (Gtk::STATE_NORMAL
);
206 case Gtk::STATE_ACTIVE
:
207 _frame
.set_name ("ProcessorFrameActiveSend");
208 _event_box
.set_state (Gtk::STATE_ACTIVE
);
216 boost::shared_ptr
<Processor
>
217 ProcessorEntry::processor () const
223 ProcessorEntry::set_enum_width (Width w
)
229 ProcessorEntry::active_toggled ()
231 if (_active
.get_active ()) {
232 if (!_processor
->active ()) {
233 _processor
->activate ();
236 if (_processor
->active ()) {
237 _processor
->deactivate ();
243 ProcessorEntry::processor_active_changed ()
245 if (_active
.get_active () != _processor
->active ()) {
246 _active
.set_active (_processor
->active ());
251 ProcessorEntry::processor_property_changed (const PropertyChange
& what_changed
)
253 if (what_changed
.contains (ARDOUR::Properties::name
)) {
254 _name
.set_text (name ());
259 ProcessorEntry::name () const
261 boost::shared_ptr
<Send
> send
;
264 if ((send
= boost::dynamic_pointer_cast
<Send
> (_processor
)) != 0 &&
265 !boost::dynamic_pointer_cast
<InternalSend
>(_processor
)) {
269 /* grab the send name out of its overall name */
271 string::size_type lbracket
, rbracket
;
272 lbracket
= send
->name().find ('[');
273 rbracket
= send
->name().find (']');
277 name_display
+= send
->name().substr (lbracket
+1, lbracket
-rbracket
-1);
280 name_display
+= PBD::short_version (send
->name().substr (lbracket
+1, lbracket
-rbracket
-1), 4);
288 name_display
+= _processor
->display_name();
291 name_display
+= PBD::short_version (_processor
->display_name(), 5);
300 SendProcessorEntry::SendProcessorEntry (boost::shared_ptr
<Send
> s
, Width w
)
301 : ProcessorEntry (s
, w
),
303 _adjustment (gain_to_slider_position_with_max (1.0, Config
->get_max_gain()), 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 float const value
= gain_to_slider_position_with_max (_send
->amp()->gain (), Config
->get_max_gain());
330 if (_adjustment
.get_value() != value
) {
331 _ignore_gain_change
= true;
332 _adjustment
.set_value (value
);
333 _ignore_gain_change
= false;
337 s
.setf (ios::fixed
, ios::floatfield
);
338 s
<< accurate_coefficient_to_dB (_send
->amp()->gain ()) << _("dB");
339 _fader
.set_tooltip_text (s
.str ());
344 SendProcessorEntry::gain_adjusted ()
346 if (_ignore_gain_change
) {
350 _send
->amp()->set_gain (slider_position_to_gain_with_max (_adjustment
.get_value(), Config
->get_max_gain()), this);
354 SendProcessorEntry::set_pixel_width (int p
)
356 _fader
.set_fader_length (p
);
359 PluginInsertProcessorEntry::PluginInsertProcessorEntry (boost::shared_ptr
<ARDOUR::PluginInsert
> p
, Width w
)
360 : ProcessorEntry (p
, w
)
363 p
->SplittingChanged
.connect (
364 _splitting_connection
, invalidator (*this), ui_bind (&PluginInsertProcessorEntry::plugin_insert_splitting_changed
, this), gui_context()
367 _splitting_icon
.set_size_request (-1, 12);
369 _vbox
.pack_start (_splitting_icon
);
370 _vbox
.reorder_child (_splitting_icon
, 0);
372 plugin_insert_splitting_changed ();
376 PluginInsertProcessorEntry::plugin_insert_splitting_changed ()
378 if (_plugin_insert
->splitting ()) {
379 _splitting_icon
.show ();
381 _splitting_icon
.hide ();
386 PluginInsertProcessorEntry::hide_things ()
388 plugin_insert_splitting_changed ();
392 PluginInsertProcessorEntry::setup_visuals ()
396 _splitting_icon
.set_name ("ProcessorPreFader");
400 _splitting_icon
.set_name ("ProcessorFader");
404 _splitting_icon
.set_name ("ProcessorPostFader");
408 ProcessorEntry::setup_visuals ();
412 PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose
* ev
)
414 cairo_t
* cr
= gdk_cairo_create (get_window()->gobj());
416 cairo_set_line_width (cr
, 1);
418 double const width
= ev
->area
.width
;
419 double const height
= ev
->area
.height
;
421 Gdk::Color
const bg
= get_style()->get_bg (STATE_NORMAL
);
422 cairo_set_source_rgb (cr
, bg
.get_red_p (), bg
.get_green_p (), bg
.get_blue_p ());
424 cairo_rectangle (cr
, 0, 0, width
, height
);
427 Gdk::Color
const fg
= get_style()->get_fg (STATE_NORMAL
);
428 cairo_set_source_rgb (cr
, fg
.get_red_p (), fg
.get_green_p (), fg
.get_blue_p ());
430 cairo_move_to (cr
, width
* 0.3, height
);
431 cairo_line_to (cr
, width
* 0.3, height
* 0.5);
432 cairo_line_to (cr
, width
* 0.7, height
* 0.5);
433 cairo_line_to (cr
, width
* 0.7, height
);
434 cairo_move_to (cr
, width
* 0.5, height
* 0.5);
435 cairo_line_to (cr
, width
* 0.5, 0);
441 ProcessorBox::ProcessorBox (ARDOUR::Session
* sess
, boost::function
<PluginSelector
*()> get_plugin_selector
,
442 RouteRedirectSelection
& rsel
, MixerStrip
* parent
, bool owner_is_mixer
)
443 : _parent_strip (parent
)
444 , _owner_is_mixer (owner_is_mixer
)
445 , ab_direction (true)
446 , _get_plugin_selector (get_plugin_selector
)
447 , _placement(PreFader
)
448 , _rr_selection(rsel
)
454 send_action_menu
= 0;
455 no_processor_redisplay
= false;
457 processor_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
458 processor_scroller
.add (processor_display
);
459 pack_start (processor_scroller
, true, true);
461 processor_display
.set_flags (CAN_FOCUS
);
462 processor_display
.set_name ("ProcessorList");
463 processor_display
.set_size_request (48, -1);
464 processor_display
.set_data ("processorbox", this);
465 processor_display
.set_spacing (2);
467 processor_display
.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify
), false);
468 processor_display
.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify
), false);
470 processor_display
.signal_key_press_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_press_event
));
471 processor_display
.signal_key_release_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_release_event
));
473 processor_display
.ButtonPress
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event
));
474 processor_display
.ButtonRelease
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event
));
476 processor_display
.Reordered
.connect (sigc::mem_fun (*this, &ProcessorBox::reordered
));
477 processor_display
.DropFromAnotherBox
.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop
));
478 processor_display
.SelectionChanged
.connect (sigc::mem_fun (*this, &ProcessorBox::selection_changed
));
480 processor_scroller
.show ();
481 processor_display
.show ();
484 parent
->DeliveryChanged
.connect (
485 _mixer_strip_connections
, invalidator (*this), ui_bind (&ProcessorBox::mixer_strip_delivery_changed
, this, _1
), gui_context ()
490 ProcessorBox::~ProcessorBox ()
495 ProcessorBox::set_route (boost::shared_ptr
<Route
> r
)
501 _route_connections
.drop_connections();
503 /* new route: any existing block on processor redisplay must be meaningless */
504 no_processor_redisplay
= false;
507 _route
->processors_changed
.connect (
508 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_processors_changed
, this, _1
), gui_context()
511 _route
->DropReferences
.connect (
512 _route_connections
, invalidator (*this), boost::bind (&ProcessorBox::route_going_away
, this), gui_context()
515 _route
->PropertyChanged
.connect (
516 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_property_changed
, this, _1
), gui_context()
519 redisplay_processors ();
523 ProcessorBox::route_going_away ()
525 /* don't keep updating display as processors are deleted */
526 no_processor_redisplay
= true;
531 ProcessorBox::object_drop(DnDVBox
<ProcessorEntry
>* source
, ProcessorEntry
* position
, Glib::RefPtr
<Gdk::DragContext
> const & context
)
533 boost::shared_ptr
<Processor
> p
;
535 p
= position
->processor ();
538 list
<ProcessorEntry
*> children
= source
->selection ();
539 list
<boost::shared_ptr
<Processor
> > procs
;
540 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
541 procs
.push_back ((*i
)->processor ());
544 for (list
<boost::shared_ptr
<Processor
> >::const_iterator i
= procs
.begin(); i
!= procs
.end(); ++i
) {
545 XMLNode
& state
= (*i
)->get_state ();
547 nlist
.push_back (&state
);
548 paste_processor_state (nlist
, p
);
552 /* since the dndvbox doesn't take care of this properly, we have to delete the originals
556 if ((context
->get_suggested_action() == Gdk::ACTION_MOVE
) && source
) {
557 ProcessorBox
* other
= reinterpret_cast<ProcessorBox
*> (source
->get_data ("processorbox"));
559 cerr
<< "source was another processor box, delete the selected items\n";
560 other
->delete_dragged_processors (procs
);
566 ProcessorBox::update()
568 redisplay_processors ();
572 ProcessorBox::set_width (Width w
)
580 list
<ProcessorEntry
*> children
= processor_display
.children ();
581 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
582 (*i
)->set_enum_width (w
);
585 redisplay_processors ();
589 ProcessorBox::build_send_action_menu ()
591 using namespace Menu_Helpers
;
593 send_action_menu
= new Menu
;
594 send_action_menu
->set_name ("ArdourContextMenu");
595 MenuList
& items
= send_action_menu
->items();
597 items
.push_back (MenuElem (_("New send"), sigc::mem_fun(*this, &ProcessorBox::new_send
)));
598 items
.push_back (MenuElem (_("Show send controls"), sigc::mem_fun(*this, &ProcessorBox::show_send_controls
)));
602 ProcessorBox::build_possible_aux_menu ()
604 boost::shared_ptr
<RouteList
> rl
= _session
->get_routes_with_internal_returns();
610 using namespace Menu_Helpers
;
611 Menu
* menu
= manage (new Menu
);
612 MenuList
& items
= menu
->items();
614 for (RouteList::iterator r
= rl
->begin(); r
!= rl
->end(); ++r
) {
615 if (!_route
->internal_send_for (*r
) && *r
!= _route
) {
616 items
.push_back (MenuElem ((*r
)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux
), boost::weak_ptr
<Route
>(*r
))));
624 ProcessorBox::show_send_controls ()
629 ProcessorBox::new_send ()
634 ProcessorBox::show_processor_menu (gint arg
)
636 if (processor_menu
== 0) {
637 processor_menu
= build_processor_menu ();
640 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
642 if (plugin_menu_item
) {
643 plugin_menu_item
->set_submenu (*_get_plugin_selector()->plugin_menu());
646 Gtk::MenuItem
* aux_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/ProcessorMenu/newaux"));
649 Menu
* m
= build_possible_aux_menu();
650 if (m
&& !m
->items().empty()) {
651 aux_menu_item
->set_submenu (*m
);
652 aux_menu_item
->set_sensitive (true);
654 /* stupid gtkmm: we need to pass a null reference here */
655 gtk_menu_item_set_submenu (aux_menu_item
->gobj(), 0);
656 aux_menu_item
->set_sensitive (false);
660 cut_action
->set_sensitive (can_cut());
661 paste_action
->set_sensitive (!_rr_selection
.processors
.empty());
663 processor_menu
->popup (1, arg
);
667 ProcessorBox::enter_notify (GdkEventCrossing
*)
669 _current_processor_box
= this;
670 Keyboard::magic_widget_grab_focus ();
671 processor_display
.grab_focus ();
677 ProcessorBox::leave_notify (GdkEventCrossing
* ev
)
679 switch (ev
->detail
) {
680 case GDK_NOTIFY_INFERIOR
:
683 Keyboard::magic_widget_drop_focus ();
690 ProcessorBox::processor_key_press_event (GdkEventKey
*)
692 /* do real stuff on key release */
697 ProcessorBox::processor_key_release_event (GdkEventKey
*ev
)
700 ProcSelection targets
;
702 get_selected_processors (targets
);
704 if (targets
.empty()) {
707 processor_display
.get_pointer (x
, y
);
709 pair
<ProcessorEntry
*, double> const pointer
= processor_display
.get_child_at_position (y
);
712 targets
.push_back (pointer
.first
->processor ());
717 switch (ev
->keyval
) {
719 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
720 processor_display
.select_all ();
726 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
727 copy_processors (targets
);
733 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
734 cut_processors (targets
);
740 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
741 if (targets
.empty()) {
744 paste_processors (targets
.front());
758 delete_processors (targets
);
763 for (ProcSelection::iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
764 if ((*i
)->active()) {
786 ProcessorBox::processor_button_press_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
788 boost::shared_ptr
<Processor
> processor
;
790 processor
= child
->processor ();
794 bool selected
= processor_display
.selected (child
);
796 if (processor
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
798 if (_session
->engine().connected()) {
799 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
800 toggle_edit_processor (processor
);
804 } else if (processor
&& ev
->button
== 1 && selected
) {
806 // this is purely informational but necessary for route params UI
807 ProcessorSelected (processor
); // emit
809 } else if (!processor
&& ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
) {
812 _get_plugin_selector()->show_manager ();
819 ProcessorBox::processor_button_release_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
821 boost::shared_ptr
<Processor
> processor
;
823 processor
= child
->processor ();
828 if (processor
&& Keyboard::is_delete_event (ev
)) {
830 Glib::signal_idle().connect (sigc::bind (
831 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor
),
832 boost::weak_ptr
<Processor
>(processor
)));
835 } else if (Keyboard::is_context_menu_event (ev
)) {
837 /* figure out if we are above or below the fader/amp processor,
838 and set the next insert position appropriately.
842 if (_route
->processor_is_prefader (processor
)) {
843 _placement
= PreFader
;
845 _placement
= PostFader
;
848 _placement
= PostFader
;
851 show_processor_menu (ev
->time
);
854 } else if (processor
&& Keyboard::is_button2_event (ev
)
856 && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))
860 /* button2-click with no/appropriate modifiers */
862 if (processor
->active()) {
863 processor
->deactivate ();
865 processor
->activate ();
875 ProcessorBox::build_processor_menu ()
877 processor_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/ProcessorMenu") );
878 processor_menu
->set_name ("ArdourContextMenu");
879 return processor_menu
;
883 ProcessorBox::selection_changed ()
885 const bool sensitive
= !processor_display
.selection().empty();
886 ActionManager::set_sensitive(ActionManager::plugin_selection_sensitive_actions
,
888 edit_action
->set_sensitive(one_processor_can_be_edited());
890 const bool single_selection
= (processor_display
.selection().size() == 1);
892 boost::shared_ptr
<PluginInsert
> pi
;
893 if (single_selection
) {
894 pi
= boost::dynamic_pointer_cast
<PluginInsert
>(
895 processor_display
.selection().front()->processor());
898 /* enable gui for plugin inserts with editors */
899 controls_action
->set_sensitive(pi
&& pi
->plugin()->has_editor());
901 /* disallow rename for multiple selections and for plugin inserts */
902 rename_action
->set_sensitive(single_selection
&& pi
);
906 ProcessorBox::select_all_processors ()
908 processor_display
.select_all ();
912 ProcessorBox::deselect_all_processors ()
914 processor_display
.select_none ();
918 ProcessorBox::choose_plugin ()
920 _get_plugin_selector()->set_interested_object (*this);
923 /** @return true if an error occurred, otherwise false */
925 ProcessorBox::use_plugins (const SelectedPlugins
& plugins
)
927 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
929 boost::shared_ptr
<Processor
> processor (new PluginInsert (*_session
, *p
));
931 Route::ProcessorStreams err_streams
;
933 if (_route
->add_processor (processor
, _placement
, &err_streams
, Config
->get_new_plugins_active ())) {
934 weird_plugin_dialog (**p
, err_streams
);
936 // XXX SHAREDPTR delete plugin here .. do we even need to care?
939 if (Profile
->get_sae()) {
940 processor
->activate ();
949 ProcessorBox::weird_plugin_dialog (Plugin
& p
, Route::ProcessorStreams streams
)
951 ArdourDialog
dialog (_("Plugin Incompatibility"));
954 string text
= string_compose(_("You attempted to add the plugin \"%1\" in slot %2.\n"),
955 p
.name(), streams
.index
);
957 bool has_midi
= streams
.count
.n_midi() > 0 || p
.get_info()->n_inputs
.n_midi() > 0;
958 bool has_audio
= streams
.count
.n_audio() > 0 || p
.get_info()->n_inputs
.n_audio() > 0;
960 text
+= _("\nThis plugin has:\n");
962 uint32_t const n
= p
.get_info()->n_inputs
.n_midi ();
963 text
+= string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n
), n
);
966 uint32_t const n
= p
.get_info()->n_inputs
.n_audio ();
967 text
+= string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n
), n
);
970 text
+= _("\nbut at the insertion point, there are:\n");
972 uint32_t const n
= streams
.count
.n_midi ();
973 text
+= string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n
), n
);
976 uint32_t const n
= streams
.count
.n_audio ();
977 text
+= string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n
), n
);
980 text
+= string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME
);
981 label
.set_text(text
);
983 dialog
.get_vbox()->pack_start (label
);
984 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
986 dialog
.set_name (X_("PluginIODialog"));
987 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
988 dialog
.set_modal (true);
995 ProcessorBox::choose_insert ()
997 boost::shared_ptr
<Processor
> processor (new PortInsert (*_session
, _route
->pannable(), _route
->mute_master()));
998 _route
->add_processor (processor
, _placement
);
1001 /* Caller must not hold process lock */
1003 ProcessorBox::choose_send ()
1005 boost::shared_ptr
<Send
> send (new Send (*_session
, _route
->pannable(), _route
->mute_master()));
1007 /* make an educated guess at the initial number of outputs for the send */
1008 ChanCount outs
= (_session
->master_out())
1009 ? _session
->master_out()->n_outputs()
1010 : _route
->n_outputs();
1012 /* XXX need processor lock on route */
1014 Glib::Mutex::Lock
lm (AudioEngine::instance()->process_lock());
1015 send
->output()->ensure_io (outs
, false, this);
1016 } catch (AudioEngine::PortRegistrationFailure
& err
) {
1017 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
1021 /* let the user adjust the IO setup before creation.
1023 Note: this dialog is NOT modal - we just leave it to run and it will
1024 return when its Finished signal is emitted - typically when the window
1028 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
->output(), true);
1031 /* keep a reference to the send so it doesn't get deleted while
1032 the IOSelectorWindow is doing its stuff
1034 _processor_being_created
= send
;
1036 ios
->selector().Finished
.connect (sigc::bind (
1037 sigc::mem_fun(*this, &ProcessorBox::send_io_finished
),
1038 boost::weak_ptr
<Processor
>(send
), ios
));
1043 ProcessorBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1045 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1047 /* drop our temporary reference to the new send */
1048 _processor_being_created
.reset ();
1055 case IOSelector::Cancelled
:
1056 // processor will go away when all shared_ptrs to it vanish
1059 case IOSelector::Accepted
:
1060 _route
->add_processor (processor
, _placement
);
1061 if (Profile
->get_sae()) {
1062 processor
->activate ();
1067 delete_when_idle (ios
);
1071 ProcessorBox::return_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1073 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1075 /* drop our temporary reference to the new return */
1076 _processor_being_created
.reset ();
1083 case IOSelector::Cancelled
:
1084 // processor will go away when all shared_ptrs to it vanish
1087 case IOSelector::Accepted
:
1088 _route
->add_processor (processor
, _placement
);
1089 if (Profile
->get_sae()) {
1090 processor
->activate ();
1095 delete_when_idle (ios
);
1099 ProcessorBox::choose_aux (boost::weak_ptr
<Route
> wr
)
1105 boost::shared_ptr
<Route
> target
= wr
.lock();
1111 boost::shared_ptr
<RouteList
> rlist (new RouteList
);
1112 rlist
->push_back (_route
);
1114 _session
->add_internal_sends (target
, PreFader
, rlist
);
1118 ProcessorBox::route_processors_changed (RouteProcessorChange c
)
1120 if (c
.type
== RouteProcessorChange::MeterPointChange
&& c
.meter_visibly_changed
== false) {
1121 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1125 redisplay_processors ();
1129 ProcessorBox::redisplay_processors ()
1131 ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors
)
1133 if (no_processor_redisplay
) {
1137 processor_display
.clear ();
1139 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display
));
1141 for (list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin(); i
!= _processor_window_proxies
.end(); ++i
) {
1142 (*i
)->marked
= false;
1145 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list
));
1147 /* trim dead wood from the processor window proxy list */
1149 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin();
1150 while (i
!= _processor_window_proxies
.end()) {
1151 list
<ProcessorWindowProxy
*>::iterator j
= i
;
1154 if (!(*i
)->marked
) {
1155 ARDOUR_UI::instance()->remove_window_proxy (*i
);
1157 _processor_window_proxies
.erase (i
);
1163 setup_entry_positions ();
1166 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
1167 * not already have one.
1170 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr
<Processor
> w
)
1172 boost::shared_ptr
<Processor
> p
= w
.lock ();
1177 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
1178 while (i
!= _processor_window_proxies
.end()) {
1180 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
1183 /* this processor is already on the list; done */
1184 (*i
)->marked
= true;
1191 /* not on the list; add it */
1194 if (_parent_strip
) {
1195 if (_parent_strip
->mixer_owned()) {
1204 ProcessorWindowProxy
* wp
= new ProcessorWindowProxy (
1205 string_compose ("%1-%2-%3", loc
, _route
->id(), p
->id()),
1206 _session
->extra_xml (X_("UI")),
1212 /* if the processor already has an existing UI,
1213 note that so that we don't recreate it
1216 void* existing_ui
= p
->get_ui ();
1219 wp
->set (static_cast<Gtk::Window
*>(existing_ui
));
1222 _processor_window_proxies
.push_back (wp
);
1223 ARDOUR_UI::instance()->add_window_proxy (wp
);
1227 ProcessorBox::add_processor_to_display (boost::weak_ptr
<Processor
> p
)
1229 boost::shared_ptr
<Processor
> processor (p
.lock ());
1231 if (!processor
|| !processor
->display_to_user()) {
1235 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (processor
);
1236 boost::shared_ptr
<PluginInsert
> plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
);
1237 ProcessorEntry
* e
= 0;
1239 e
= new SendProcessorEntry (send
, _width
);
1240 } else if (plugin_insert
) {
1241 e
= new PluginInsertProcessorEntry (plugin_insert
, _width
);
1243 e
= new ProcessorEntry (processor
, _width
);
1246 e
->set_pixel_width (get_allocation().get_width());
1247 processor_display
.add_child (e
);
1252 ProcessorBox::build_processor_tooltip (EventBox
& box
, string start
)
1256 list
<ProcessorEntry
*> children
= processor_display
.children ();
1257 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1259 tip
+= (*i
)->processor()->name();
1262 ARDOUR_UI::instance()->set_tip (box
, tip
);
1266 ProcessorBox::reordered ()
1268 compute_processor_sort_keys ();
1269 setup_entry_positions ();
1273 ProcessorBox::setup_entry_positions ()
1275 list
<ProcessorEntry
*> children
= processor_display
.children ();
1276 bool pre_fader
= true;
1278 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1279 if (boost::dynamic_pointer_cast
<Amp
>((*i
)->processor())) {
1281 (*i
)->set_position (ProcessorEntry::Fader
);
1284 (*i
)->set_position (ProcessorEntry::PreFader
);
1286 (*i
)->set_position (ProcessorEntry::PostFader
);
1293 ProcessorBox::compute_processor_sort_keys ()
1295 list
<ProcessorEntry
*> children
= processor_display
.children ();
1296 Route::ProcessorList our_processors
;
1298 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1299 our_processors
.push_back ((*iter
)->processor ());
1302 if (_route
->reorder_processors (our_processors
)) {
1303 /* Reorder failed, so report this to the user. As far as I can see this must be done
1304 in an idle handler: it seems that the redisplay_processors() that happens below destroys
1305 widgets that were involved in the drag-and-drop on the processor list, which causes problems
1306 when the drag is torn down after this handler function is finished.
1308 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder
));
1313 ProcessorBox::report_failed_reorder ()
1315 /* reorder failed, so redisplay */
1317 redisplay_processors ();
1319 /* now tell them about the problem */
1321 ArdourDialog
dialog (_("Plugin Incompatibility"));
1324 label
.set_text (_("\
1325 You cannot reorder these plugins/sends/inserts\n\
1326 in that way because the inputs and\n\
1327 outputs will not work correctly."));
1329 dialog
.get_vbox()->set_border_width (12);
1330 dialog
.get_vbox()->pack_start (label
);
1331 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
1333 dialog
.set_name (X_("PluginIODialog"));
1334 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1335 dialog
.set_modal (true);
1342 ProcessorBox::rename_processors ()
1344 ProcSelection to_be_renamed
;
1346 get_selected_processors (to_be_renamed
);
1348 if (to_be_renamed
.empty()) {
1352 for (ProcSelection::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
1353 rename_processor (*i
);
1358 ProcessorBox::can_cut () const
1360 vector
<boost::shared_ptr
<Processor
> > sel
;
1362 get_selected_processors (sel
);
1364 /* cut_processors () does not cut inserts */
1366 for (vector
<boost::shared_ptr
<Processor
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
1368 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1369 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1370 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1379 ProcessorBox::cut_processors ()
1381 ProcSelection to_be_removed
;
1383 get_selected_processors (to_be_removed
);
1387 ProcessorBox::cut_processors (const ProcSelection
& to_be_removed
)
1389 if (to_be_removed
.empty()) {
1393 XMLNode
* node
= new XMLNode (X_("cut"));
1394 Route::ProcessorList to_cut
;
1396 no_processor_redisplay
= true;
1397 for (ProcSelection::const_iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
1398 // Cut only plugins, sends and returns
1399 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1400 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1401 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1403 Window
* w
= get_processor_ui (*i
);
1409 XMLNode
& child ((*i
)->get_state());
1410 node
->add_child_nocopy (child
);
1411 to_cut
.push_back (*i
);
1415 if (_route
->remove_processors (to_cut
) != 0) {
1417 no_processor_redisplay
= false;
1421 _rr_selection
.set (node
);
1423 no_processor_redisplay
= false;
1424 redisplay_processors ();
1428 ProcessorBox::copy_processors ()
1430 ProcSelection to_be_copied
;
1431 get_selected_processors (to_be_copied
);
1432 copy_processors (to_be_copied
);
1436 ProcessorBox::copy_processors (const ProcSelection
& to_be_copied
)
1438 if (to_be_copied
.empty()) {
1442 XMLNode
* node
= new XMLNode (X_("copy"));
1444 for (ProcSelection::const_iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
1445 // Copy only plugins, sends, returns
1446 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1447 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1448 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1449 node
->add_child_nocopy ((*i
)->get_state());
1453 _rr_selection
.set (node
);
1457 ProcessorBox::delete_processors ()
1459 ProcSelection to_be_deleted
;
1460 get_selected_processors (to_be_deleted
);
1461 delete_processors (to_be_deleted
);
1465 ProcessorBox::delete_processors (const ProcSelection
& targets
)
1467 if (targets
.empty()) {
1471 no_processor_redisplay
= true;
1473 for (ProcSelection::const_iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
1475 Window
* w
= get_processor_ui (*i
);
1481 _route
->remove_processor(*i
);
1484 no_processor_redisplay
= false;
1485 redisplay_processors ();
1489 ProcessorBox::delete_dragged_processors (const list
<boost::shared_ptr
<Processor
> >& procs
)
1491 list
<boost::shared_ptr
<Processor
> >::const_iterator x
;
1493 no_processor_redisplay
= true;
1494 for (x
= procs
.begin(); x
!= procs
.end(); ++x
) {
1496 Window
* w
= get_processor_ui (*x
);
1502 _route
->remove_processor(*x
);
1505 no_processor_redisplay
= false;
1506 redisplay_processors ();
1510 ProcessorBox::idle_delete_processor (boost::weak_ptr
<Processor
> weak_processor
)
1512 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1518 /* NOT copied to _mixer.selection() */
1520 no_processor_redisplay
= true;
1521 _route
->remove_processor (processor
);
1522 no_processor_redisplay
= false;
1523 redisplay_processors ();
1529 ProcessorBox::rename_processor (boost::shared_ptr
<Processor
> processor
)
1531 ArdourPrompter
name_prompter (true);
1533 name_prompter
.set_title (_("Rename Processor"));
1534 name_prompter
.set_prompt (_("New name:"));
1535 name_prompter
.set_initial_text (processor
->name());
1536 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
1537 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1538 name_prompter
.show_all ();
1540 switch (name_prompter
.run ()) {
1542 case Gtk::RESPONSE_ACCEPT
:
1543 name_prompter
.get_result (result
);
1544 if (result
.length()) {
1547 string test
= result
;
1549 while (tries
< 100) {
1550 if (_session
->io_name_is_legal (test
)) {
1556 test
= string_compose ("%1-%2", result
, tries
);
1560 processor
->set_name (result
);
1563 ARDOUR_UI::instance()->popup_error
1564 (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result
));
1574 ProcessorBox::paste_processors ()
1576 if (_rr_selection
.processors
.empty()) {
1580 paste_processor_state (_rr_selection
.processors
.get_node().children(), boost::shared_ptr
<Processor
>());
1584 ProcessorBox::paste_processors (boost::shared_ptr
<Processor
> before
)
1587 if (_rr_selection
.processors
.empty()) {
1591 paste_processor_state (_rr_selection
.processors
.get_node().children(), before
);
1595 ProcessorBox::paste_processor_state (const XMLNodeList
& nlist
, boost::shared_ptr
<Processor
> p
)
1597 XMLNodeConstIterator niter
;
1598 list
<boost::shared_ptr
<Processor
> > copies
;
1600 if (nlist
.empty()) {
1604 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1606 XMLProperty
const * type
= (*niter
)->property ("type");
1609 boost::shared_ptr
<Processor
> p
;
1611 if (type
->value() == "meter" ||
1612 type
->value() == "main-outs" ||
1613 type
->value() == "amp" ||
1614 type
->value() == "intsend" || type
->value() == "intreturn") {
1615 /* do not paste meter, main outs, amp or internal send/returns */
1618 } else if (type
->value() == "send") {
1620 XMLNode
n (**niter
);
1621 Send::make_unique (n
, *_session
);
1622 Send
* s
= new Send (*_session
, _route
->pannable(), _route
->mute_master());
1623 if (s
->set_state (n
, Stateful::loading_state_version
)) {
1631 } else if (type
->value() == "return") {
1633 XMLNode
n (**niter
);
1634 Return::make_unique (n
, *_session
);
1635 Return
* r
= new Return (*_session
);
1637 if (r
->set_state (n
, Stateful::loading_state_version
)) {
1644 } else if (type
->value() == "port") {
1646 XMLNode
n (**niter
);
1647 p
.reset (new PortInsert (*_session
, _route
->pannable (), _route
->mute_master ()));
1648 if (p
->set_state (n
, Stateful::loading_state_version
)) {
1653 /* XXX its a bit limiting to assume that everything else
1657 p
.reset (new PluginInsert (*_session
));
1658 p
->set_state (**niter
, Stateful::current_state_version
);
1661 copies
.push_back (p
);
1665 cerr
<< "plugin insert constructor failed\n";
1669 if (copies
.empty()) {
1673 if (_route
->add_processors (copies
, p
)) {
1676 "Copying the set of processors on the clipboard failed,\n\
1677 probably because the I/O configuration of the plugins\n\
1678 could not match the configuration of this track.");
1679 MessageDialog
am (msg
);
1685 ProcessorBox::activate_processor (boost::shared_ptr
<Processor
> r
)
1691 ProcessorBox::deactivate_processor (boost::shared_ptr
<Processor
> r
)
1697 ProcessorBox::get_selected_processors (ProcSelection
& processors
) const
1699 const list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1700 for (list
<ProcessorEntry
*>::const_iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1701 processors
.push_back ((*i
)->processor ());
1706 ProcessorBox::for_selected_processors (void (ProcessorBox::*method
)(boost::shared_ptr
<Processor
>))
1708 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1709 for (list
<ProcessorEntry
*>::iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1710 (this->*method
) ((*i
)->processor ());
1715 ProcessorBox::all_processors_active (bool state
)
1717 _route
->all_processors_active (_placement
, state
);
1721 ProcessorBox::ab_plugins ()
1723 _route
->ab_plugins (ab_direction
);
1724 ab_direction
= !ab_direction
;
1729 ProcessorBox::clear_processors ()
1732 vector
<string
> choices
;
1734 prompt
= string_compose (_("Do you really want to remove all processors from %1?\n"
1735 "(this cannot be undone)"), _route
->name());
1737 choices
.push_back (_("Cancel"));
1738 choices
.push_back (_("Yes, remove them all"));
1740 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1742 if (prompter
.run () == 1) {
1743 _route
->clear_processors (PreFader
);
1744 _route
->clear_processors (PostFader
);
1749 ProcessorBox::clear_processors (Placement p
)
1752 vector
<string
> choices
;
1754 if (p
== PreFader
) {
1755 prompt
= string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1756 "(this cannot be undone)"), _route
->name());
1758 prompt
= string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1759 "(this cannot be undone)"), _route
->name());
1762 choices
.push_back (_("Cancel"));
1763 choices
.push_back (_("Yes, remove them all"));
1765 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1767 if (prompter
.run () == 1) {
1768 _route
->clear_processors (p
);
1773 ProcessorBox::processor_can_be_edited (boost::shared_ptr
<Processor
> processor
)
1775 boost::shared_ptr
<AudioTrack
> at
= boost::dynamic_pointer_cast
<AudioTrack
> (_route
);
1776 if (at
&& at
->freeze_state() == AudioTrack::Frozen
) {
1781 boost::dynamic_pointer_cast
<Send
> (processor
) ||
1782 boost::dynamic_pointer_cast
<Return
> (processor
) ||
1783 boost::dynamic_pointer_cast
<PluginInsert
> (processor
) ||
1784 boost::dynamic_pointer_cast
<PortInsert
> (processor
)
1793 ProcessorBox::one_processor_can_be_edited ()
1795 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1796 list
<ProcessorEntry
*>::iterator i
= selection
.begin();
1797 while (i
!= selection
.end() && processor_can_be_edited ((*i
)->processor()) == false) {
1801 return (i
!= selection
.end());
1805 ProcessorBox::toggle_edit_processor (boost::shared_ptr
<Processor
> processor
)
1807 boost::shared_ptr
<Send
> send
;
1808 boost::shared_ptr
<InternalSend
> internal_send
;
1809 boost::shared_ptr
<Return
> retrn
;
1810 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1811 boost::shared_ptr
<PortInsert
> port_insert
;
1814 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1816 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1821 if (boost::dynamic_pointer_cast
<Amp
> (processor
)) {
1823 if (_parent_strip
) {
1824 _parent_strip
->revert_to_default_display ();
1827 } else if ((internal_send
= boost::dynamic_pointer_cast
<InternalSend
> (processor
)) != 0) {
1829 if (!_session
->engine().connected()) {
1833 if (_parent_strip
) {
1834 if (boost::dynamic_pointer_cast
<Send
> (_parent_strip
->current_delivery()) == internal_send
) {
1835 _parent_strip
->revert_to_default_display ();
1837 _parent_strip
->show_send (internal_send
);
1841 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
1843 if (!_session
->engine().connected()) {
1847 SendUIWindow
* w
= new SendUIWindow (send
, _session
);
1850 } else if ((retrn
= boost::dynamic_pointer_cast
<Return
> (processor
)) != 0) {
1852 if (boost::dynamic_pointer_cast
<InternalReturn
> (retrn
)) {
1853 /* no GUI for these */
1857 if (!_session
->engine().connected()) {
1861 boost::shared_ptr
<Return
> retrn
= boost::dynamic_pointer_cast
<Return
> (processor
);
1863 ReturnUIWindow
*return_ui
;
1864 Window
* w
= get_processor_ui (retrn
);
1868 return_ui
= new ReturnUIWindow (retrn
, _session
);
1869 return_ui
->set_title (retrn
->name ());
1870 set_processor_ui (send
, return_ui
);
1873 return_ui
= dynamic_cast<ReturnUIWindow
*> (w
);
1878 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
1880 PluginUIWindow
*plugin_ui
;
1882 /* these are both allowed to be null */
1884 Container
* toplevel
= get_toplevel();
1885 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1887 Window
* w
= get_processor_ui (plugin_insert
);
1891 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1892 plugin_ui
->set_title (generate_processor_title (plugin_insert
));
1893 set_processor_ui (plugin_insert
, plugin_ui
);
1896 plugin_ui
= dynamic_cast<PluginUIWindow
*> (w
);
1897 plugin_ui
->set_parent (win
);
1902 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (processor
)) != 0) {
1904 if (!_session
->engine().connected()) {
1905 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1910 PortInsertWindow
*io_selector
;
1912 Window
* w
= get_processor_ui (port_insert
);
1915 io_selector
= new PortInsertWindow (_session
, port_insert
);
1916 set_processor_ui (port_insert
, io_selector
);
1919 io_selector
= dynamic_cast<PortInsertWindow
*> (w
);
1922 gidget
= io_selector
;
1926 if (gidget
->is_visible()) {
1929 gidget
->show_all ();
1936 ProcessorBox::toggle_processor_controls (boost::shared_ptr
<Processor
> processor
)
1938 boost::shared_ptr
<PluginInsert
> plugin_insert
1939 = boost::dynamic_pointer_cast
<PluginInsert
>(processor
);
1940 if (!plugin_insert
) {
1944 Container
* toplevel
= get_toplevel();
1945 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1946 PluginUIWindow
* plugin_ui
= new PluginUIWindow(win
, plugin_insert
, true, false);
1947 plugin_ui
->set_title(generate_processor_title (plugin_insert
));
1949 if (plugin_ui
->is_visible()) {
1952 plugin_ui
->show_all();
1953 plugin_ui
->present();
1958 ProcessorBox::register_actions ()
1960 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("ProcessorMenu"));
1961 Glib::RefPtr
<Action
> act
;
1964 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"),
1965 sigc::ptr_fun (ProcessorBox::rb_choose_plugin
));
1967 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"),
1968 sigc::ptr_fun (ProcessorBox::rb_choose_insert
));
1969 ActionManager::jack_sensitive_actions
.push_back (act
);
1970 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."),
1971 sigc::ptr_fun (ProcessorBox::rb_choose_send
));
1972 ActionManager::jack_sensitive_actions
.push_back (act
);
1974 ActionManager::register_action (popup_act_grp
, X_("newaux"), _("New Aux Send ..."));
1976 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear (all)"),
1977 sigc::ptr_fun (ProcessorBox::rb_clear
));
1978 ActionManager::register_action (popup_act_grp
, X_("clear_pre"), _("Clear (pre-fader)"),
1979 sigc::ptr_fun (ProcessorBox::rb_clear_pre
));
1980 ActionManager::register_action (popup_act_grp
, X_("clear_post"), _("Clear (post-fader)"),
1981 sigc::ptr_fun (ProcessorBox::rb_clear_post
));
1983 /* standard editing stuff */
1984 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"),
1985 sigc::ptr_fun (ProcessorBox::rb_cut
));
1986 ActionManager::plugin_selection_sensitive_actions
.push_back(cut_action
);
1987 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"),
1988 sigc::ptr_fun (ProcessorBox::rb_copy
));
1989 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1991 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"),
1992 sigc::ptr_fun (ProcessorBox::rb_delete
));
1993 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1995 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"),
1996 sigc::ptr_fun (ProcessorBox::rb_paste
));
1997 rename_action
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"),
1998 sigc::ptr_fun (ProcessorBox::rb_rename
));
1999 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"),
2000 sigc::ptr_fun (ProcessorBox::rb_select_all
));
2001 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"),
2002 sigc::ptr_fun (ProcessorBox::rb_deselect_all
));
2004 /* activation etc. */
2006 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"),
2007 sigc::ptr_fun (ProcessorBox::rb_activate_all
));
2008 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"),
2009 sigc::ptr_fun (ProcessorBox::rb_deactivate_all
));
2010 ActionManager::register_action (popup_act_grp
, X_("ab_plugins"), _("A/B Plugins"),
2011 sigc::ptr_fun (ProcessorBox::rb_ab_plugins
));
2014 edit_action
= ActionManager::register_action (
2015 popup_act_grp
, X_("edit"), _("Edit..."),
2016 sigc::ptr_fun (ProcessorBox::rb_edit
));
2018 /* show plugin GUI */
2019 controls_action
= ActionManager::register_action (
2020 popup_act_grp
, X_("controls"), _("Controls..."),
2021 sigc::ptr_fun (ProcessorBox::rb_controls
));
2023 ActionManager::add_action_group (popup_act_grp
);
2027 ProcessorBox::rb_ab_plugins ()
2029 if (_current_processor_box
== 0) {
2033 _current_processor_box
->ab_plugins ();
2037 ProcessorBox::rb_choose_plugin ()
2039 if (_current_processor_box
== 0) {
2042 _current_processor_box
->choose_plugin ();
2046 ProcessorBox::rb_choose_insert ()
2048 if (_current_processor_box
== 0) {
2051 _current_processor_box
->choose_insert ();
2055 ProcessorBox::rb_choose_send ()
2057 if (_current_processor_box
== 0) {
2060 _current_processor_box
->choose_send ();
2064 ProcessorBox::rb_choose_aux (boost::weak_ptr
<Route
> wr
)
2066 if (_current_processor_box
== 0) {
2070 _current_processor_box
->choose_aux (wr
);
2074 ProcessorBox::rb_clear ()
2076 if (_current_processor_box
== 0) {
2080 _current_processor_box
->clear_processors ();
2085 ProcessorBox::rb_clear_pre ()
2087 if (_current_processor_box
== 0) {
2091 _current_processor_box
->clear_processors (PreFader
);
2096 ProcessorBox::rb_clear_post ()
2098 if (_current_processor_box
== 0) {
2102 _current_processor_box
->clear_processors (PostFader
);
2106 ProcessorBox::rb_cut ()
2108 if (_current_processor_box
== 0) {
2112 _current_processor_box
->cut_processors ();
2116 ProcessorBox::rb_delete ()
2118 if (_current_processor_box
== 0) {
2122 _current_processor_box
->delete_processors ();
2126 ProcessorBox::rb_copy ()
2128 if (_current_processor_box
== 0) {
2131 _current_processor_box
->copy_processors ();
2135 ProcessorBox::rb_paste ()
2137 if (_current_processor_box
== 0) {
2141 _current_processor_box
->paste_processors ();
2145 ProcessorBox::rb_rename ()
2147 if (_current_processor_box
== 0) {
2150 _current_processor_box
->rename_processors ();
2154 ProcessorBox::rb_select_all ()
2156 if (_current_processor_box
== 0) {
2160 _current_processor_box
->select_all_processors ();
2164 ProcessorBox::rb_deselect_all ()
2166 if (_current_processor_box
== 0) {
2170 _current_processor_box
->deselect_all_processors ();
2174 ProcessorBox::rb_activate_all ()
2176 if (_current_processor_box
== 0) {
2180 _current_processor_box
->all_processors_active (true);
2184 ProcessorBox::rb_deactivate_all ()
2186 if (_current_processor_box
== 0) {
2189 _current_processor_box
->all_processors_active (false);
2193 ProcessorBox::rb_edit ()
2195 if (_current_processor_box
== 0) {
2199 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_edit_processor
);
2203 ProcessorBox::rb_controls ()
2205 if (_current_processor_box
== 0) {
2209 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_processor_controls
);
2213 ProcessorBox::route_property_changed (const PropertyChange
& what_changed
)
2215 if (!what_changed
.contains (ARDOUR::Properties::name
)) {
2219 ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed
, what_changed
);
2221 boost::shared_ptr
<Processor
> processor
;
2222 boost::shared_ptr
<PluginInsert
> plugin_insert
;
2223 boost::shared_ptr
<Send
> send
;
2225 list
<ProcessorEntry
*> children
= processor_display
.children();
2227 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
2229 processor
= (*iter
)->processor ();
2231 Window
* w
= get_processor_ui (processor
);
2237 /* rename editor windows for sends and plugins */
2239 if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
2240 w
->set_title (send
->name ());
2241 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
2242 w
->set_title (generate_processor_title (plugin_insert
));
2248 ProcessorBox::generate_processor_title (boost::shared_ptr
<PluginInsert
> pi
)
2250 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
2251 string::size_type email_pos
;
2253 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
2254 maker
= maker
.substr (0, email_pos
- 1);
2257 if (maker
.length() > 32) {
2258 maker
= maker
.substr (0, 32);
2262 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);
2266 ProcessorBox::on_size_allocate (Allocation
& a
)
2268 HBox::on_size_allocate (a
);
2270 list
<ProcessorEntry
*> children
= processor_display
.children ();
2271 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
2272 (*i
)->set_pixel_width (a
.get_width ());
2276 /** @param p Processor.
2277 * @return the UI window for \a p.
2280 ProcessorBox::get_processor_ui (boost::shared_ptr
<Processor
> p
) const
2282 list
<ProcessorWindowProxy
*>::const_iterator i
= _processor_window_proxies
.begin ();
2283 while (i
!= _processor_window_proxies
.end()) {
2284 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2286 return (*i
)->get ();
2292 /* we shouldn't get here, because the ProcessorUIList should always contain
2293 an entry for each processor.
2299 /** Make a note of the UI window that a processor is using.
2300 * @param p Processor.
2301 * @param w UI window.
2304 ProcessorBox::set_processor_ui (boost::shared_ptr
<Processor
> p
, Gtk::Window
* w
)
2306 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
2310 while (i
!= _processor_window_proxies
.end()) {
2311 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2320 /* we shouldn't get here, because the ProcessorUIList should always contain
2321 an entry for each processor.
2327 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr
<Delivery
> w
)
2329 boost::shared_ptr
<Delivery
> d
= w
.lock ();
2334 list
<ProcessorEntry
*> children
= processor_display
.children ();
2335 list
<ProcessorEntry
*>::const_iterator i
= children
.begin();
2336 while (i
!= children
.end() && (*i
)->processor() != d
) {
2340 if (i
== children
.end()) {
2341 processor_display
.set_active (0);
2343 processor_display
.set_active (*i
);
2348 ProcessorBox::hide_things ()
2350 list
<ProcessorEntry
*> c
= processor_display
.children ();
2351 for (list
<ProcessorEntry
*>::iterator i
= c
.begin(); i
!= c
.end(); ++i
) {
2352 (*i
)->hide_things ();
2356 ProcessorWindowProxy::ProcessorWindowProxy (
2357 string
const & name
,
2358 XMLNode
const * node
,
2360 boost::weak_ptr
<Processor
> processor
2362 : WindowProxy
<Gtk::Window
> (name
, node
)
2364 , _processor_box (box
)
2365 , _processor (processor
)
2372 ProcessorWindowProxy::show ()
2374 boost::shared_ptr
<Processor
> p
= _processor
.lock ();
2379 _processor_box
->toggle_edit_processor (p
);