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 ();
826 if (processor
&& Keyboard::is_delete_event (ev
)) {
828 Glib::signal_idle().connect (sigc::bind (
829 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor
),
830 boost::weak_ptr
<Processor
>(processor
)));
832 } else if (Keyboard::is_context_menu_event (ev
)) {
834 /* figure out if we are above or below the fader/amp processor,
835 and set the next insert position appropriately.
839 if (_route
->processor_is_prefader (processor
)) {
840 _placement
= PreFader
;
842 _placement
= PostFader
;
845 _placement
= PostFader
;
848 show_processor_menu (ev
->time
);
850 } else if (processor
&& Keyboard::is_button2_event (ev
)
852 && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))
856 /* button2-click with no/appropriate modifiers */
858 if (processor
->active()) {
859 processor
->deactivate ();
861 processor
->activate ();
869 ProcessorBox::build_processor_menu ()
871 processor_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/ProcessorMenu") );
872 processor_menu
->set_name ("ArdourContextMenu");
873 return processor_menu
;
877 ProcessorBox::selection_changed ()
879 const bool sensitive
= !processor_display
.selection().empty();
880 ActionManager::set_sensitive(ActionManager::plugin_selection_sensitive_actions
,
882 edit_action
->set_sensitive(one_processor_can_be_edited());
884 const bool single_selection
= (processor_display
.selection().size() == 1);
886 boost::shared_ptr
<PluginInsert
> pi
;
887 if (single_selection
) {
888 pi
= boost::dynamic_pointer_cast
<PluginInsert
>(
889 processor_display
.selection().front()->processor());
892 /* enable gui for plugin inserts with editors */
893 controls_action
->set_sensitive(pi
&& pi
->plugin()->has_editor());
895 /* disallow rename for multiple selections and for plugin inserts */
896 rename_action
->set_sensitive(single_selection
&& pi
);
900 ProcessorBox::select_all_processors ()
902 processor_display
.select_all ();
906 ProcessorBox::deselect_all_processors ()
908 processor_display
.select_none ();
912 ProcessorBox::choose_plugin ()
914 _get_plugin_selector()->set_interested_object (*this);
917 /** @return true if an error occurred, otherwise false */
919 ProcessorBox::use_plugins (const SelectedPlugins
& plugins
)
921 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
923 boost::shared_ptr
<Processor
> processor (new PluginInsert (*_session
, *p
));
925 Route::ProcessorStreams err_streams
;
927 if (_route
->add_processor (processor
, _placement
, &err_streams
, Config
->get_new_plugins_active ())) {
928 weird_plugin_dialog (**p
, err_streams
);
930 // XXX SHAREDPTR delete plugin here .. do we even need to care?
933 if (Profile
->get_sae()) {
934 processor
->activate ();
943 ProcessorBox::weird_plugin_dialog (Plugin
& p
, Route::ProcessorStreams streams
)
945 ArdourDialog
dialog (_("Plugin Incompatibility"));
948 string text
= string_compose(_("You attempted to add the plugin \"%1\" in slot %2.\n"),
949 p
.name(), streams
.index
);
951 bool has_midi
= streams
.count
.n_midi() > 0 || p
.get_info()->n_inputs
.n_midi() > 0;
952 bool has_audio
= streams
.count
.n_audio() > 0 || p
.get_info()->n_inputs
.n_audio() > 0;
954 text
+= _("\nThis plugin has:\n");
956 uint32_t const n
= p
.get_info()->n_inputs
.n_midi ();
957 text
+= string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n
), n
);
960 uint32_t const n
= p
.get_info()->n_inputs
.n_audio ();
961 text
+= string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n
), n
);
964 text
+= _("\nbut at the insertion point, there are:\n");
966 uint32_t const n
= streams
.count
.n_midi ();
967 text
+= string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n
), n
);
970 uint32_t const n
= streams
.count
.n_audio ();
971 text
+= string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n
), n
);
974 text
+= string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME
);
975 label
.set_text(text
);
977 dialog
.get_vbox()->pack_start (label
);
978 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
980 dialog
.set_name (X_("PluginIODialog"));
981 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
982 dialog
.set_modal (true);
989 ProcessorBox::choose_insert ()
991 boost::shared_ptr
<Processor
> processor (new PortInsert (*_session
, _route
->pannable(), _route
->mute_master()));
992 _route
->add_processor (processor
, _placement
);
995 /* Caller must not hold process lock */
997 ProcessorBox::choose_send ()
999 boost::shared_ptr
<Send
> send (new Send (*_session
, _route
->pannable(), _route
->mute_master()));
1001 /* make an educated guess at the initial number of outputs for the send */
1002 ChanCount outs
= (_session
->master_out())
1003 ? _session
->master_out()->n_outputs()
1004 : _route
->n_outputs();
1006 /* XXX need processor lock on route */
1008 Glib::Mutex::Lock
lm (AudioEngine::instance()->process_lock());
1009 send
->output()->ensure_io (outs
, false, this);
1010 } catch (AudioEngine::PortRegistrationFailure
& err
) {
1011 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
1015 /* let the user adjust the IO setup before creation.
1017 Note: this dialog is NOT modal - we just leave it to run and it will
1018 return when its Finished signal is emitted - typically when the window
1022 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
->output(), true);
1025 /* keep a reference to the send so it doesn't get deleted while
1026 the IOSelectorWindow is doing its stuff
1028 _processor_being_created
= send
;
1030 ios
->selector().Finished
.connect (sigc::bind (
1031 sigc::mem_fun(*this, &ProcessorBox::send_io_finished
),
1032 boost::weak_ptr
<Processor
>(send
), ios
));
1037 ProcessorBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1039 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1041 /* drop our temporary reference to the new send */
1042 _processor_being_created
.reset ();
1049 case IOSelector::Cancelled
:
1050 // processor will go away when all shared_ptrs to it vanish
1053 case IOSelector::Accepted
:
1054 _route
->add_processor (processor
, _placement
);
1055 if (Profile
->get_sae()) {
1056 processor
->activate ();
1061 delete_when_idle (ios
);
1065 ProcessorBox::return_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1067 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1069 /* drop our temporary reference to the new return */
1070 _processor_being_created
.reset ();
1077 case IOSelector::Cancelled
:
1078 // processor will go away when all shared_ptrs to it vanish
1081 case IOSelector::Accepted
:
1082 _route
->add_processor (processor
, _placement
);
1083 if (Profile
->get_sae()) {
1084 processor
->activate ();
1089 delete_when_idle (ios
);
1093 ProcessorBox::choose_aux (boost::weak_ptr
<Route
> wr
)
1099 boost::shared_ptr
<Route
> target
= wr
.lock();
1105 boost::shared_ptr
<RouteList
> rlist (new RouteList
);
1106 rlist
->push_back (_route
);
1108 _session
->add_internal_sends (target
, PreFader
, rlist
);
1112 ProcessorBox::route_processors_changed (RouteProcessorChange c
)
1114 if (c
.type
== RouteProcessorChange::MeterPointChange
&& c
.meter_visibly_changed
== false) {
1115 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1119 redisplay_processors ();
1123 ProcessorBox::redisplay_processors ()
1125 ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors
)
1127 if (no_processor_redisplay
) {
1131 processor_display
.clear ();
1133 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display
));
1135 for (list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin(); i
!= _processor_window_proxies
.end(); ++i
) {
1136 (*i
)->marked
= false;
1139 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list
));
1141 /* trim dead wood from the processor window proxy list */
1143 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin();
1144 while (i
!= _processor_window_proxies
.end()) {
1145 list
<ProcessorWindowProxy
*>::iterator j
= i
;
1148 if (!(*i
)->marked
) {
1149 ARDOUR_UI::instance()->remove_window_proxy (*i
);
1151 _processor_window_proxies
.erase (i
);
1157 setup_entry_positions ();
1160 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
1161 * not already have one.
1164 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr
<Processor
> w
)
1166 boost::shared_ptr
<Processor
> p
= w
.lock ();
1171 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
1172 while (i
!= _processor_window_proxies
.end()) {
1174 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
1177 /* this processor is already on the list; done */
1178 (*i
)->marked
= true;
1185 /* not on the list; add it */
1188 if (_parent_strip
) {
1189 if (_parent_strip
->mixer_owned()) {
1198 ProcessorWindowProxy
* wp
= new ProcessorWindowProxy (
1199 string_compose ("%1-%2-%3", loc
, _route
->id(), p
->id()),
1200 _session
->extra_xml (X_("UI")),
1206 /* if the processor already has an existing UI,
1207 note that so that we don't recreate it
1210 void* existing_ui
= p
->get_ui ();
1213 wp
->set (static_cast<Gtk::Window
*>(existing_ui
));
1216 _processor_window_proxies
.push_back (wp
);
1217 ARDOUR_UI::instance()->add_window_proxy (wp
);
1221 ProcessorBox::add_processor_to_display (boost::weak_ptr
<Processor
> p
)
1223 boost::shared_ptr
<Processor
> processor (p
.lock ());
1225 if (!processor
|| !processor
->display_to_user()) {
1229 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (processor
);
1230 boost::shared_ptr
<PluginInsert
> plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
);
1231 ProcessorEntry
* e
= 0;
1233 e
= new SendProcessorEntry (send
, _width
);
1234 } else if (plugin_insert
) {
1235 e
= new PluginInsertProcessorEntry (plugin_insert
, _width
);
1237 e
= new ProcessorEntry (processor
, _width
);
1240 e
->set_pixel_width (get_allocation().get_width());
1241 processor_display
.add_child (e
);
1246 ProcessorBox::build_processor_tooltip (EventBox
& box
, string start
)
1250 list
<ProcessorEntry
*> children
= processor_display
.children ();
1251 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1253 tip
+= (*i
)->processor()->name();
1256 ARDOUR_UI::instance()->set_tip (box
, tip
);
1260 ProcessorBox::reordered ()
1262 compute_processor_sort_keys ();
1263 setup_entry_positions ();
1267 ProcessorBox::setup_entry_positions ()
1269 list
<ProcessorEntry
*> children
= processor_display
.children ();
1270 bool pre_fader
= true;
1272 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1273 if (boost::dynamic_pointer_cast
<Amp
>((*i
)->processor())) {
1275 (*i
)->set_position (ProcessorEntry::Fader
);
1278 (*i
)->set_position (ProcessorEntry::PreFader
);
1280 (*i
)->set_position (ProcessorEntry::PostFader
);
1287 ProcessorBox::compute_processor_sort_keys ()
1289 list
<ProcessorEntry
*> children
= processor_display
.children ();
1290 Route::ProcessorList our_processors
;
1292 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1293 our_processors
.push_back ((*iter
)->processor ());
1296 if (_route
->reorder_processors (our_processors
)) {
1297 /* Reorder failed, so report this to the user. As far as I can see this must be done
1298 in an idle handler: it seems that the redisplay_processors() that happens below destroys
1299 widgets that were involved in the drag-and-drop on the processor list, which causes problems
1300 when the drag is torn down after this handler function is finished.
1302 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder
));
1307 ProcessorBox::report_failed_reorder ()
1309 /* reorder failed, so redisplay */
1311 redisplay_processors ();
1313 /* now tell them about the problem */
1315 ArdourDialog
dialog (_("Plugin Incompatibility"));
1318 label
.set_text (_("\
1319 You cannot reorder these plugins/sends/inserts\n\
1320 in that way because the inputs and\n\
1321 outputs will not work correctly."));
1323 dialog
.get_vbox()->set_border_width (12);
1324 dialog
.get_vbox()->pack_start (label
);
1325 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
1327 dialog
.set_name (X_("PluginIODialog"));
1328 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1329 dialog
.set_modal (true);
1336 ProcessorBox::rename_processors ()
1338 ProcSelection to_be_renamed
;
1340 get_selected_processors (to_be_renamed
);
1342 if (to_be_renamed
.empty()) {
1346 for (ProcSelection::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
1347 rename_processor (*i
);
1352 ProcessorBox::can_cut () const
1354 vector
<boost::shared_ptr
<Processor
> > sel
;
1356 get_selected_processors (sel
);
1358 /* cut_processors () does not cut inserts */
1360 for (vector
<boost::shared_ptr
<Processor
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
1362 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1363 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1364 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1373 ProcessorBox::cut_processors ()
1375 ProcSelection to_be_removed
;
1377 get_selected_processors (to_be_removed
);
1381 ProcessorBox::cut_processors (const ProcSelection
& to_be_removed
)
1383 if (to_be_removed
.empty()) {
1387 XMLNode
* node
= new XMLNode (X_("cut"));
1388 Route::ProcessorList to_cut
;
1390 no_processor_redisplay
= true;
1391 for (ProcSelection::const_iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
1392 // Cut only plugins, sends and returns
1393 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1394 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1395 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1397 Window
* w
= get_processor_ui (*i
);
1403 XMLNode
& child ((*i
)->get_state());
1404 node
->add_child_nocopy (child
);
1405 to_cut
.push_back (*i
);
1409 if (_route
->remove_processors (to_cut
) != 0) {
1411 no_processor_redisplay
= false;
1415 _rr_selection
.set (node
);
1417 no_processor_redisplay
= false;
1418 redisplay_processors ();
1422 ProcessorBox::copy_processors ()
1424 ProcSelection to_be_copied
;
1425 get_selected_processors (to_be_copied
);
1426 copy_processors (to_be_copied
);
1430 ProcessorBox::copy_processors (const ProcSelection
& to_be_copied
)
1432 if (to_be_copied
.empty()) {
1436 XMLNode
* node
= new XMLNode (X_("copy"));
1438 for (ProcSelection::const_iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
1439 // Copy only plugins, sends, returns
1440 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1441 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1442 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1443 node
->add_child_nocopy ((*i
)->get_state());
1447 _rr_selection
.set (node
);
1451 ProcessorBox::delete_processors ()
1453 ProcSelection to_be_deleted
;
1454 get_selected_processors (to_be_deleted
);
1455 delete_processors (to_be_deleted
);
1459 ProcessorBox::delete_processors (const ProcSelection
& targets
)
1461 if (targets
.empty()) {
1465 no_processor_redisplay
= true;
1467 for (ProcSelection::const_iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
1469 Window
* w
= get_processor_ui (*i
);
1475 _route
->remove_processor(*i
);
1478 no_processor_redisplay
= false;
1479 redisplay_processors ();
1483 ProcessorBox::delete_dragged_processors (const list
<boost::shared_ptr
<Processor
> >& procs
)
1485 list
<boost::shared_ptr
<Processor
> >::const_iterator x
;
1487 no_processor_redisplay
= true;
1488 for (x
= procs
.begin(); x
!= procs
.end(); ++x
) {
1490 Window
* w
= get_processor_ui (*x
);
1496 _route
->remove_processor(*x
);
1499 no_processor_redisplay
= false;
1500 redisplay_processors ();
1504 ProcessorBox::idle_delete_processor (boost::weak_ptr
<Processor
> weak_processor
)
1506 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1512 /* NOT copied to _mixer.selection() */
1514 no_processor_redisplay
= true;
1515 _route
->remove_processor (processor
);
1516 no_processor_redisplay
= false;
1517 redisplay_processors ();
1523 ProcessorBox::rename_processor (boost::shared_ptr
<Processor
> processor
)
1525 ArdourPrompter
name_prompter (true);
1527 name_prompter
.set_title (_("Rename Processor"));
1528 name_prompter
.set_prompt (_("New name:"));
1529 name_prompter
.set_initial_text (processor
->name());
1530 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
1531 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1532 name_prompter
.show_all ();
1534 switch (name_prompter
.run ()) {
1536 case Gtk::RESPONSE_ACCEPT
:
1537 name_prompter
.get_result (result
);
1538 if (result
.length()) {
1541 string test
= result
;
1543 while (tries
< 100) {
1544 if (_session
->io_name_is_legal (test
)) {
1550 test
= string_compose ("%1-%2", result
, tries
);
1554 processor
->set_name (result
);
1557 ARDOUR_UI::instance()->popup_error
1558 (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result
));
1568 ProcessorBox::paste_processors ()
1570 if (_rr_selection
.processors
.empty()) {
1574 paste_processor_state (_rr_selection
.processors
.get_node().children(), boost::shared_ptr
<Processor
>());
1578 ProcessorBox::paste_processors (boost::shared_ptr
<Processor
> before
)
1581 if (_rr_selection
.processors
.empty()) {
1585 paste_processor_state (_rr_selection
.processors
.get_node().children(), before
);
1589 ProcessorBox::paste_processor_state (const XMLNodeList
& nlist
, boost::shared_ptr
<Processor
> p
)
1591 XMLNodeConstIterator niter
;
1592 list
<boost::shared_ptr
<Processor
> > copies
;
1594 if (nlist
.empty()) {
1598 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1600 XMLProperty
const * type
= (*niter
)->property ("type");
1603 boost::shared_ptr
<Processor
> p
;
1605 if (type
->value() == "meter" ||
1606 type
->value() == "main-outs" ||
1607 type
->value() == "amp" ||
1608 type
->value() == "intsend" || type
->value() == "intreturn") {
1609 /* do not paste meter, main outs, amp or internal send/returns */
1612 } else if (type
->value() == "send") {
1614 XMLNode
n (**niter
);
1615 Send::make_unique (n
, *_session
);
1616 Send
* s
= new Send (*_session
, _route
->pannable(), _route
->mute_master());
1617 if (s
->set_state (n
, Stateful::loading_state_version
)) {
1625 } else if (type
->value() == "return") {
1627 XMLNode
n (**niter
);
1628 Return::make_unique (n
, *_session
);
1629 Return
* r
= new Return (*_session
);
1631 if (r
->set_state (n
, Stateful::loading_state_version
)) {
1638 } else if (type
->value() == "port") {
1640 XMLNode
n (**niter
);
1641 p
.reset (new PortInsert (*_session
, _route
->pannable (), _route
->mute_master ()));
1642 if (p
->set_state (n
, Stateful::loading_state_version
)) {
1647 /* XXX its a bit limiting to assume that everything else
1651 p
.reset (new PluginInsert (*_session
));
1652 p
->set_state (**niter
, Stateful::current_state_version
);
1655 copies
.push_back (p
);
1659 cerr
<< "plugin insert constructor failed\n";
1663 if (copies
.empty()) {
1667 if (_route
->add_processors (copies
, p
)) {
1670 "Copying the set of processors on the clipboard failed,\n\
1671 probably because the I/O configuration of the plugins\n\
1672 could not match the configuration of this track.");
1673 MessageDialog
am (msg
);
1679 ProcessorBox::activate_processor (boost::shared_ptr
<Processor
> r
)
1685 ProcessorBox::deactivate_processor (boost::shared_ptr
<Processor
> r
)
1691 ProcessorBox::get_selected_processors (ProcSelection
& processors
) const
1693 const list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1694 for (list
<ProcessorEntry
*>::const_iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1695 processors
.push_back ((*i
)->processor ());
1700 ProcessorBox::for_selected_processors (void (ProcessorBox::*method
)(boost::shared_ptr
<Processor
>))
1702 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1703 for (list
<ProcessorEntry
*>::iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1704 (this->*method
) ((*i
)->processor ());
1709 ProcessorBox::all_processors_active (bool state
)
1711 _route
->all_processors_active (_placement
, state
);
1715 ProcessorBox::ab_plugins ()
1717 _route
->ab_plugins (ab_direction
);
1718 ab_direction
= !ab_direction
;
1723 ProcessorBox::clear_processors ()
1726 vector
<string
> choices
;
1728 prompt
= string_compose (_("Do you really want to remove all processors from %1?\n"
1729 "(this cannot be undone)"), _route
->name());
1731 choices
.push_back (_("Cancel"));
1732 choices
.push_back (_("Yes, remove them all"));
1734 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1736 if (prompter
.run () == 1) {
1737 _route
->clear_processors (PreFader
);
1738 _route
->clear_processors (PostFader
);
1743 ProcessorBox::clear_processors (Placement p
)
1746 vector
<string
> choices
;
1748 if (p
== PreFader
) {
1749 prompt
= string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1750 "(this cannot be undone)"), _route
->name());
1752 prompt
= string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1753 "(this cannot be undone)"), _route
->name());
1756 choices
.push_back (_("Cancel"));
1757 choices
.push_back (_("Yes, remove them all"));
1759 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1761 if (prompter
.run () == 1) {
1762 _route
->clear_processors (p
);
1767 ProcessorBox::processor_can_be_edited (boost::shared_ptr
<Processor
> processor
)
1769 boost::shared_ptr
<AudioTrack
> at
= boost::dynamic_pointer_cast
<AudioTrack
> (_route
);
1770 if (at
&& at
->freeze_state() == AudioTrack::Frozen
) {
1775 boost::dynamic_pointer_cast
<Send
> (processor
) ||
1776 boost::dynamic_pointer_cast
<Return
> (processor
) ||
1777 boost::dynamic_pointer_cast
<PluginInsert
> (processor
) ||
1778 boost::dynamic_pointer_cast
<PortInsert
> (processor
)
1787 ProcessorBox::one_processor_can_be_edited ()
1789 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1790 list
<ProcessorEntry
*>::iterator i
= selection
.begin();
1791 while (i
!= selection
.end() && processor_can_be_edited ((*i
)->processor()) == false) {
1795 return (i
!= selection
.end());
1799 ProcessorBox::toggle_edit_processor (boost::shared_ptr
<Processor
> processor
)
1801 boost::shared_ptr
<Send
> send
;
1802 boost::shared_ptr
<InternalSend
> internal_send
;
1803 boost::shared_ptr
<Return
> retrn
;
1804 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1805 boost::shared_ptr
<PortInsert
> port_insert
;
1808 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1810 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1815 if (boost::dynamic_pointer_cast
<Amp
> (processor
)) {
1817 if (_parent_strip
) {
1818 _parent_strip
->revert_to_default_display ();
1821 } else if ((internal_send
= boost::dynamic_pointer_cast
<InternalSend
> (processor
)) != 0) {
1823 if (!_session
->engine().connected()) {
1827 if (_parent_strip
) {
1828 if (boost::dynamic_pointer_cast
<Send
> (_parent_strip
->current_delivery()) == internal_send
) {
1829 _parent_strip
->revert_to_default_display ();
1831 _parent_strip
->show_send (internal_send
);
1835 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
1837 if (!_session
->engine().connected()) {
1841 SendUIWindow
* w
= new SendUIWindow (send
, _session
);
1844 } else if ((retrn
= boost::dynamic_pointer_cast
<Return
> (processor
)) != 0) {
1846 if (boost::dynamic_pointer_cast
<InternalReturn
> (retrn
)) {
1847 /* no GUI for these */
1851 if (!_session
->engine().connected()) {
1855 boost::shared_ptr
<Return
> retrn
= boost::dynamic_pointer_cast
<Return
> (processor
);
1857 ReturnUIWindow
*return_ui
;
1858 Window
* w
= get_processor_ui (retrn
);
1862 return_ui
= new ReturnUIWindow (retrn
, _session
);
1863 return_ui
->set_title (retrn
->name ());
1864 set_processor_ui (send
, return_ui
);
1867 return_ui
= dynamic_cast<ReturnUIWindow
*> (w
);
1872 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
1874 PluginUIWindow
*plugin_ui
;
1876 /* these are both allowed to be null */
1878 Container
* toplevel
= get_toplevel();
1879 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1881 Window
* w
= get_processor_ui (plugin_insert
);
1885 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1886 plugin_ui
->set_title (generate_processor_title (plugin_insert
));
1887 set_processor_ui (plugin_insert
, plugin_ui
);
1890 plugin_ui
= dynamic_cast<PluginUIWindow
*> (w
);
1891 plugin_ui
->set_parent (win
);
1896 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (processor
)) != 0) {
1898 if (!_session
->engine().connected()) {
1899 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1904 PortInsertWindow
*io_selector
;
1906 Window
* w
= get_processor_ui (port_insert
);
1909 io_selector
= new PortInsertWindow (_session
, port_insert
);
1910 set_processor_ui (port_insert
, io_selector
);
1913 io_selector
= dynamic_cast<PortInsertWindow
*> (w
);
1916 gidget
= io_selector
;
1920 if (gidget
->is_visible()) {
1923 gidget
->show_all ();
1930 ProcessorBox::toggle_processor_controls (boost::shared_ptr
<Processor
> processor
)
1932 boost::shared_ptr
<PluginInsert
> plugin_insert
1933 = boost::dynamic_pointer_cast
<PluginInsert
>(processor
);
1934 if (!plugin_insert
) {
1938 Container
* toplevel
= get_toplevel();
1939 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1940 PluginUIWindow
* plugin_ui
= new PluginUIWindow(win
, plugin_insert
, true, false);
1941 plugin_ui
->set_title(generate_processor_title (plugin_insert
));
1943 if (plugin_ui
->is_visible()) {
1946 plugin_ui
->show_all();
1947 plugin_ui
->present();
1952 ProcessorBox::register_actions ()
1954 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("ProcessorMenu"));
1955 Glib::RefPtr
<Action
> act
;
1958 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"),
1959 sigc::ptr_fun (ProcessorBox::rb_choose_plugin
));
1961 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"),
1962 sigc::ptr_fun (ProcessorBox::rb_choose_insert
));
1963 ActionManager::jack_sensitive_actions
.push_back (act
);
1964 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."),
1965 sigc::ptr_fun (ProcessorBox::rb_choose_send
));
1966 ActionManager::jack_sensitive_actions
.push_back (act
);
1968 ActionManager::register_action (popup_act_grp
, X_("newaux"), _("New Aux Send ..."));
1970 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear (all)"),
1971 sigc::ptr_fun (ProcessorBox::rb_clear
));
1972 ActionManager::register_action (popup_act_grp
, X_("clear_pre"), _("Clear (pre-fader)"),
1973 sigc::ptr_fun (ProcessorBox::rb_clear_pre
));
1974 ActionManager::register_action (popup_act_grp
, X_("clear_post"), _("Clear (post-fader)"),
1975 sigc::ptr_fun (ProcessorBox::rb_clear_post
));
1977 /* standard editing stuff */
1978 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"),
1979 sigc::ptr_fun (ProcessorBox::rb_cut
));
1980 ActionManager::plugin_selection_sensitive_actions
.push_back(cut_action
);
1981 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"),
1982 sigc::ptr_fun (ProcessorBox::rb_copy
));
1983 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1985 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"),
1986 sigc::ptr_fun (ProcessorBox::rb_delete
));
1987 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1989 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"),
1990 sigc::ptr_fun (ProcessorBox::rb_paste
));
1991 rename_action
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"),
1992 sigc::ptr_fun (ProcessorBox::rb_rename
));
1993 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"),
1994 sigc::ptr_fun (ProcessorBox::rb_select_all
));
1995 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"),
1996 sigc::ptr_fun (ProcessorBox::rb_deselect_all
));
1998 /* activation etc. */
2000 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"),
2001 sigc::ptr_fun (ProcessorBox::rb_activate_all
));
2002 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"),
2003 sigc::ptr_fun (ProcessorBox::rb_deactivate_all
));
2004 ActionManager::register_action (popup_act_grp
, X_("ab_plugins"), _("A/B Plugins"),
2005 sigc::ptr_fun (ProcessorBox::rb_ab_plugins
));
2008 edit_action
= ActionManager::register_action (
2009 popup_act_grp
, X_("edit"), _("Edit..."),
2010 sigc::ptr_fun (ProcessorBox::rb_edit
));
2012 /* show plugin GUI */
2013 controls_action
= ActionManager::register_action (
2014 popup_act_grp
, X_("controls"), _("Controls..."),
2015 sigc::ptr_fun (ProcessorBox::rb_controls
));
2017 ActionManager::add_action_group (popup_act_grp
);
2021 ProcessorBox::rb_ab_plugins ()
2023 if (_current_processor_box
== 0) {
2027 _current_processor_box
->ab_plugins ();
2031 ProcessorBox::rb_choose_plugin ()
2033 if (_current_processor_box
== 0) {
2036 _current_processor_box
->choose_plugin ();
2040 ProcessorBox::rb_choose_insert ()
2042 if (_current_processor_box
== 0) {
2045 _current_processor_box
->choose_insert ();
2049 ProcessorBox::rb_choose_send ()
2051 if (_current_processor_box
== 0) {
2054 _current_processor_box
->choose_send ();
2058 ProcessorBox::rb_choose_aux (boost::weak_ptr
<Route
> wr
)
2060 if (_current_processor_box
== 0) {
2064 _current_processor_box
->choose_aux (wr
);
2068 ProcessorBox::rb_clear ()
2070 if (_current_processor_box
== 0) {
2074 _current_processor_box
->clear_processors ();
2079 ProcessorBox::rb_clear_pre ()
2081 if (_current_processor_box
== 0) {
2085 _current_processor_box
->clear_processors (PreFader
);
2090 ProcessorBox::rb_clear_post ()
2092 if (_current_processor_box
== 0) {
2096 _current_processor_box
->clear_processors (PostFader
);
2100 ProcessorBox::rb_cut ()
2102 if (_current_processor_box
== 0) {
2106 _current_processor_box
->cut_processors ();
2110 ProcessorBox::rb_delete ()
2112 if (_current_processor_box
== 0) {
2116 _current_processor_box
->delete_processors ();
2120 ProcessorBox::rb_copy ()
2122 if (_current_processor_box
== 0) {
2125 _current_processor_box
->copy_processors ();
2129 ProcessorBox::rb_paste ()
2131 if (_current_processor_box
== 0) {
2135 _current_processor_box
->paste_processors ();
2139 ProcessorBox::rb_rename ()
2141 if (_current_processor_box
== 0) {
2144 _current_processor_box
->rename_processors ();
2148 ProcessorBox::rb_select_all ()
2150 if (_current_processor_box
== 0) {
2154 _current_processor_box
->select_all_processors ();
2158 ProcessorBox::rb_deselect_all ()
2160 if (_current_processor_box
== 0) {
2164 _current_processor_box
->deselect_all_processors ();
2168 ProcessorBox::rb_activate_all ()
2170 if (_current_processor_box
== 0) {
2174 _current_processor_box
->all_processors_active (true);
2178 ProcessorBox::rb_deactivate_all ()
2180 if (_current_processor_box
== 0) {
2183 _current_processor_box
->all_processors_active (false);
2187 ProcessorBox::rb_edit ()
2189 if (_current_processor_box
== 0) {
2193 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_edit_processor
);
2197 ProcessorBox::rb_controls ()
2199 if (_current_processor_box
== 0) {
2203 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_processor_controls
);
2207 ProcessorBox::route_property_changed (const PropertyChange
& what_changed
)
2209 if (!what_changed
.contains (ARDOUR::Properties::name
)) {
2213 ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed
, what_changed
);
2215 boost::shared_ptr
<Processor
> processor
;
2216 boost::shared_ptr
<PluginInsert
> plugin_insert
;
2217 boost::shared_ptr
<Send
> send
;
2219 list
<ProcessorEntry
*> children
= processor_display
.children();
2221 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
2223 processor
= (*iter
)->processor ();
2225 Window
* w
= get_processor_ui (processor
);
2231 /* rename editor windows for sends and plugins */
2233 if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
2234 w
->set_title (send
->name ());
2235 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
2236 w
->set_title (generate_processor_title (plugin_insert
));
2242 ProcessorBox::generate_processor_title (boost::shared_ptr
<PluginInsert
> pi
)
2244 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
2245 string::size_type email_pos
;
2247 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
2248 maker
= maker
.substr (0, email_pos
- 1);
2251 if (maker
.length() > 32) {
2252 maker
= maker
.substr (0, 32);
2256 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);
2260 ProcessorBox::on_size_allocate (Allocation
& a
)
2262 HBox::on_size_allocate (a
);
2264 list
<ProcessorEntry
*> children
= processor_display
.children ();
2265 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
2266 (*i
)->set_pixel_width (a
.get_width ());
2270 /** @param p Processor.
2271 * @return the UI window for \a p.
2274 ProcessorBox::get_processor_ui (boost::shared_ptr
<Processor
> p
) const
2276 list
<ProcessorWindowProxy
*>::const_iterator i
= _processor_window_proxies
.begin ();
2277 while (i
!= _processor_window_proxies
.end()) {
2278 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2280 return (*i
)->get ();
2286 /* we shouldn't get here, because the ProcessorUIList should always contain
2287 an entry for each processor.
2293 /** Make a note of the UI window that a processor is using.
2294 * @param p Processor.
2295 * @param w UI window.
2298 ProcessorBox::set_processor_ui (boost::shared_ptr
<Processor
> p
, Gtk::Window
* w
)
2300 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
2304 while (i
!= _processor_window_proxies
.end()) {
2305 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2314 /* we shouldn't get here, because the ProcessorUIList should always contain
2315 an entry for each processor.
2321 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr
<Delivery
> w
)
2323 boost::shared_ptr
<Delivery
> d
= w
.lock ();
2328 list
<ProcessorEntry
*> children
= processor_display
.children ();
2329 list
<ProcessorEntry
*>::const_iterator i
= children
.begin();
2330 while (i
!= children
.end() && (*i
)->processor() != d
) {
2334 if (i
== children
.end()) {
2335 processor_display
.set_active (0);
2337 processor_display
.set_active (*i
);
2342 ProcessorBox::hide_things ()
2344 list
<ProcessorEntry
*> c
= processor_display
.children ();
2345 for (list
<ProcessorEntry
*>::iterator i
= c
.begin(); i
!= c
.end(); ++i
) {
2346 (*i
)->hide_things ();
2350 ProcessorWindowProxy::ProcessorWindowProxy (
2351 string
const & name
,
2352 XMLNode
const * node
,
2354 boost::weak_ptr
<Processor
> processor
2356 : WindowProxy
<Gtk::Window
> (name
, node
)
2358 , _processor_box (box
)
2359 , _processor (processor
)
2366 ProcessorWindowProxy::show ()
2368 boost::shared_ptr
<Processor
> p
= _processor
.lock ();
2373 _processor_box
->toggle_edit_processor (p
);