2 Copyright (C) 2000-2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtk2ardour-config.h"
28 #include <sigc++/bind.h>
30 #include "pbd/convert.h"
32 #include <glibmm/miscutils.h>
34 #include <gtkmm/messagedialog.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/utils.h>
38 #include <gtkmm2ext/choice.h>
39 #include <gtkmm2ext/utils.h>
40 #include <gtkmm2ext/doi.h>
42 #include "ardour/amp.h"
43 #include "ardour/ardour.h"
44 #include "ardour/audio_track.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/internal_send.h"
47 #include "ardour/internal_return.h"
48 #include "ardour/ladspa_plugin.h"
49 #include "ardour/meter.h"
50 #include "ardour/plugin_insert.h"
51 #include "ardour/port_insert.h"
52 #include "ardour/profile.h"
53 #include "ardour/return.h"
54 #include "ardour/route.h"
55 #include "ardour/send.h"
56 #include "ardour/session.h"
57 #include "ardour/dB.h"
60 #include "ardour_dialog.h"
61 #include "ardour_ui.h"
62 #include "gui_thread.h"
63 #include "io_selector.h"
66 #include "mixer_strip.h"
67 #include "plugin_selector.h"
68 #include "plugin_ui.h"
69 #include "port_insert_ui.h"
70 #include "processor_box.h"
71 #include "public_editor.h"
72 #include "return_ui.h"
73 #include "route_processor_selection.h"
79 #ifdef HAVE_AUDIOUNITS
84 using namespace ARDOUR
;
88 using namespace Gtkmm2ext
;
90 ProcessorBox
* ProcessorBox::_current_processor_box
= 0;
91 RefPtr
<Action
> ProcessorBox::paste_action
;
92 RefPtr
<Action
> ProcessorBox::cut_action
;
93 RefPtr
<Action
> ProcessorBox::rename_action
;
94 RefPtr
<Action
> ProcessorBox::edit_action
;
95 Glib::RefPtr
<Gdk::Pixbuf
> SendProcessorEntry::_slider
;
97 ProcessorEntry::ProcessorEntry (boost::shared_ptr
<Processor
> p
, Width w
)
98 : _position (PreFader
)
101 , _visual_state (Gtk::STATE_NORMAL
)
103 _hbox
.pack_start (_active
, false, false);
104 _event_box
.add (_name
);
105 _hbox
.pack_start (_event_box
, true, true);
106 _vbox
.pack_start (_hbox
);
109 /* without this, the border is mis-drawn on some systems */
110 _vbox
.set_border_width (1);
112 _name
.set_alignment (0, 0.5);
113 _name
.set_text (name ());
114 _name
.set_padding (2, 2);
116 if (boost::dynamic_pointer_cast
<Amp
> (p
)) {
117 /* Fader processor gets a special look */
118 _event_box
.set_name ("ProcessorFader");
119 _frame
.set_name ("ProcessorFaderFrame");
120 _name
.set_padding (2, 4);
123 _active
.set_active (_processor
->active ());
124 _active
.signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::active_toggled
));
133 _processor
->ActiveChanged
.connect (active_connection
, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed
, this), gui_context());
134 _processor
->PropertyChanged
.connect (name_connection
, invalidator (*this), ui_bind (&ProcessorEntry::processor_property_changed
, this, _1
), gui_context());
138 ProcessorEntry::action_widget ()
144 ProcessorEntry::widget ()
150 ProcessorEntry::drag_text () const
156 ProcessorEntry::set_visual_state (Gtk::StateType t
)
163 ProcessorEntry::set_position (Position p
)
170 ProcessorEntry::setup_visuals ()
174 _event_box
.set_name ("ProcessorPreFader");
175 if (_visual_state
== Gtk::STATE_NORMAL
) {
176 _frame
.set_name ("ProcessorPreFaderFrame");
181 _event_box
.set_name ("ProcessorFader");
182 if (_visual_state
== Gtk::STATE_NORMAL
) {
183 _frame
.set_name ("ProcessorFaderFrame");
188 _event_box
.set_name ("ProcessorPostFader");
189 if (_visual_state
== Gtk::STATE_NORMAL
) {
190 _frame
.set_name ("ProcessorPostFaderFrame");
195 switch (_visual_state
) {
196 case Gtk::STATE_NORMAL
:
197 /* _frame has been set up above */
198 _event_box
.set_state (Gtk::STATE_NORMAL
);
200 case Gtk::STATE_SELECTED
:
201 _frame
.set_name ("ProcessorFrameSelected");
202 /* don't change the background of the box when it is selected */
203 _event_box
.set_state (Gtk::STATE_NORMAL
);
205 case Gtk::STATE_ACTIVE
:
206 _frame
.set_name ("ProcessorFrameActiveSend");
207 _event_box
.set_state (Gtk::STATE_ACTIVE
);
215 boost::shared_ptr
<Processor
>
216 ProcessorEntry::processor () const
222 ProcessorEntry::set_enum_width (Width w
)
228 ProcessorEntry::active_toggled ()
230 if (_active
.get_active ()) {
231 if (!_processor
->active ()) {
232 _processor
->activate ();
235 if (_processor
->active ()) {
236 _processor
->deactivate ();
242 ProcessorEntry::processor_active_changed ()
244 if (_active
.get_active () != _processor
->active ()) {
245 _active
.set_active (_processor
->active ());
250 ProcessorEntry::processor_property_changed (const PropertyChange
& what_changed
)
252 if (what_changed
.contains (ARDOUR::Properties::name
)) {
253 _name
.set_text (name ());
258 ProcessorEntry::name () const
260 boost::shared_ptr
<Send
> send
;
263 if ((send
= boost::dynamic_pointer_cast
<Send
> (_processor
)) != 0 &&
264 !boost::dynamic_pointer_cast
<InternalSend
>(_processor
)) {
268 /* grab the send name out of its overall name */
270 string::size_type lbracket
, rbracket
;
271 lbracket
= send
->name().find ('[');
272 rbracket
= send
->name().find (']');
276 name_display
+= send
->name().substr (lbracket
+1, lbracket
-rbracket
-1);
279 name_display
+= PBD::short_version (send
->name().substr (lbracket
+1, lbracket
-rbracket
-1), 4);
287 name_display
+= _processor
->display_name();
290 name_display
+= PBD::short_version (_processor
->display_name(), 5);
299 SendProcessorEntry::SendProcessorEntry (boost::shared_ptr
<Send
> s
, Width w
)
300 : ProcessorEntry (s
, w
),
302 /* set the adjustment to a gain of 0dB so that the fader's default value is right */
303 _adjustment (0.781787, 0, 1, 0.01, 0.1),
304 _fader (_slider
, &_adjustment
, 0, false),
305 _ignore_gain_change (false)
307 _fader
.set_name ("SendFader");
308 _fader
.set_controllable (_send
->amp()->gain_control ());
309 _vbox
.pack_start (_fader
);
313 _adjustment
.signal_value_changed().connect (sigc::mem_fun (*this, &SendProcessorEntry::gain_adjusted
));
314 _send
->amp()->gain_control()->Changed
.connect (send_gain_connection
, invalidator (*this), boost::bind (&SendProcessorEntry::show_gain
, this), gui_context());
319 SendProcessorEntry::setup_slider_pix ()
321 _slider
= ::get_icon ("fader_belt_h_thin");
326 SendProcessorEntry::show_gain ()
328 ENSURE_GUI_THREAD (*this, &SendProcessorEntry::show_gain
)
330 float const value
= gain_to_slider_position (_send
->amp()->gain ());
332 if (_adjustment
.get_value() != value
) {
333 _ignore_gain_change
= true;
334 _adjustment
.set_value (value
);
335 _ignore_gain_change
= false;
339 s
.setf (ios::fixed
, ios::floatfield
);
340 s
<< accurate_coefficient_to_dB (_send
->amp()->gain ()) << _("dB");
341 _fader
.set_tooltip_text (s
.str ());
346 SendProcessorEntry::gain_adjusted ()
348 if (_ignore_gain_change
) {
352 _send
->amp()->set_gain (slider_position_to_gain (_adjustment
.get_value()), this);
356 SendProcessorEntry::set_pixel_width (int p
)
358 _fader
.set_fader_length (p
);
361 PluginInsertProcessorEntry::PluginInsertProcessorEntry (boost::shared_ptr
<ARDOUR::PluginInsert
> p
, Width w
)
362 : ProcessorEntry (p
, w
)
365 p
->SplittingChanged
.connect (
366 _splitting_connection
, invalidator (*this), ui_bind (&PluginInsertProcessorEntry::plugin_insert_splitting_changed
, this), gui_context()
369 _splitting_icon
.set_size_request (-1, 12);
371 _vbox
.pack_start (_splitting_icon
);
372 _vbox
.reorder_child (_splitting_icon
, 0);
374 plugin_insert_splitting_changed ();
378 PluginInsertProcessorEntry::plugin_insert_splitting_changed ()
380 if (_plugin_insert
->splitting ()) {
381 _splitting_icon
.show ();
383 _splitting_icon
.hide ();
388 PluginInsertProcessorEntry::hide_things ()
390 plugin_insert_splitting_changed ();
394 PluginInsertProcessorEntry::setup_visuals ()
398 _splitting_icon
.set_name ("ProcessorPreFader");
402 _splitting_icon
.set_name ("ProcessorFader");
406 _splitting_icon
.set_name ("ProcessorPostFader");
410 ProcessorEntry::setup_visuals ();
414 PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose
* ev
)
416 cairo_t
* cr
= gdk_cairo_create (get_window()->gobj());
418 cairo_set_line_width (cr
, 1);
420 double const width
= ev
->area
.width
;
421 double const height
= ev
->area
.height
;
423 Gdk::Color
const bg
= get_style()->get_bg (STATE_NORMAL
);
424 cairo_set_source_rgb (cr
, bg
.get_red_p (), bg
.get_green_p (), bg
.get_blue_p ());
426 cairo_rectangle (cr
, 0, 0, width
, height
);
429 Gdk::Color
const fg
= get_style()->get_fg (STATE_NORMAL
);
430 cairo_set_source_rgb (cr
, fg
.get_red_p (), fg
.get_green_p (), fg
.get_blue_p ());
432 cairo_move_to (cr
, width
* 0.3, height
);
433 cairo_line_to (cr
, width
* 0.3, height
* 0.5);
434 cairo_line_to (cr
, width
* 0.7, height
* 0.5);
435 cairo_line_to (cr
, width
* 0.7, height
);
436 cairo_move_to (cr
, width
* 0.5, height
* 0.5);
437 cairo_line_to (cr
, width
* 0.5, 0);
443 ProcessorBox::ProcessorBox (ARDOUR::Session
* sess
, boost::function
<PluginSelector
*()> get_plugin_selector
,
444 RouteRedirectSelection
& rsel
, MixerStrip
* parent
, bool owner_is_mixer
)
445 : _parent_strip (parent
)
446 , _owner_is_mixer (owner_is_mixer
)
447 , ab_direction (true)
448 , _get_plugin_selector (get_plugin_selector
)
449 , _placement(PreFader
)
450 , _rr_selection(rsel
)
456 send_action_menu
= 0;
457 no_processor_redisplay
= false;
459 processor_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
460 processor_scroller
.add (processor_display
);
461 pack_start (processor_scroller
, true, true);
463 processor_display
.set_flags (CAN_FOCUS
);
464 processor_display
.set_name ("ProcessorList");
465 processor_display
.set_size_request (48, -1);
466 processor_display
.set_data ("processorbox", this);
467 processor_display
.set_spacing (2);
469 processor_display
.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify
), false);
470 processor_display
.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify
), false);
472 processor_display
.signal_key_press_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_press_event
));
473 processor_display
.signal_key_release_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_release_event
));
475 processor_display
.ButtonPress
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event
));
476 processor_display
.ButtonRelease
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event
));
478 processor_display
.Reordered
.connect (sigc::mem_fun (*this, &ProcessorBox::reordered
));
479 processor_display
.DropFromAnotherBox
.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop
));
480 processor_display
.SelectionChanged
.connect (sigc::mem_fun (*this, &ProcessorBox::selection_changed
));
482 processor_scroller
.show ();
483 processor_display
.show ();
486 parent
->DeliveryChanged
.connect (
487 _mixer_strip_connections
, invalidator (*this), ui_bind (&ProcessorBox::mixer_strip_delivery_changed
, this, _1
), gui_context ()
492 ProcessorBox::~ProcessorBox ()
497 ProcessorBox::set_route (boost::shared_ptr
<Route
> r
)
503 _route_connections
.drop_connections();
505 /* new route: any existing block on processor redisplay must be meaningless */
506 no_processor_redisplay
= false;
509 _route
->processors_changed
.connect (
510 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_processors_changed
, this, _1
), gui_context()
513 _route
->DropReferences
.connect (
514 _route_connections
, invalidator (*this), boost::bind (&ProcessorBox::route_going_away
, this), gui_context()
517 _route
->PropertyChanged
.connect (
518 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_property_changed
, this, _1
), gui_context()
521 redisplay_processors ();
525 ProcessorBox::route_going_away ()
527 /* don't keep updating display as processors are deleted */
528 no_processor_redisplay
= true;
532 ProcessorBox::object_drop(DnDVBox
<ProcessorEntry
>* source
, ProcessorEntry
* position
, Glib::RefPtr
<Gdk::DragContext
> const & context
)
534 boost::shared_ptr
<Processor
> p
;
536 p
= position
->processor ();
539 list
<ProcessorEntry
*> children
= source
->selection ();
540 list
<boost::shared_ptr
<Processor
> > procs
;
541 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
542 procs
.push_back ((*i
)->processor ());
545 for (list
<boost::shared_ptr
<Processor
> >::const_iterator i
= procs
.begin(); i
!= procs
.end(); ++i
) {
546 XMLNode
& state
= (*i
)->get_state ();
548 nlist
.push_back (&state
);
549 paste_processor_state (nlist
, p
);
553 /* since the dndvbox doesn't take care of this properly, we have to delete the originals
557 if ((context
->get_suggested_action() == Gdk::ACTION_MOVE
) && source
) {
558 ProcessorBox
* other
= reinterpret_cast<ProcessorBox
*> (source
->get_data ("processorbox"));
560 cerr
<< "source was another processor box, delete the selected items\n";
561 other
->delete_dragged_processors (procs
);
567 ProcessorBox::update()
569 redisplay_processors ();
573 ProcessorBox::set_width (Width w
)
581 list
<ProcessorEntry
*> children
= processor_display
.children ();
582 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
583 (*i
)->set_enum_width (w
);
586 redisplay_processors ();
590 ProcessorBox::build_send_action_menu ()
592 using namespace Menu_Helpers
;
594 send_action_menu
= new Menu
;
595 send_action_menu
->set_name ("ArdourContextMenu");
596 MenuList
& items
= send_action_menu
->items();
598 items
.push_back (MenuElem (_("New send"), sigc::mem_fun(*this, &ProcessorBox::new_send
)));
599 items
.push_back (MenuElem (_("Show send controls"), sigc::mem_fun(*this, &ProcessorBox::show_send_controls
)));
603 ProcessorBox::build_possible_aux_menu ()
605 boost::shared_ptr
<RouteList
> rl
= _session
->get_routes_with_internal_returns();
611 using namespace Menu_Helpers
;
612 Menu
* menu
= manage (new Menu
);
613 MenuList
& items
= menu
->items();
615 for (RouteList::iterator r
= rl
->begin(); r
!= rl
->end(); ++r
) {
616 if (!_route
->internal_send_for (*r
) && *r
!= _route
) {
617 items
.push_back (MenuElem ((*r
)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux
), boost::weak_ptr
<Route
>(*r
))));
625 ProcessorBox::show_send_controls ()
630 ProcessorBox::new_send ()
635 ProcessorBox::show_processor_menu (gint arg
)
637 if (processor_menu
== 0) {
638 processor_menu
= build_processor_menu ();
641 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/processormenu/newplugin"));
643 if (plugin_menu_item
) {
644 plugin_menu_item
->set_submenu (*_get_plugin_selector()->plugin_menu());
647 Gtk::MenuItem
* aux_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/processormenu/newaux"));
650 Menu
* m
= build_possible_aux_menu();
651 if (m
&& !m
->items().empty()) {
652 aux_menu_item
->set_submenu (*m
);
653 aux_menu_item
->set_sensitive (true);
655 /* stupid gtkmm: we need to pass a null reference here */
656 gtk_menu_item_set_submenu (aux_menu_item
->gobj(), 0);
657 aux_menu_item
->set_sensitive (false);
661 cut_action
->set_sensitive (can_cut());
662 paste_action
->set_sensitive (!_rr_selection
.processors
.empty());
664 processor_menu
->popup (1, arg
);
668 ProcessorBox::enter_notify (GdkEventCrossing
*)
670 _current_processor_box
= this;
671 Keyboard::magic_widget_grab_focus ();
672 processor_display
.grab_focus ();
678 ProcessorBox::leave_notify (GdkEventCrossing
* ev
)
680 switch (ev
->detail
) {
681 case GDK_NOTIFY_INFERIOR
:
684 Keyboard::magic_widget_drop_focus ();
691 ProcessorBox::processor_key_press_event (GdkEventKey
*)
693 /* do real stuff on key release */
698 ProcessorBox::processor_key_release_event (GdkEventKey
*ev
)
701 ProcSelection targets
;
703 get_selected_processors (targets
);
705 if (targets
.empty()) {
708 processor_display
.get_pointer (x
, y
);
710 pair
<ProcessorEntry
*, double> const pointer
= processor_display
.get_child_at_position (y
);
713 targets
.push_back (pointer
.first
->processor ());
718 switch (ev
->keyval
) {
720 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
721 processor_display
.select_all ();
727 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
728 copy_processors (targets
);
734 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
735 cut_processors (targets
);
741 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
742 if (targets
.empty()) {
745 paste_processors (targets
.front());
759 delete_processors (targets
);
764 for (ProcSelection::iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
765 if ((*i
)->active()) {
787 ProcessorBox::processor_button_press_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
789 boost::shared_ptr
<Processor
> processor
;
791 processor
= child
->processor ();
795 bool selected
= processor_display
.selected (child
);
797 if (processor
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
799 if (_session
->engine().connected()) {
800 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
801 toggle_edit_processor (processor
);
805 } else if (processor
&& ev
->button
== 1 && selected
) {
807 // this is purely informational but necessary for route params UI
808 ProcessorSelected (processor
); // emit
810 } else if (!processor
&& ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
) {
813 _get_plugin_selector()->show_manager ();
820 ProcessorBox::processor_button_release_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
822 boost::shared_ptr
<Processor
> processor
;
824 processor
= child
->processor ();
829 if (processor
&& Keyboard::is_delete_event (ev
)) {
831 Glib::signal_idle().connect (sigc::bind (
832 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor
),
833 boost::weak_ptr
<Processor
>(processor
)));
836 } else if (Keyboard::is_context_menu_event (ev
)) {
838 /* figure out if we are above or below the fader/amp processor,
839 and set the next insert position appropriately.
843 if (_route
->processor_is_prefader (processor
)) {
844 _placement
= PreFader
;
846 _placement
= PostFader
;
849 _placement
= PostFader
;
852 show_processor_menu (ev
->time
);
855 } else if (processor
&& Keyboard::is_button2_event (ev
)
857 && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))
861 /* button2-click with no/appropriate modifiers */
863 if (processor
->active()) {
864 processor
->deactivate ();
866 processor
->activate ();
876 ProcessorBox::build_processor_menu ()
878 processor_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/processormenu") );
879 processor_menu
->set_name ("ArdourContextMenu");
880 return processor_menu
;
884 ProcessorBox::selection_changed ()
886 bool const sensitive
= (processor_display
.selection().empty()) ? false : true;
887 ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions
, sensitive
);
888 edit_action
->set_sensitive (one_processor_can_be_edited ());
890 /* disallow rename for multiple selections and for plugin inserts */
891 rename_action
->set_sensitive (
892 processor_display
.selection().size() == 1 && boost::dynamic_pointer_cast
<PluginInsert
> (processor_display
.selection().front()->processor()) == 0
897 ProcessorBox::select_all_processors ()
899 processor_display
.select_all ();
903 ProcessorBox::deselect_all_processors ()
905 processor_display
.select_none ();
909 ProcessorBox::choose_plugin ()
911 _get_plugin_selector()->set_interested_object (*this);
914 /** @return true if an error occurred, otherwise false */
916 ProcessorBox::use_plugins (const SelectedPlugins
& plugins
)
918 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
920 boost::shared_ptr
<Processor
> processor (new PluginInsert (*_session
, *p
));
922 Route::ProcessorStreams err_streams
;
924 if (Config
->get_new_plugins_active()) {
925 processor
->activate ();
928 if (_route
->add_processor (processor
, _placement
, &err_streams
)) {
929 weird_plugin_dialog (**p
, err_streams
);
931 // XXX SHAREDPTR delete plugin here .. do we even need to care?
934 if (Profile
->get_sae()) {
935 processor
->activate ();
944 ProcessorBox::weird_plugin_dialog (Plugin
& p
, Route::ProcessorStreams streams
)
946 ArdourDialog
dialog (_("Plugin Incompatibility"));
949 string text
= string_compose(_("You attempted to add the plugin \"%1\" at index %2.\n"),
950 p
.name(), streams
.index
);
952 bool has_midi
= streams
.count
.n_midi() > 0 || p
.get_info()->n_inputs
.n_midi() > 0;
953 bool has_audio
= streams
.count
.n_audio() > 0 || p
.get_info()->n_inputs
.n_audio() > 0;
955 text
+= _("\nThis plugin has:\n");
957 uint32_t const n
= p
.get_info()->n_inputs
.n_midi ();
958 text
+= string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n
), n
);
961 uint32_t const n
= p
.get_info()->n_inputs
.n_audio ();
962 text
+= string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n
), n
);
965 text
+= _("\nbut at the insertion point, there are:\n");
967 uint32_t const n
= streams
.count
.n_midi ();
968 text
+= string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n
), n
);
971 uint32_t const n
= streams
.count
.n_audio ();
972 text
+= string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n
), n
);
975 text
+= string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME
);
976 label
.set_text(text
);
978 dialog
.get_vbox()->pack_start (label
);
979 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
981 dialog
.set_name (X_("PluginIODialog"));
982 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
983 dialog
.set_modal (true);
990 ProcessorBox::choose_insert ()
992 boost::shared_ptr
<Processor
> processor (new PortInsert (*_session
, _route
->pannable(), _route
->mute_master()));
993 _route
->add_processor (processor
, _placement
);
996 /* Caller must not hold process lock */
998 ProcessorBox::choose_send ()
1000 boost::shared_ptr
<Send
> send (new Send (*_session
, _route
->pannable(), _route
->mute_master()));
1002 /* make an educated guess at the initial number of outputs for the send */
1003 ChanCount outs
= (_session
->master_out())
1004 ? _session
->master_out()->n_outputs()
1005 : _route
->n_outputs();
1007 /* XXX need processor lock on route */
1009 Glib::Mutex::Lock
lm (AudioEngine::instance()->process_lock());
1010 send
->output()->ensure_io (outs
, false, this);
1011 } catch (AudioEngine::PortRegistrationFailure
& err
) {
1012 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
1016 /* let the user adjust the IO setup before creation.
1018 Note: this dialog is NOT modal - we just leave it to run and it will
1019 return when its Finished signal is emitted - typically when the window
1023 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
->output(), true);
1026 /* keep a reference to the send so it doesn't get deleted while
1027 the IOSelectorWindow is doing its stuff
1029 _processor_being_created
= send
;
1031 ios
->selector().Finished
.connect (sigc::bind (
1032 sigc::mem_fun(*this, &ProcessorBox::send_io_finished
),
1033 boost::weak_ptr
<Processor
>(send
), ios
));
1038 ProcessorBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1040 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1042 /* drop our temporary reference to the new send */
1043 _processor_being_created
.reset ();
1050 case IOSelector::Cancelled
:
1051 // processor will go away when all shared_ptrs to it vanish
1054 case IOSelector::Accepted
:
1055 _route
->add_processor (processor
, _placement
);
1056 if (Profile
->get_sae()) {
1057 processor
->activate ();
1062 delete_when_idle (ios
);
1066 ProcessorBox::return_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1068 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1070 /* drop our temporary reference to the new return */
1071 _processor_being_created
.reset ();
1078 case IOSelector::Cancelled
:
1079 // processor will go away when all shared_ptrs to it vanish
1082 case IOSelector::Accepted
:
1083 _route
->add_processor (processor
, _placement
);
1084 if (Profile
->get_sae()) {
1085 processor
->activate ();
1090 delete_when_idle (ios
);
1094 ProcessorBox::choose_aux (boost::weak_ptr
<Route
> wr
)
1100 boost::shared_ptr
<Route
> target
= wr
.lock();
1106 boost::shared_ptr
<RouteList
> rlist (new RouteList
);
1107 rlist
->push_back (_route
);
1109 _session
->add_internal_sends (target
, PreFader
, rlist
);
1113 ProcessorBox::route_processors_changed (RouteProcessorChange c
)
1115 if (c
.type
== RouteProcessorChange::MeterPointChange
&& c
.meter_visibly_changed
== false) {
1116 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1120 redisplay_processors ();
1124 ProcessorBox::redisplay_processors ()
1126 ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors
)
1128 if (no_processor_redisplay
) {
1132 processor_display
.clear ();
1134 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display
));
1136 for (list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin(); i
!= _processor_window_proxies
.end(); ++i
) {
1137 (*i
)->marked
= false;
1140 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list
));
1142 /* trim dead wood from the processor window proxy list */
1144 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin();
1145 while (i
!= _processor_window_proxies
.end()) {
1146 list
<ProcessorWindowProxy
*>::iterator j
= i
;
1149 if (!(*i
)->marked
) {
1150 ARDOUR_UI::instance()->remove_window_proxy (*i
);
1152 _processor_window_proxies
.erase (i
);
1158 setup_entry_positions ();
1161 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
1162 * not already have one.
1165 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr
<Processor
> w
)
1167 boost::shared_ptr
<Processor
> p
= w
.lock ();
1172 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
1173 while (i
!= _processor_window_proxies
.end()) {
1175 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
1178 /* this processor is already on the list; done */
1179 (*i
)->marked
= true;
1186 /* not on the list; add it */
1189 if (_parent_strip
) {
1190 if (_parent_strip
->mixer_owned()) {
1199 ProcessorWindowProxy
* wp
= new ProcessorWindowProxy (
1200 string_compose ("%1-%2-%3", loc
, _route
->id(), p
->id()),
1201 _session
->extra_xml (X_("UI")),
1207 /* if the processor already has an existing UI,
1208 note that so that we don't recreate it
1211 void* existing_ui
= p
->get_ui ();
1214 wp
->set (static_cast<Gtk::Window
*>(existing_ui
));
1217 _processor_window_proxies
.push_back (wp
);
1218 ARDOUR_UI::instance()->add_window_proxy (wp
);
1222 ProcessorBox::add_processor_to_display (boost::weak_ptr
<Processor
> p
)
1224 boost::shared_ptr
<Processor
> processor (p
.lock ());
1226 if (!processor
|| !processor
->display_to_user()) {
1230 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (processor
);
1231 boost::shared_ptr
<PluginInsert
> plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
);
1232 ProcessorEntry
* e
= 0;
1234 e
= new SendProcessorEntry (send
, _width
);
1235 } else if (plugin_insert
) {
1236 e
= new PluginInsertProcessorEntry (plugin_insert
, _width
);
1238 e
= new ProcessorEntry (processor
, _width
);
1241 e
->set_pixel_width (get_allocation().get_width());
1242 processor_display
.add_child (e
);
1247 ProcessorBox::build_processor_tooltip (EventBox
& box
, string start
)
1251 list
<ProcessorEntry
*> children
= processor_display
.children ();
1252 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1254 tip
+= (*i
)->processor()->name();
1257 ARDOUR_UI::instance()->set_tip (box
, tip
);
1261 ProcessorBox::reordered ()
1263 compute_processor_sort_keys ();
1264 setup_entry_positions ();
1268 ProcessorBox::setup_entry_positions ()
1270 list
<ProcessorEntry
*> children
= processor_display
.children ();
1271 bool pre_fader
= true;
1273 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1274 if (boost::dynamic_pointer_cast
<Amp
>((*i
)->processor())) {
1276 (*i
)->set_position (ProcessorEntry::Fader
);
1279 (*i
)->set_position (ProcessorEntry::PreFader
);
1281 (*i
)->set_position (ProcessorEntry::PostFader
);
1288 ProcessorBox::compute_processor_sort_keys ()
1290 list
<ProcessorEntry
*> children
= processor_display
.children ();
1291 Route::ProcessorList our_processors
;
1293 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1294 our_processors
.push_back ((*iter
)->processor ());
1297 if (_route
->reorder_processors (our_processors
)) {
1298 /* Reorder failed, so report this to the user. As far as I can see this must be done
1299 in an idle handler: it seems that the redisplay_processors() that happens below destroys
1300 widgets that were involved in the drag-and-drop on the processor list, which causes problems
1301 when the drag is torn down after this handler function is finished.
1303 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder
));
1308 ProcessorBox::report_failed_reorder ()
1310 /* reorder failed, so redisplay */
1312 redisplay_processors ();
1314 /* now tell them about the problem */
1316 ArdourDialog
dialog (_("Plugin Incompatibility"));
1319 label
.set_text (_("\
1320 You cannot reorder these plugins/sends/inserts\n\
1321 in that way because the inputs and\n\
1322 outputs will not work correctly."));
1324 dialog
.get_vbox()->set_border_width (12);
1325 dialog
.get_vbox()->pack_start (label
);
1326 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
1328 dialog
.set_name (X_("PluginIODialog"));
1329 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1330 dialog
.set_modal (true);
1337 ProcessorBox::rename_processors ()
1339 ProcSelection to_be_renamed
;
1341 get_selected_processors (to_be_renamed
);
1343 if (to_be_renamed
.empty()) {
1347 for (ProcSelection::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
1348 rename_processor (*i
);
1353 ProcessorBox::can_cut () const
1355 vector
<boost::shared_ptr
<Processor
> > sel
;
1357 get_selected_processors (sel
);
1359 /* cut_processors () does not cut inserts */
1361 for (vector
<boost::shared_ptr
<Processor
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
1363 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1364 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1365 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1374 ProcessorBox::cut_processors ()
1376 ProcSelection to_be_removed
;
1378 get_selected_processors (to_be_removed
);
1382 ProcessorBox::cut_processors (const ProcSelection
& to_be_removed
)
1384 if (to_be_removed
.empty()) {
1388 XMLNode
* node
= new XMLNode (X_("cut"));
1389 Route::ProcessorList to_cut
;
1391 no_processor_redisplay
= true;
1392 for (ProcSelection::const_iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
1393 // Cut only plugins, sends and returns
1394 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1395 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1396 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1398 Window
* w
= get_processor_ui (*i
);
1404 XMLNode
& child ((*i
)->get_state());
1405 node
->add_child_nocopy (child
);
1406 to_cut
.push_back (*i
);
1410 if (_route
->remove_processors (to_cut
) != 0) {
1412 no_processor_redisplay
= false;
1416 _rr_selection
.set (node
);
1418 no_processor_redisplay
= false;
1419 redisplay_processors ();
1423 ProcessorBox::copy_processors ()
1425 ProcSelection to_be_copied
;
1426 get_selected_processors (to_be_copied
);
1427 copy_processors (to_be_copied
);
1431 ProcessorBox::copy_processors (const ProcSelection
& to_be_copied
)
1433 if (to_be_copied
.empty()) {
1437 XMLNode
* node
= new XMLNode (X_("copy"));
1439 for (ProcSelection::const_iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
1440 // Copy only plugins, sends, returns
1441 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1442 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1443 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1444 node
->add_child_nocopy ((*i
)->get_state());
1448 _rr_selection
.set (node
);
1452 ProcessorBox::delete_processors ()
1454 ProcSelection to_be_deleted
;
1455 get_selected_processors (to_be_deleted
);
1456 delete_processors (to_be_deleted
);
1460 ProcessorBox::delete_processors (const ProcSelection
& targets
)
1462 if (targets
.empty()) {
1466 no_processor_redisplay
= true;
1468 for (ProcSelection::const_iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
1470 Window
* w
= get_processor_ui (*i
);
1476 _route
->remove_processor(*i
);
1479 no_processor_redisplay
= false;
1480 redisplay_processors ();
1484 ProcessorBox::delete_dragged_processors (const list
<boost::shared_ptr
<Processor
> >& procs
)
1486 list
<boost::shared_ptr
<Processor
> >::const_iterator x
;
1488 no_processor_redisplay
= true;
1489 for (x
= procs
.begin(); x
!= procs
.end(); ++x
) {
1491 Window
* w
= get_processor_ui (*x
);
1497 _route
->remove_processor(*x
);
1500 no_processor_redisplay
= false;
1501 redisplay_processors ();
1505 ProcessorBox::idle_delete_processor (boost::weak_ptr
<Processor
> weak_processor
)
1507 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1513 /* NOT copied to _mixer.selection() */
1515 no_processor_redisplay
= true;
1516 _route
->remove_processor (processor
);
1517 no_processor_redisplay
= false;
1518 redisplay_processors ();
1524 ProcessorBox::rename_processor (boost::shared_ptr
<Processor
> processor
)
1526 ArdourPrompter
name_prompter (true);
1528 name_prompter
.set_title (_("Rename Processor"));
1529 name_prompter
.set_prompt (_("New name:"));
1530 name_prompter
.set_initial_text (processor
->name());
1531 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
1532 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1533 name_prompter
.show_all ();
1535 switch (name_prompter
.run ()) {
1537 case Gtk::RESPONSE_ACCEPT
:
1538 name_prompter
.get_result (result
);
1539 if (result
.length()) {
1542 string test
= result
;
1544 while (tries
< 100) {
1545 if (_session
->io_name_is_legal (test
)) {
1551 test
= string_compose ("%1-%2", result
, tries
);
1555 processor
->set_name (result
);
1558 ARDOUR_UI::instance()->popup_error
1559 (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result
));
1569 ProcessorBox::paste_processors ()
1571 if (_rr_selection
.processors
.empty()) {
1575 paste_processor_state (_rr_selection
.processors
.get_node().children(), boost::shared_ptr
<Processor
>());
1579 ProcessorBox::paste_processors (boost::shared_ptr
<Processor
> before
)
1582 if (_rr_selection
.processors
.empty()) {
1586 paste_processor_state (_rr_selection
.processors
.get_node().children(), before
);
1590 ProcessorBox::paste_processor_state (const XMLNodeList
& nlist
, boost::shared_ptr
<Processor
> p
)
1592 XMLNodeConstIterator niter
;
1593 list
<boost::shared_ptr
<Processor
> > copies
;
1595 if (nlist
.empty()) {
1599 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1601 XMLProperty
const * type
= (*niter
)->property ("type");
1604 boost::shared_ptr
<Processor
> p
;
1606 if (type
->value() == "meter" ||
1607 type
->value() == "main-outs" ||
1608 type
->value() == "amp" ||
1609 type
->value() == "intsend" || type
->value() == "intreturn") {
1610 /* do not paste meter, main outs, amp or internal send/returns */
1613 } else if (type
->value() == "send") {
1615 XMLNode
n (**niter
);
1616 Send::make_unique (n
, *_session
);
1617 Send
* s
= new Send (*_session
, _route
->pannable(), _route
->mute_master());
1618 if (s
->set_state (n
, Stateful::loading_state_version
)) {
1626 } else if (type
->value() == "return") {
1628 XMLNode
n (**niter
);
1629 Return::make_unique (n
, *_session
);
1630 Return
* r
= new Return (*_session
);
1632 if (r
->set_state (n
, Stateful::loading_state_version
)) {
1640 /* XXX its a bit limiting to assume that everything else
1644 p
.reset (new PluginInsert (*_session
));
1645 p
->set_state (**niter
, Stateful::current_state_version
);
1648 copies
.push_back (p
);
1652 cerr
<< "plugin insert constructor failed\n";
1656 if (copies
.empty()) {
1660 if (_route
->add_processors (copies
, p
)) {
1663 "Copying the set of processors on the clipboard failed,\n\
1664 probably because the I/O configuration of the plugins\n\
1665 could not match the configuration of this track.");
1666 MessageDialog
am (msg
);
1672 ProcessorBox::activate_processor (boost::shared_ptr
<Processor
> r
)
1678 ProcessorBox::deactivate_processor (boost::shared_ptr
<Processor
> r
)
1684 ProcessorBox::get_selected_processors (ProcSelection
& processors
) const
1686 const list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1687 for (list
<ProcessorEntry
*>::const_iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1688 processors
.push_back ((*i
)->processor ());
1693 ProcessorBox::for_selected_processors (void (ProcessorBox::*method
)(boost::shared_ptr
<Processor
>))
1695 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1696 for (list
<ProcessorEntry
*>::iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1697 (this->*method
) ((*i
)->processor ());
1702 ProcessorBox::all_processors_active (bool state
)
1704 _route
->all_processors_active (_placement
, state
);
1708 ProcessorBox::ab_plugins ()
1710 _route
->ab_plugins (ab_direction
);
1711 ab_direction
= !ab_direction
;
1716 ProcessorBox::clear_processors ()
1719 vector
<string
> choices
;
1721 prompt
= string_compose (_("Do you really want to remove all processors from %1?\n"
1722 "(this cannot be undone)"), _route
->name());
1724 choices
.push_back (_("Cancel"));
1725 choices
.push_back (_("Yes, remove them all"));
1727 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1729 if (prompter
.run () == 1) {
1730 _route
->clear_processors (PreFader
);
1731 _route
->clear_processors (PostFader
);
1736 ProcessorBox::clear_processors (Placement p
)
1739 vector
<string
> choices
;
1741 if (p
== PreFader
) {
1742 prompt
= string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1743 "(this cannot be undone)"), _route
->name());
1745 prompt
= string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1746 "(this cannot be undone)"), _route
->name());
1749 choices
.push_back (_("Cancel"));
1750 choices
.push_back (_("Yes, remove them all"));
1752 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1754 if (prompter
.run () == 1) {
1755 _route
->clear_processors (p
);
1760 ProcessorBox::processor_can_be_edited (boost::shared_ptr
<Processor
> processor
)
1762 boost::shared_ptr
<AudioTrack
> at
= boost::dynamic_pointer_cast
<AudioTrack
> (_route
);
1763 if (at
&& at
->freeze_state() == AudioTrack::Frozen
) {
1768 boost::dynamic_pointer_cast
<Send
> (processor
) ||
1769 boost::dynamic_pointer_cast
<Return
> (processor
) ||
1770 boost::dynamic_pointer_cast
<PluginInsert
> (processor
) ||
1771 boost::dynamic_pointer_cast
<PortInsert
> (processor
)
1780 ProcessorBox::one_processor_can_be_edited ()
1782 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1783 list
<ProcessorEntry
*>::iterator i
= selection
.begin();
1784 while (i
!= selection
.end() && processor_can_be_edited ((*i
)->processor()) == false) {
1788 return (i
!= selection
.end());
1792 ProcessorBox::toggle_edit_processor (boost::shared_ptr
<Processor
> processor
)
1794 boost::shared_ptr
<Send
> send
;
1795 boost::shared_ptr
<InternalSend
> internal_send
;
1796 boost::shared_ptr
<Return
> retrn
;
1797 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1798 boost::shared_ptr
<PortInsert
> port_insert
;
1801 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1803 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1808 if (boost::dynamic_pointer_cast
<Amp
> (processor
)) {
1810 _parent_strip
->revert_to_default_display ();
1812 } else if ((internal_send
= boost::dynamic_pointer_cast
<InternalSend
> (processor
)) != 0) {
1814 if (!_session
->engine().connected()) {
1818 if (_parent_strip
) {
1819 if (boost::dynamic_pointer_cast
<Send
> (_parent_strip
->current_delivery()) == internal_send
) {
1820 _parent_strip
->revert_to_default_display ();
1822 _parent_strip
->show_send (internal_send
);
1826 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
1828 if (!_session
->engine().connected()) {
1832 SendUIWindow
* w
= new SendUIWindow (send
, _session
);
1835 } else if ((retrn
= boost::dynamic_pointer_cast
<Return
> (processor
)) != 0) {
1837 if (boost::dynamic_pointer_cast
<InternalReturn
> (retrn
)) {
1838 /* no GUI for these */
1842 if (!_session
->engine().connected()) {
1846 boost::shared_ptr
<Return
> retrn
= boost::dynamic_pointer_cast
<Return
> (processor
);
1848 ReturnUIWindow
*return_ui
;
1849 Window
* w
= get_processor_ui (retrn
);
1853 return_ui
= new ReturnUIWindow (retrn
, _session
);
1854 return_ui
->set_title (retrn
->name ());
1855 set_processor_ui (send
, return_ui
);
1858 return_ui
= dynamic_cast<ReturnUIWindow
*> (w
);
1863 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
1865 PluginUIWindow
*plugin_ui
;
1867 /* these are both allowed to be null */
1869 Container
* toplevel
= get_toplevel();
1870 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1872 Window
* w
= get_processor_ui (plugin_insert
);
1876 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1877 plugin_ui
->set_title (generate_processor_title (plugin_insert
));
1878 set_processor_ui (plugin_insert
, plugin_ui
);
1881 plugin_ui
= dynamic_cast<PluginUIWindow
*> (w
);
1882 plugin_ui
->set_parent (win
);
1887 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (processor
)) != 0) {
1889 if (!_session
->engine().connected()) {
1890 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1895 PortInsertWindow
*io_selector
;
1897 Window
* w
= get_processor_ui (port_insert
);
1900 io_selector
= new PortInsertWindow (_session
, port_insert
);
1901 set_processor_ui (port_insert
, io_selector
);
1904 io_selector
= dynamic_cast<PortInsertWindow
*> (w
);
1907 gidget
= io_selector
;
1911 if (gidget
->is_visible()) {
1914 gidget
->show_all ();
1921 ProcessorBox::register_actions ()
1923 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("processormenu"));
1924 Glib::RefPtr
<Action
> act
;
1927 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"),
1928 sigc::ptr_fun (ProcessorBox::rb_choose_plugin
));
1930 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"),
1931 sigc::ptr_fun (ProcessorBox::rb_choose_insert
));
1932 ActionManager::jack_sensitive_actions
.push_back (act
);
1933 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."),
1934 sigc::ptr_fun (ProcessorBox::rb_choose_send
));
1935 ActionManager::jack_sensitive_actions
.push_back (act
);
1937 ActionManager::register_action (popup_act_grp
, X_("newaux"), _("New Aux Send ..."));
1939 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear (all)"),
1940 sigc::ptr_fun (ProcessorBox::rb_clear
));
1941 ActionManager::register_action (popup_act_grp
, X_("clear_pre"), _("Clear (pre-fader)"),
1942 sigc::ptr_fun (ProcessorBox::rb_clear_pre
));
1943 ActionManager::register_action (popup_act_grp
, X_("clear_post"), _("Clear (post-fader)"),
1944 sigc::ptr_fun (ProcessorBox::rb_clear_post
));
1946 /* standard editing stuff */
1947 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"),
1948 sigc::ptr_fun (ProcessorBox::rb_cut
));
1949 ActionManager::plugin_selection_sensitive_actions
.push_back(cut_action
);
1950 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"),
1951 sigc::ptr_fun (ProcessorBox::rb_copy
));
1952 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1954 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"),
1955 sigc::ptr_fun (ProcessorBox::rb_delete
));
1956 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1958 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"),
1959 sigc::ptr_fun (ProcessorBox::rb_paste
));
1960 rename_action
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"),
1961 sigc::ptr_fun (ProcessorBox::rb_rename
));
1962 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"),
1963 sigc::ptr_fun (ProcessorBox::rb_select_all
));
1964 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"),
1965 sigc::ptr_fun (ProcessorBox::rb_deselect_all
));
1967 /* activation etc. */
1969 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"),
1970 sigc::ptr_fun (ProcessorBox::rb_activate_all
));
1971 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"),
1972 sigc::ptr_fun (ProcessorBox::rb_deactivate_all
));
1973 ActionManager::register_action (popup_act_grp
, X_("ab_plugins"), _("A/B Plugins"),
1974 sigc::ptr_fun (ProcessorBox::rb_ab_plugins
));
1977 edit_action
= ActionManager::register_action (popup_act_grp
, X_("edit"), _("Edit..."),
1978 sigc::ptr_fun (ProcessorBox::rb_edit
));
1980 ActionManager::add_action_group (popup_act_grp
);
1984 ProcessorBox::rb_ab_plugins ()
1986 if (_current_processor_box
== 0) {
1990 _current_processor_box
->ab_plugins ();
1994 ProcessorBox::rb_choose_plugin ()
1996 if (_current_processor_box
== 0) {
1999 _current_processor_box
->choose_plugin ();
2003 ProcessorBox::rb_choose_insert ()
2005 if (_current_processor_box
== 0) {
2008 _current_processor_box
->choose_insert ();
2012 ProcessorBox::rb_choose_send ()
2014 if (_current_processor_box
== 0) {
2017 _current_processor_box
->choose_send ();
2021 ProcessorBox::rb_choose_aux (boost::weak_ptr
<Route
> wr
)
2023 if (_current_processor_box
== 0) {
2027 _current_processor_box
->choose_aux (wr
);
2031 ProcessorBox::rb_clear ()
2033 if (_current_processor_box
== 0) {
2037 _current_processor_box
->clear_processors ();
2042 ProcessorBox::rb_clear_pre ()
2044 if (_current_processor_box
== 0) {
2048 _current_processor_box
->clear_processors (PreFader
);
2053 ProcessorBox::rb_clear_post ()
2055 if (_current_processor_box
== 0) {
2059 _current_processor_box
->clear_processors (PostFader
);
2063 ProcessorBox::rb_cut ()
2065 if (_current_processor_box
== 0) {
2069 _current_processor_box
->cut_processors ();
2073 ProcessorBox::rb_delete ()
2075 if (_current_processor_box
== 0) {
2079 _current_processor_box
->delete_processors ();
2083 ProcessorBox::rb_copy ()
2085 if (_current_processor_box
== 0) {
2088 _current_processor_box
->copy_processors ();
2092 ProcessorBox::rb_paste ()
2094 if (_current_processor_box
== 0) {
2098 _current_processor_box
->paste_processors ();
2102 ProcessorBox::rb_rename ()
2104 if (_current_processor_box
== 0) {
2107 _current_processor_box
->rename_processors ();
2111 ProcessorBox::rb_select_all ()
2113 if (_current_processor_box
== 0) {
2117 _current_processor_box
->select_all_processors ();
2121 ProcessorBox::rb_deselect_all ()
2123 if (_current_processor_box
== 0) {
2127 _current_processor_box
->deselect_all_processors ();
2131 ProcessorBox::rb_activate_all ()
2133 if (_current_processor_box
== 0) {
2137 _current_processor_box
->all_processors_active (true);
2141 ProcessorBox::rb_deactivate_all ()
2143 if (_current_processor_box
== 0) {
2146 _current_processor_box
->all_processors_active (false);
2150 ProcessorBox::rb_edit ()
2152 if (_current_processor_box
== 0) {
2156 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_edit_processor
);
2160 ProcessorBox::route_property_changed (const PropertyChange
& what_changed
)
2162 if (!what_changed
.contains (ARDOUR::Properties::name
)) {
2166 ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed
, what_changed
);
2168 boost::shared_ptr
<Processor
> processor
;
2169 boost::shared_ptr
<PluginInsert
> plugin_insert
;
2170 boost::shared_ptr
<Send
> send
;
2172 list
<ProcessorEntry
*> children
= processor_display
.children();
2174 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
2176 processor
= (*iter
)->processor ();
2178 Window
* w
= get_processor_ui (processor
);
2184 /* rename editor windows for sends and plugins */
2186 if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
2187 w
->set_title (send
->name ());
2188 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
2189 w
->set_title (generate_processor_title (plugin_insert
));
2195 ProcessorBox::generate_processor_title (boost::shared_ptr
<PluginInsert
> pi
)
2197 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
2198 string::size_type email_pos
;
2200 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
2201 maker
= maker
.substr (0, email_pos
- 1);
2204 if (maker
.length() > 32) {
2205 maker
= maker
.substr (0, 32);
2209 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);
2213 ProcessorBox::on_size_allocate (Allocation
& a
)
2215 HBox::on_size_allocate (a
);
2217 list
<ProcessorEntry
*> children
= processor_display
.children ();
2218 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
2219 (*i
)->set_pixel_width (a
.get_width ());
2223 /** @param p Processor.
2224 * @return the UI window for \a p.
2227 ProcessorBox::get_processor_ui (boost::shared_ptr
<Processor
> p
) const
2229 list
<ProcessorWindowProxy
*>::const_iterator i
= _processor_window_proxies
.begin ();
2230 while (i
!= _processor_window_proxies
.end()) {
2231 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2233 return (*i
)->get ();
2239 /* we shouldn't get here, because the ProcessorUIList should always contain
2240 an entry for each processor.
2246 /** Make a note of the UI window that a processor is using.
2247 * @param p Processor.
2248 * @param w UI window.
2251 ProcessorBox::set_processor_ui (boost::shared_ptr
<Processor
> p
, Gtk::Window
* w
)
2253 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
2257 while (i
!= _processor_window_proxies
.end()) {
2258 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2267 /* we shouldn't get here, because the ProcessorUIList should always contain
2268 an entry for each processor.
2274 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr
<Delivery
> w
)
2276 boost::shared_ptr
<Delivery
> d
= w
.lock ();
2281 list
<ProcessorEntry
*> children
= processor_display
.children ();
2282 list
<ProcessorEntry
*>::const_iterator i
= children
.begin();
2283 while (i
!= children
.end() && (*i
)->processor() != d
) {
2287 if (i
== children
.end()) {
2288 processor_display
.set_active (0);
2290 processor_display
.set_active (*i
);
2295 ProcessorBox::hide_things ()
2297 list
<ProcessorEntry
*> c
= processor_display
.children ();
2298 for (list
<ProcessorEntry
*>::iterator i
= c
.begin(); i
!= c
.end(); ++i
) {
2299 (*i
)->hide_things ();
2303 ProcessorWindowProxy::ProcessorWindowProxy (
2304 string
const & name
,
2305 XMLNode
const * node
,
2307 boost::weak_ptr
<Processor
> processor
2309 : WindowProxy
<Gtk::Window
> (name
, node
)
2311 , _processor_box (box
)
2312 , _processor (processor
)
2319 ProcessorWindowProxy::show ()
2321 boost::shared_ptr
<Processor
> p
= _processor
.lock ();
2326 _processor_box
->toggle_edit_processor (p
);