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 /* set the adjustment to a gain of 0dB so that the fader's default value is right */
304 _adjustment (0.781787, 0, 1, 0.01, 0.1),
305 _fader (_slider
, &_adjustment
, 0, false),
306 _ignore_gain_change (false)
308 _fader
.set_name ("SendFader");
309 _fader
.set_controllable (_send
->amp()->gain_control ());
310 _vbox
.pack_start (_fader
);
314 _adjustment
.signal_value_changed().connect (sigc::mem_fun (*this, &SendProcessorEntry::gain_adjusted
));
315 _send
->amp()->gain_control()->Changed
.connect (send_gain_connection
, invalidator (*this), boost::bind (&SendProcessorEntry::show_gain
, this), gui_context());
320 SendProcessorEntry::setup_slider_pix ()
322 _slider
= ::get_icon ("fader_belt_h_thin");
327 SendProcessorEntry::show_gain ()
329 ENSURE_GUI_THREAD (*this, &SendProcessorEntry::show_gain
)
331 float const value
= gain_to_slider_position (_send
->amp()->gain ());
333 if (_adjustment
.get_value() != value
) {
334 _ignore_gain_change
= true;
335 _adjustment
.set_value (value
);
336 _ignore_gain_change
= false;
340 s
.setf (ios::fixed
, ios::floatfield
);
341 s
<< accurate_coefficient_to_dB (_send
->amp()->gain ()) << _("dB");
342 _fader
.set_tooltip_text (s
.str ());
347 SendProcessorEntry::gain_adjusted ()
349 if (_ignore_gain_change
) {
353 _send
->amp()->set_gain (slider_position_to_gain (_adjustment
.get_value()), this);
357 SendProcessorEntry::set_pixel_width (int p
)
359 _fader
.set_fader_length (p
);
362 PluginInsertProcessorEntry::PluginInsertProcessorEntry (boost::shared_ptr
<ARDOUR::PluginInsert
> p
, Width w
)
363 : ProcessorEntry (p
, w
)
366 p
->SplittingChanged
.connect (
367 _splitting_connection
, invalidator (*this), ui_bind (&PluginInsertProcessorEntry::plugin_insert_splitting_changed
, this), gui_context()
370 _splitting_icon
.set_size_request (-1, 12);
372 _vbox
.pack_start (_splitting_icon
);
373 _vbox
.reorder_child (_splitting_icon
, 0);
375 plugin_insert_splitting_changed ();
379 PluginInsertProcessorEntry::plugin_insert_splitting_changed ()
381 if (_plugin_insert
->splitting ()) {
382 _splitting_icon
.show ();
384 _splitting_icon
.hide ();
389 PluginInsertProcessorEntry::hide_things ()
391 plugin_insert_splitting_changed ();
395 PluginInsertProcessorEntry::setup_visuals ()
399 _splitting_icon
.set_name ("ProcessorPreFader");
403 _splitting_icon
.set_name ("ProcessorFader");
407 _splitting_icon
.set_name ("ProcessorPostFader");
411 ProcessorEntry::setup_visuals ();
415 PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose
* ev
)
417 cairo_t
* cr
= gdk_cairo_create (get_window()->gobj());
419 cairo_set_line_width (cr
, 1);
421 double const width
= ev
->area
.width
;
422 double const height
= ev
->area
.height
;
424 Gdk::Color
const bg
= get_style()->get_bg (STATE_NORMAL
);
425 cairo_set_source_rgb (cr
, bg
.get_red_p (), bg
.get_green_p (), bg
.get_blue_p ());
427 cairo_rectangle (cr
, 0, 0, width
, height
);
430 Gdk::Color
const fg
= get_style()->get_fg (STATE_NORMAL
);
431 cairo_set_source_rgb (cr
, fg
.get_red_p (), fg
.get_green_p (), fg
.get_blue_p ());
433 cairo_move_to (cr
, width
* 0.3, height
);
434 cairo_line_to (cr
, width
* 0.3, height
* 0.5);
435 cairo_line_to (cr
, width
* 0.7, height
* 0.5);
436 cairo_line_to (cr
, width
* 0.7, height
);
437 cairo_move_to (cr
, width
* 0.5, height
* 0.5);
438 cairo_line_to (cr
, width
* 0.5, 0);
444 ProcessorBox::ProcessorBox (ARDOUR::Session
* sess
, boost::function
<PluginSelector
*()> get_plugin_selector
,
445 RouteRedirectSelection
& rsel
, MixerStrip
* parent
, bool owner_is_mixer
)
446 : _parent_strip (parent
)
447 , _owner_is_mixer (owner_is_mixer
)
448 , ab_direction (true)
449 , _get_plugin_selector (get_plugin_selector
)
450 , _placement(PreFader
)
451 , _rr_selection(rsel
)
457 send_action_menu
= 0;
458 no_processor_redisplay
= false;
460 processor_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
461 processor_scroller
.add (processor_display
);
462 pack_start (processor_scroller
, true, true);
464 processor_display
.set_flags (CAN_FOCUS
);
465 processor_display
.set_name ("ProcessorList");
466 processor_display
.set_size_request (48, -1);
467 processor_display
.set_data ("processorbox", this);
468 processor_display
.set_spacing (2);
470 processor_display
.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify
), false);
471 processor_display
.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify
), false);
473 processor_display
.signal_key_press_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_press_event
));
474 processor_display
.signal_key_release_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_release_event
));
476 processor_display
.ButtonPress
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event
));
477 processor_display
.ButtonRelease
.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event
));
479 processor_display
.Reordered
.connect (sigc::mem_fun (*this, &ProcessorBox::reordered
));
480 processor_display
.DropFromAnotherBox
.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop
));
481 processor_display
.SelectionChanged
.connect (sigc::mem_fun (*this, &ProcessorBox::selection_changed
));
483 processor_scroller
.show ();
484 processor_display
.show ();
487 parent
->DeliveryChanged
.connect (
488 _mixer_strip_connections
, invalidator (*this), ui_bind (&ProcessorBox::mixer_strip_delivery_changed
, this, _1
), gui_context ()
493 ProcessorBox::~ProcessorBox ()
498 ProcessorBox::set_route (boost::shared_ptr
<Route
> r
)
504 _route_connections
.drop_connections();
506 /* new route: any existing block on processor redisplay must be meaningless */
507 no_processor_redisplay
= false;
510 _route
->processors_changed
.connect (
511 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_processors_changed
, this, _1
), gui_context()
514 _route
->DropReferences
.connect (
515 _route_connections
, invalidator (*this), boost::bind (&ProcessorBox::route_going_away
, this), gui_context()
518 _route
->PropertyChanged
.connect (
519 _route_connections
, invalidator (*this), ui_bind (&ProcessorBox::route_property_changed
, this, _1
), gui_context()
522 redisplay_processors ();
526 ProcessorBox::route_going_away ()
528 /* don't keep updating display as processors are deleted */
529 no_processor_redisplay
= true;
534 ProcessorBox::object_drop(DnDVBox
<ProcessorEntry
>* source
, ProcessorEntry
* position
, Glib::RefPtr
<Gdk::DragContext
> const & context
)
536 boost::shared_ptr
<Processor
> p
;
538 p
= position
->processor ();
541 list
<ProcessorEntry
*> children
= source
->selection ();
542 list
<boost::shared_ptr
<Processor
> > procs
;
543 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
544 procs
.push_back ((*i
)->processor ());
547 for (list
<boost::shared_ptr
<Processor
> >::const_iterator i
= procs
.begin(); i
!= procs
.end(); ++i
) {
548 XMLNode
& state
= (*i
)->get_state ();
550 nlist
.push_back (&state
);
551 paste_processor_state (nlist
, p
);
555 /* since the dndvbox doesn't take care of this properly, we have to delete the originals
559 if ((context
->get_suggested_action() == Gdk::ACTION_MOVE
) && source
) {
560 ProcessorBox
* other
= reinterpret_cast<ProcessorBox
*> (source
->get_data ("processorbox"));
562 cerr
<< "source was another processor box, delete the selected items\n";
563 other
->delete_dragged_processors (procs
);
569 ProcessorBox::update()
571 redisplay_processors ();
575 ProcessorBox::set_width (Width w
)
583 list
<ProcessorEntry
*> children
= processor_display
.children ();
584 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
585 (*i
)->set_enum_width (w
);
588 redisplay_processors ();
592 ProcessorBox::build_send_action_menu ()
594 using namespace Menu_Helpers
;
596 send_action_menu
= new Menu
;
597 send_action_menu
->set_name ("ArdourContextMenu");
598 MenuList
& items
= send_action_menu
->items();
600 items
.push_back (MenuElem (_("New send"), sigc::mem_fun(*this, &ProcessorBox::new_send
)));
601 items
.push_back (MenuElem (_("Show send controls"), sigc::mem_fun(*this, &ProcessorBox::show_send_controls
)));
605 ProcessorBox::build_possible_aux_menu ()
607 boost::shared_ptr
<RouteList
> rl
= _session
->get_routes_with_internal_returns();
613 using namespace Menu_Helpers
;
614 Menu
* menu
= manage (new Menu
);
615 MenuList
& items
= menu
->items();
617 for (RouteList::iterator r
= rl
->begin(); r
!= rl
->end(); ++r
) {
618 if (!_route
->internal_send_for (*r
) && *r
!= _route
) {
619 items
.push_back (MenuElem ((*r
)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux
), boost::weak_ptr
<Route
>(*r
))));
627 ProcessorBox::show_send_controls ()
632 ProcessorBox::new_send ()
637 ProcessorBox::show_processor_menu (gint arg
)
639 if (processor_menu
== 0) {
640 processor_menu
= build_processor_menu ();
643 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
645 if (plugin_menu_item
) {
646 plugin_menu_item
->set_submenu (*_get_plugin_selector()->plugin_menu());
649 Gtk::MenuItem
* aux_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/ProcessorMenu/newaux"));
652 Menu
* m
= build_possible_aux_menu();
653 if (m
&& !m
->items().empty()) {
654 aux_menu_item
->set_submenu (*m
);
655 aux_menu_item
->set_sensitive (true);
657 /* stupid gtkmm: we need to pass a null reference here */
658 gtk_menu_item_set_submenu (aux_menu_item
->gobj(), 0);
659 aux_menu_item
->set_sensitive (false);
663 cut_action
->set_sensitive (can_cut());
664 paste_action
->set_sensitive (!_rr_selection
.processors
.empty());
666 processor_menu
->popup (1, arg
);
670 ProcessorBox::enter_notify (GdkEventCrossing
*)
672 _current_processor_box
= this;
673 Keyboard::magic_widget_grab_focus ();
674 processor_display
.grab_focus ();
680 ProcessorBox::leave_notify (GdkEventCrossing
* ev
)
682 switch (ev
->detail
) {
683 case GDK_NOTIFY_INFERIOR
:
686 Keyboard::magic_widget_drop_focus ();
693 ProcessorBox::processor_key_press_event (GdkEventKey
*)
695 /* do real stuff on key release */
700 ProcessorBox::processor_key_release_event (GdkEventKey
*ev
)
703 ProcSelection targets
;
705 get_selected_processors (targets
);
707 if (targets
.empty()) {
710 processor_display
.get_pointer (x
, y
);
712 pair
<ProcessorEntry
*, double> const pointer
= processor_display
.get_child_at_position (y
);
715 targets
.push_back (pointer
.first
->processor ());
720 switch (ev
->keyval
) {
722 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
723 processor_display
.select_all ();
729 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
730 copy_processors (targets
);
736 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
737 cut_processors (targets
);
743 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
744 if (targets
.empty()) {
747 paste_processors (targets
.front());
761 delete_processors (targets
);
766 for (ProcSelection::iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
767 if ((*i
)->active()) {
789 ProcessorBox::processor_button_press_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
791 boost::shared_ptr
<Processor
> processor
;
793 processor
= child
->processor ();
797 bool selected
= processor_display
.selected (child
);
799 if (processor
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
801 if (_session
->engine().connected()) {
802 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
803 toggle_edit_processor (processor
);
807 } else if (processor
&& ev
->button
== 1 && selected
) {
809 // this is purely informational but necessary for route params UI
810 ProcessorSelected (processor
); // emit
812 } else if (!processor
&& ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
) {
815 _get_plugin_selector()->show_manager ();
822 ProcessorBox::processor_button_release_event (GdkEventButton
*ev
, ProcessorEntry
* child
)
824 boost::shared_ptr
<Processor
> processor
;
826 processor
= child
->processor ();
831 if (processor
&& Keyboard::is_delete_event (ev
)) {
833 Glib::signal_idle().connect (sigc::bind (
834 sigc::mem_fun(*this, &ProcessorBox::idle_delete_processor
),
835 boost::weak_ptr
<Processor
>(processor
)));
838 } else if (Keyboard::is_context_menu_event (ev
)) {
840 /* figure out if we are above or below the fader/amp processor,
841 and set the next insert position appropriately.
845 if (_route
->processor_is_prefader (processor
)) {
846 _placement
= PreFader
;
848 _placement
= PostFader
;
851 _placement
= PostFader
;
854 show_processor_menu (ev
->time
);
857 } else if (processor
&& Keyboard::is_button2_event (ev
)
859 && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))
863 /* button2-click with no/appropriate modifiers */
865 if (processor
->active()) {
866 processor
->deactivate ();
868 processor
->activate ();
878 ProcessorBox::build_processor_menu ()
880 processor_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/ProcessorMenu") );
881 processor_menu
->set_name ("ArdourContextMenu");
882 return processor_menu
;
886 ProcessorBox::selection_changed ()
888 const bool sensitive
= !processor_display
.selection().empty();
889 ActionManager::set_sensitive(ActionManager::plugin_selection_sensitive_actions
,
891 edit_action
->set_sensitive(one_processor_can_be_edited());
893 const bool single_selection
= (processor_display
.selection().size() == 1);
895 boost::shared_ptr
<PluginInsert
> pi
;
896 if (single_selection
) {
897 pi
= boost::dynamic_pointer_cast
<PluginInsert
>(
898 processor_display
.selection().front()->processor());
901 /* enable gui for plugin inserts with editors */
902 controls_action
->set_sensitive(pi
&& pi
->plugin()->has_editor());
904 /* disallow rename for multiple selections and for plugin inserts */
905 rename_action
->set_sensitive(single_selection
&& pi
);
909 ProcessorBox::select_all_processors ()
911 processor_display
.select_all ();
915 ProcessorBox::deselect_all_processors ()
917 processor_display
.select_none ();
921 ProcessorBox::choose_plugin ()
923 _get_plugin_selector()->set_interested_object (*this);
926 /** @return true if an error occurred, otherwise false */
928 ProcessorBox::use_plugins (const SelectedPlugins
& plugins
)
930 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
932 boost::shared_ptr
<Processor
> processor (new PluginInsert (*_session
, *p
));
934 Route::ProcessorStreams err_streams
;
936 if (_route
->add_processor (processor
, _placement
, &err_streams
, Config
->get_new_plugins_active ())) {
937 weird_plugin_dialog (**p
, err_streams
);
939 // XXX SHAREDPTR delete plugin here .. do we even need to care?
942 if (Profile
->get_sae()) {
943 processor
->activate ();
952 ProcessorBox::weird_plugin_dialog (Plugin
& p
, Route::ProcessorStreams streams
)
954 ArdourDialog
dialog (_("Plugin Incompatibility"));
957 string text
= string_compose(_("You attempted to add the plugin \"%1\" at index %2.\n"),
958 p
.name(), streams
.index
);
960 bool has_midi
= streams
.count
.n_midi() > 0 || p
.get_info()->n_inputs
.n_midi() > 0;
961 bool has_audio
= streams
.count
.n_audio() > 0 || p
.get_info()->n_inputs
.n_audio() > 0;
963 text
+= _("\nThis plugin has:\n");
965 uint32_t const n
= p
.get_info()->n_inputs
.n_midi ();
966 text
+= string_compose (ngettext ("\t%1 MIDI input\n", "\t%1 MIDI inputs\n", n
), n
);
969 uint32_t const n
= p
.get_info()->n_inputs
.n_audio ();
970 text
+= string_compose (ngettext ("\t%1 audio input\n", "\t%1 audio inputs\n", n
), n
);
973 text
+= _("\nbut at the insertion point, there are:\n");
975 uint32_t const n
= streams
.count
.n_midi ();
976 text
+= string_compose (ngettext ("\t%1 MIDI channel\n", "\t%1 MIDI channels\n", n
), n
);
979 uint32_t const n
= streams
.count
.n_audio ();
980 text
+= string_compose (ngettext ("\t%1 audio channel\n", "\t%1 audio channels\n", n
), n
);
983 text
+= string_compose (_("\n%1 is unable to insert this plugin here.\n"), PROGRAM_NAME
);
984 label
.set_text(text
);
986 dialog
.get_vbox()->pack_start (label
);
987 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
989 dialog
.set_name (X_("PluginIODialog"));
990 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
991 dialog
.set_modal (true);
998 ProcessorBox::choose_insert ()
1000 boost::shared_ptr
<Processor
> processor (new PortInsert (*_session
, _route
->pannable(), _route
->mute_master()));
1001 _route
->add_processor (processor
, _placement
);
1004 /* Caller must not hold process lock */
1006 ProcessorBox::choose_send ()
1008 boost::shared_ptr
<Send
> send (new Send (*_session
, _route
->pannable(), _route
->mute_master()));
1010 /* make an educated guess at the initial number of outputs for the send */
1011 ChanCount outs
= (_session
->master_out())
1012 ? _session
->master_out()->n_outputs()
1013 : _route
->n_outputs();
1015 /* XXX need processor lock on route */
1017 Glib::Mutex::Lock
lm (AudioEngine::instance()->process_lock());
1018 send
->output()->ensure_io (outs
, false, this);
1019 } catch (AudioEngine::PortRegistrationFailure
& err
) {
1020 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
1024 /* let the user adjust the IO setup before creation.
1026 Note: this dialog is NOT modal - we just leave it to run and it will
1027 return when its Finished signal is emitted - typically when the window
1031 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
->output(), true);
1034 /* keep a reference to the send so it doesn't get deleted while
1035 the IOSelectorWindow is doing its stuff
1037 _processor_being_created
= send
;
1039 ios
->selector().Finished
.connect (sigc::bind (
1040 sigc::mem_fun(*this, &ProcessorBox::send_io_finished
),
1041 boost::weak_ptr
<Processor
>(send
), ios
));
1046 ProcessorBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1048 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1050 /* drop our temporary reference to the new send */
1051 _processor_being_created
.reset ();
1058 case IOSelector::Cancelled
:
1059 // processor will go away when all shared_ptrs to it vanish
1062 case IOSelector::Accepted
:
1063 _route
->add_processor (processor
, _placement
);
1064 if (Profile
->get_sae()) {
1065 processor
->activate ();
1070 delete_when_idle (ios
);
1074 ProcessorBox::return_io_finished (IOSelector::Result r
, boost::weak_ptr
<Processor
> weak_processor
, IOSelectorWindow
* ios
)
1076 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1078 /* drop our temporary reference to the new return */
1079 _processor_being_created
.reset ();
1086 case IOSelector::Cancelled
:
1087 // processor will go away when all shared_ptrs to it vanish
1090 case IOSelector::Accepted
:
1091 _route
->add_processor (processor
, _placement
);
1092 if (Profile
->get_sae()) {
1093 processor
->activate ();
1098 delete_when_idle (ios
);
1102 ProcessorBox::choose_aux (boost::weak_ptr
<Route
> wr
)
1108 boost::shared_ptr
<Route
> target
= wr
.lock();
1114 boost::shared_ptr
<RouteList
> rlist (new RouteList
);
1115 rlist
->push_back (_route
);
1117 _session
->add_internal_sends (target
, PreFader
, rlist
);
1121 ProcessorBox::route_processors_changed (RouteProcessorChange c
)
1123 if (c
.type
== RouteProcessorChange::MeterPointChange
&& c
.meter_visibly_changed
== false) {
1124 /* the meter has moved, but it was and still is invisible to the user, so nothing to do */
1128 redisplay_processors ();
1132 ProcessorBox::redisplay_processors ()
1134 ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors
)
1136 if (no_processor_redisplay
) {
1140 processor_display
.clear ();
1142 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display
));
1144 for (list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin(); i
!= _processor_window_proxies
.end(); ++i
) {
1145 (*i
)->marked
= false;
1148 _route
->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list
));
1150 /* trim dead wood from the processor window proxy list */
1152 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin();
1153 while (i
!= _processor_window_proxies
.end()) {
1154 list
<ProcessorWindowProxy
*>::iterator j
= i
;
1157 if (!(*i
)->marked
) {
1158 ARDOUR_UI::instance()->remove_window_proxy (*i
);
1160 _processor_window_proxies
.erase (i
);
1166 setup_entry_positions ();
1169 /** Add a ProcessorWindowProxy for a processor to our list, if that processor does
1170 * not already have one.
1173 ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr
<Processor
> w
)
1175 boost::shared_ptr
<Processor
> p
= w
.lock ();
1180 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
1181 while (i
!= _processor_window_proxies
.end()) {
1183 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
1186 /* this processor is already on the list; done */
1187 (*i
)->marked
= true;
1194 /* not on the list; add it */
1197 if (_parent_strip
) {
1198 if (_parent_strip
->mixer_owned()) {
1207 ProcessorWindowProxy
* wp
= new ProcessorWindowProxy (
1208 string_compose ("%1-%2-%3", loc
, _route
->id(), p
->id()),
1209 _session
->extra_xml (X_("UI")),
1215 /* if the processor already has an existing UI,
1216 note that so that we don't recreate it
1219 void* existing_ui
= p
->get_ui ();
1222 wp
->set (static_cast<Gtk::Window
*>(existing_ui
));
1225 _processor_window_proxies
.push_back (wp
);
1226 ARDOUR_UI::instance()->add_window_proxy (wp
);
1230 ProcessorBox::add_processor_to_display (boost::weak_ptr
<Processor
> p
)
1232 boost::shared_ptr
<Processor
> processor (p
.lock ());
1234 if (!processor
|| !processor
->display_to_user()) {
1238 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (processor
);
1239 boost::shared_ptr
<PluginInsert
> plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
);
1240 ProcessorEntry
* e
= 0;
1242 e
= new SendProcessorEntry (send
, _width
);
1243 } else if (plugin_insert
) {
1244 e
= new PluginInsertProcessorEntry (plugin_insert
, _width
);
1246 e
= new ProcessorEntry (processor
, _width
);
1249 e
->set_pixel_width (get_allocation().get_width());
1250 processor_display
.add_child (e
);
1255 ProcessorBox::build_processor_tooltip (EventBox
& box
, string start
)
1259 list
<ProcessorEntry
*> children
= processor_display
.children ();
1260 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1262 tip
+= (*i
)->processor()->name();
1265 ARDOUR_UI::instance()->set_tip (box
, tip
);
1269 ProcessorBox::reordered ()
1271 compute_processor_sort_keys ();
1272 setup_entry_positions ();
1276 ProcessorBox::setup_entry_positions ()
1278 list
<ProcessorEntry
*> children
= processor_display
.children ();
1279 bool pre_fader
= true;
1281 for (list
<ProcessorEntry
*>::iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
1282 if (boost::dynamic_pointer_cast
<Amp
>((*i
)->processor())) {
1284 (*i
)->set_position (ProcessorEntry::Fader
);
1287 (*i
)->set_position (ProcessorEntry::PreFader
);
1289 (*i
)->set_position (ProcessorEntry::PostFader
);
1296 ProcessorBox::compute_processor_sort_keys ()
1298 list
<ProcessorEntry
*> children
= processor_display
.children ();
1299 Route::ProcessorList our_processors
;
1301 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1302 our_processors
.push_back ((*iter
)->processor ());
1305 if (_route
->reorder_processors (our_processors
)) {
1306 /* Reorder failed, so report this to the user. As far as I can see this must be done
1307 in an idle handler: it seems that the redisplay_processors() that happens below destroys
1308 widgets that were involved in the drag-and-drop on the processor list, which causes problems
1309 when the drag is torn down after this handler function is finished.
1311 Glib::signal_idle().connect_once (sigc::mem_fun (*this, &ProcessorBox::report_failed_reorder
));
1316 ProcessorBox::report_failed_reorder ()
1318 /* reorder failed, so redisplay */
1320 redisplay_processors ();
1322 /* now tell them about the problem */
1324 ArdourDialog
dialog (_("Plugin Incompatibility"));
1327 label
.set_text (_("\
1328 You cannot reorder these plugins/sends/inserts\n\
1329 in that way because the inputs and\n\
1330 outputs will not work correctly."));
1332 dialog
.get_vbox()->set_border_width (12);
1333 dialog
.get_vbox()->pack_start (label
);
1334 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
1336 dialog
.set_name (X_("PluginIODialog"));
1337 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1338 dialog
.set_modal (true);
1345 ProcessorBox::rename_processors ()
1347 ProcSelection to_be_renamed
;
1349 get_selected_processors (to_be_renamed
);
1351 if (to_be_renamed
.empty()) {
1355 for (ProcSelection::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
1356 rename_processor (*i
);
1361 ProcessorBox::can_cut () const
1363 vector
<boost::shared_ptr
<Processor
> > sel
;
1365 get_selected_processors (sel
);
1367 /* cut_processors () does not cut inserts */
1369 for (vector
<boost::shared_ptr
<Processor
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
1371 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1372 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1373 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1382 ProcessorBox::cut_processors ()
1384 ProcSelection to_be_removed
;
1386 get_selected_processors (to_be_removed
);
1390 ProcessorBox::cut_processors (const ProcSelection
& to_be_removed
)
1392 if (to_be_removed
.empty()) {
1396 XMLNode
* node
= new XMLNode (X_("cut"));
1397 Route::ProcessorList to_cut
;
1399 no_processor_redisplay
= true;
1400 for (ProcSelection::const_iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
1401 // Cut only plugins, sends and returns
1402 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1403 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1404 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1406 Window
* w
= get_processor_ui (*i
);
1412 XMLNode
& child ((*i
)->get_state());
1413 node
->add_child_nocopy (child
);
1414 to_cut
.push_back (*i
);
1418 if (_route
->remove_processors (to_cut
) != 0) {
1420 no_processor_redisplay
= false;
1424 _rr_selection
.set (node
);
1426 no_processor_redisplay
= false;
1427 redisplay_processors ();
1431 ProcessorBox::copy_processors ()
1433 ProcSelection to_be_copied
;
1434 get_selected_processors (to_be_copied
);
1435 copy_processors (to_be_copied
);
1439 ProcessorBox::copy_processors (const ProcSelection
& to_be_copied
)
1441 if (to_be_copied
.empty()) {
1445 XMLNode
* node
= new XMLNode (X_("copy"));
1447 for (ProcSelection::const_iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
1448 // Copy only plugins, sends, returns
1449 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0 ||
1450 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0) ||
1451 (boost::dynamic_pointer_cast
<Return
>((*i
)) != 0)) {
1452 node
->add_child_nocopy ((*i
)->get_state());
1456 _rr_selection
.set (node
);
1460 ProcessorBox::delete_processors ()
1462 ProcSelection to_be_deleted
;
1463 get_selected_processors (to_be_deleted
);
1464 delete_processors (to_be_deleted
);
1468 ProcessorBox::delete_processors (const ProcSelection
& targets
)
1470 if (targets
.empty()) {
1474 no_processor_redisplay
= true;
1476 for (ProcSelection::const_iterator i
= targets
.begin(); i
!= targets
.end(); ++i
) {
1478 Window
* w
= get_processor_ui (*i
);
1484 _route
->remove_processor(*i
);
1487 no_processor_redisplay
= false;
1488 redisplay_processors ();
1492 ProcessorBox::delete_dragged_processors (const list
<boost::shared_ptr
<Processor
> >& procs
)
1494 list
<boost::shared_ptr
<Processor
> >::const_iterator x
;
1496 no_processor_redisplay
= true;
1497 for (x
= procs
.begin(); x
!= procs
.end(); ++x
) {
1499 Window
* w
= get_processor_ui (*x
);
1505 _route
->remove_processor(*x
);
1508 no_processor_redisplay
= false;
1509 redisplay_processors ();
1513 ProcessorBox::idle_delete_processor (boost::weak_ptr
<Processor
> weak_processor
)
1515 boost::shared_ptr
<Processor
> processor (weak_processor
.lock());
1521 /* NOT copied to _mixer.selection() */
1523 no_processor_redisplay
= true;
1524 _route
->remove_processor (processor
);
1525 no_processor_redisplay
= false;
1526 redisplay_processors ();
1532 ProcessorBox::rename_processor (boost::shared_ptr
<Processor
> processor
)
1534 ArdourPrompter
name_prompter (true);
1536 name_prompter
.set_title (_("Rename Processor"));
1537 name_prompter
.set_prompt (_("New name:"));
1538 name_prompter
.set_initial_text (processor
->name());
1539 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
1540 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1541 name_prompter
.show_all ();
1543 switch (name_prompter
.run ()) {
1545 case Gtk::RESPONSE_ACCEPT
:
1546 name_prompter
.get_result (result
);
1547 if (result
.length()) {
1550 string test
= result
;
1552 while (tries
< 100) {
1553 if (_session
->io_name_is_legal (test
)) {
1559 test
= string_compose ("%1-%2", result
, tries
);
1563 processor
->set_name (result
);
1566 ARDOUR_UI::instance()->popup_error
1567 (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result
));
1577 ProcessorBox::paste_processors ()
1579 if (_rr_selection
.processors
.empty()) {
1583 paste_processor_state (_rr_selection
.processors
.get_node().children(), boost::shared_ptr
<Processor
>());
1587 ProcessorBox::paste_processors (boost::shared_ptr
<Processor
> before
)
1590 if (_rr_selection
.processors
.empty()) {
1594 paste_processor_state (_rr_selection
.processors
.get_node().children(), before
);
1598 ProcessorBox::paste_processor_state (const XMLNodeList
& nlist
, boost::shared_ptr
<Processor
> p
)
1600 XMLNodeConstIterator niter
;
1601 list
<boost::shared_ptr
<Processor
> > copies
;
1603 if (nlist
.empty()) {
1607 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1609 XMLProperty
const * type
= (*niter
)->property ("type");
1612 boost::shared_ptr
<Processor
> p
;
1614 if (type
->value() == "meter" ||
1615 type
->value() == "main-outs" ||
1616 type
->value() == "amp" ||
1617 type
->value() == "intsend" || type
->value() == "intreturn") {
1618 /* do not paste meter, main outs, amp or internal send/returns */
1621 } else if (type
->value() == "send") {
1623 XMLNode
n (**niter
);
1624 Send::make_unique (n
, *_session
);
1625 Send
* s
= new Send (*_session
, _route
->pannable(), _route
->mute_master());
1626 if (s
->set_state (n
, Stateful::loading_state_version
)) {
1634 } else if (type
->value() == "return") {
1636 XMLNode
n (**niter
);
1637 Return::make_unique (n
, *_session
);
1638 Return
* r
= new Return (*_session
);
1640 if (r
->set_state (n
, Stateful::loading_state_version
)) {
1647 } else if (type
->value() == "port") {
1649 XMLNode
n (**niter
);
1650 p
.reset (new PortInsert (*_session
, _route
->pannable (), _route
->mute_master ()));
1651 if (p
->set_state (n
, Stateful::loading_state_version
)) {
1656 /* XXX its a bit limiting to assume that everything else
1660 p
.reset (new PluginInsert (*_session
));
1661 p
->set_state (**niter
, Stateful::current_state_version
);
1664 copies
.push_back (p
);
1668 cerr
<< "plugin insert constructor failed\n";
1672 if (copies
.empty()) {
1676 if (_route
->add_processors (copies
, p
)) {
1679 "Copying the set of processors on the clipboard failed,\n\
1680 probably because the I/O configuration of the plugins\n\
1681 could not match the configuration of this track.");
1682 MessageDialog
am (msg
);
1688 ProcessorBox::activate_processor (boost::shared_ptr
<Processor
> r
)
1694 ProcessorBox::deactivate_processor (boost::shared_ptr
<Processor
> r
)
1700 ProcessorBox::get_selected_processors (ProcSelection
& processors
) const
1702 const list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1703 for (list
<ProcessorEntry
*>::const_iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1704 processors
.push_back ((*i
)->processor ());
1709 ProcessorBox::for_selected_processors (void (ProcessorBox::*method
)(boost::shared_ptr
<Processor
>))
1711 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1712 for (list
<ProcessorEntry
*>::iterator i
= selection
.begin(); i
!= selection
.end(); ++i
) {
1713 (this->*method
) ((*i
)->processor ());
1718 ProcessorBox::all_processors_active (bool state
)
1720 _route
->all_processors_active (_placement
, state
);
1724 ProcessorBox::ab_plugins ()
1726 _route
->ab_plugins (ab_direction
);
1727 ab_direction
= !ab_direction
;
1732 ProcessorBox::clear_processors ()
1735 vector
<string
> choices
;
1737 prompt
= string_compose (_("Do you really want to remove all processors from %1?\n"
1738 "(this cannot be undone)"), _route
->name());
1740 choices
.push_back (_("Cancel"));
1741 choices
.push_back (_("Yes, remove them all"));
1743 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1745 if (prompter
.run () == 1) {
1746 _route
->clear_processors (PreFader
);
1747 _route
->clear_processors (PostFader
);
1752 ProcessorBox::clear_processors (Placement p
)
1755 vector
<string
> choices
;
1757 if (p
== PreFader
) {
1758 prompt
= string_compose (_("Do you really want to remove all pre-fader processors from %1?\n"
1759 "(this cannot be undone)"), _route
->name());
1761 prompt
= string_compose (_("Do you really want to remove all post-fader processors from %1?\n"
1762 "(this cannot be undone)"), _route
->name());
1765 choices
.push_back (_("Cancel"));
1766 choices
.push_back (_("Yes, remove them all"));
1768 Gtkmm2ext::Choice
prompter (_("Remove processors"), prompt
, choices
);
1770 if (prompter
.run () == 1) {
1771 _route
->clear_processors (p
);
1776 ProcessorBox::processor_can_be_edited (boost::shared_ptr
<Processor
> processor
)
1778 boost::shared_ptr
<AudioTrack
> at
= boost::dynamic_pointer_cast
<AudioTrack
> (_route
);
1779 if (at
&& at
->freeze_state() == AudioTrack::Frozen
) {
1784 boost::dynamic_pointer_cast
<Send
> (processor
) ||
1785 boost::dynamic_pointer_cast
<Return
> (processor
) ||
1786 boost::dynamic_pointer_cast
<PluginInsert
> (processor
) ||
1787 boost::dynamic_pointer_cast
<PortInsert
> (processor
)
1796 ProcessorBox::one_processor_can_be_edited ()
1798 list
<ProcessorEntry
*> selection
= processor_display
.selection ();
1799 list
<ProcessorEntry
*>::iterator i
= selection
.begin();
1800 while (i
!= selection
.end() && processor_can_be_edited ((*i
)->processor()) == false) {
1804 return (i
!= selection
.end());
1808 ProcessorBox::toggle_edit_processor (boost::shared_ptr
<Processor
> processor
)
1810 boost::shared_ptr
<Send
> send
;
1811 boost::shared_ptr
<InternalSend
> internal_send
;
1812 boost::shared_ptr
<Return
> retrn
;
1813 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1814 boost::shared_ptr
<PortInsert
> port_insert
;
1817 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1819 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1824 if (boost::dynamic_pointer_cast
<Amp
> (processor
)) {
1826 _parent_strip
->revert_to_default_display ();
1828 } else if ((internal_send
= boost::dynamic_pointer_cast
<InternalSend
> (processor
)) != 0) {
1830 if (!_session
->engine().connected()) {
1834 if (_parent_strip
) {
1835 if (boost::dynamic_pointer_cast
<Send
> (_parent_strip
->current_delivery()) == internal_send
) {
1836 _parent_strip
->revert_to_default_display ();
1838 _parent_strip
->show_send (internal_send
);
1842 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
1844 if (!_session
->engine().connected()) {
1848 SendUIWindow
* w
= new SendUIWindow (send
, _session
);
1851 } else if ((retrn
= boost::dynamic_pointer_cast
<Return
> (processor
)) != 0) {
1853 if (boost::dynamic_pointer_cast
<InternalReturn
> (retrn
)) {
1854 /* no GUI for these */
1858 if (!_session
->engine().connected()) {
1862 boost::shared_ptr
<Return
> retrn
= boost::dynamic_pointer_cast
<Return
> (processor
);
1864 ReturnUIWindow
*return_ui
;
1865 Window
* w
= get_processor_ui (retrn
);
1869 return_ui
= new ReturnUIWindow (retrn
, _session
);
1870 return_ui
->set_title (retrn
->name ());
1871 set_processor_ui (send
, return_ui
);
1874 return_ui
= dynamic_cast<ReturnUIWindow
*> (w
);
1879 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
1881 PluginUIWindow
*plugin_ui
;
1883 /* these are both allowed to be null */
1885 Container
* toplevel
= get_toplevel();
1886 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1888 Window
* w
= get_processor_ui (plugin_insert
);
1892 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1893 plugin_ui
->set_title (generate_processor_title (plugin_insert
));
1894 set_processor_ui (plugin_insert
, plugin_ui
);
1897 plugin_ui
= dynamic_cast<PluginUIWindow
*> (w
);
1898 plugin_ui
->set_parent (win
);
1903 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (processor
)) != 0) {
1905 if (!_session
->engine().connected()) {
1906 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1911 PortInsertWindow
*io_selector
;
1913 Window
* w
= get_processor_ui (port_insert
);
1916 io_selector
= new PortInsertWindow (_session
, port_insert
);
1917 set_processor_ui (port_insert
, io_selector
);
1920 io_selector
= dynamic_cast<PortInsertWindow
*> (w
);
1923 gidget
= io_selector
;
1927 if (gidget
->is_visible()) {
1930 gidget
->show_all ();
1937 ProcessorBox::toggle_processor_controls (boost::shared_ptr
<Processor
> processor
)
1939 boost::shared_ptr
<PluginInsert
> plugin_insert
1940 = boost::dynamic_pointer_cast
<PluginInsert
>(processor
);
1941 if (!plugin_insert
) {
1945 Container
* toplevel
= get_toplevel();
1946 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1947 PluginUIWindow
* plugin_ui
= new PluginUIWindow(win
, plugin_insert
, true, false);
1948 plugin_ui
->set_title(generate_processor_title (plugin_insert
));
1950 if (plugin_ui
->is_visible()) {
1953 plugin_ui
->show_all();
1954 plugin_ui
->present();
1959 ProcessorBox::register_actions ()
1961 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("ProcessorMenu"));
1962 Glib::RefPtr
<Action
> act
;
1965 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"),
1966 sigc::ptr_fun (ProcessorBox::rb_choose_plugin
));
1968 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"),
1969 sigc::ptr_fun (ProcessorBox::rb_choose_insert
));
1970 ActionManager::jack_sensitive_actions
.push_back (act
);
1971 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."),
1972 sigc::ptr_fun (ProcessorBox::rb_choose_send
));
1973 ActionManager::jack_sensitive_actions
.push_back (act
);
1975 ActionManager::register_action (popup_act_grp
, X_("newaux"), _("New Aux Send ..."));
1977 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear (all)"),
1978 sigc::ptr_fun (ProcessorBox::rb_clear
));
1979 ActionManager::register_action (popup_act_grp
, X_("clear_pre"), _("Clear (pre-fader)"),
1980 sigc::ptr_fun (ProcessorBox::rb_clear_pre
));
1981 ActionManager::register_action (popup_act_grp
, X_("clear_post"), _("Clear (post-fader)"),
1982 sigc::ptr_fun (ProcessorBox::rb_clear_post
));
1984 /* standard editing stuff */
1985 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"),
1986 sigc::ptr_fun (ProcessorBox::rb_cut
));
1987 ActionManager::plugin_selection_sensitive_actions
.push_back(cut_action
);
1988 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"),
1989 sigc::ptr_fun (ProcessorBox::rb_copy
));
1990 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1992 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"),
1993 sigc::ptr_fun (ProcessorBox::rb_delete
));
1994 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1996 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"),
1997 sigc::ptr_fun (ProcessorBox::rb_paste
));
1998 rename_action
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"),
1999 sigc::ptr_fun (ProcessorBox::rb_rename
));
2000 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"),
2001 sigc::ptr_fun (ProcessorBox::rb_select_all
));
2002 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"),
2003 sigc::ptr_fun (ProcessorBox::rb_deselect_all
));
2005 /* activation etc. */
2007 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"),
2008 sigc::ptr_fun (ProcessorBox::rb_activate_all
));
2009 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"),
2010 sigc::ptr_fun (ProcessorBox::rb_deactivate_all
));
2011 ActionManager::register_action (popup_act_grp
, X_("ab_plugins"), _("A/B Plugins"),
2012 sigc::ptr_fun (ProcessorBox::rb_ab_plugins
));
2015 edit_action
= ActionManager::register_action (
2016 popup_act_grp
, X_("edit"), _("Edit..."),
2017 sigc::ptr_fun (ProcessorBox::rb_edit
));
2019 /* show plugin GUI */
2020 controls_action
= ActionManager::register_action (
2021 popup_act_grp
, X_("controls"), _("Controls..."),
2022 sigc::ptr_fun (ProcessorBox::rb_controls
));
2024 ActionManager::add_action_group (popup_act_grp
);
2028 ProcessorBox::rb_ab_plugins ()
2030 if (_current_processor_box
== 0) {
2034 _current_processor_box
->ab_plugins ();
2038 ProcessorBox::rb_choose_plugin ()
2040 if (_current_processor_box
== 0) {
2043 _current_processor_box
->choose_plugin ();
2047 ProcessorBox::rb_choose_insert ()
2049 if (_current_processor_box
== 0) {
2052 _current_processor_box
->choose_insert ();
2056 ProcessorBox::rb_choose_send ()
2058 if (_current_processor_box
== 0) {
2061 _current_processor_box
->choose_send ();
2065 ProcessorBox::rb_choose_aux (boost::weak_ptr
<Route
> wr
)
2067 if (_current_processor_box
== 0) {
2071 _current_processor_box
->choose_aux (wr
);
2075 ProcessorBox::rb_clear ()
2077 if (_current_processor_box
== 0) {
2081 _current_processor_box
->clear_processors ();
2086 ProcessorBox::rb_clear_pre ()
2088 if (_current_processor_box
== 0) {
2092 _current_processor_box
->clear_processors (PreFader
);
2097 ProcessorBox::rb_clear_post ()
2099 if (_current_processor_box
== 0) {
2103 _current_processor_box
->clear_processors (PostFader
);
2107 ProcessorBox::rb_cut ()
2109 if (_current_processor_box
== 0) {
2113 _current_processor_box
->cut_processors ();
2117 ProcessorBox::rb_delete ()
2119 if (_current_processor_box
== 0) {
2123 _current_processor_box
->delete_processors ();
2127 ProcessorBox::rb_copy ()
2129 if (_current_processor_box
== 0) {
2132 _current_processor_box
->copy_processors ();
2136 ProcessorBox::rb_paste ()
2138 if (_current_processor_box
== 0) {
2142 _current_processor_box
->paste_processors ();
2146 ProcessorBox::rb_rename ()
2148 if (_current_processor_box
== 0) {
2151 _current_processor_box
->rename_processors ();
2155 ProcessorBox::rb_select_all ()
2157 if (_current_processor_box
== 0) {
2161 _current_processor_box
->select_all_processors ();
2165 ProcessorBox::rb_deselect_all ()
2167 if (_current_processor_box
== 0) {
2171 _current_processor_box
->deselect_all_processors ();
2175 ProcessorBox::rb_activate_all ()
2177 if (_current_processor_box
== 0) {
2181 _current_processor_box
->all_processors_active (true);
2185 ProcessorBox::rb_deactivate_all ()
2187 if (_current_processor_box
== 0) {
2190 _current_processor_box
->all_processors_active (false);
2194 ProcessorBox::rb_edit ()
2196 if (_current_processor_box
== 0) {
2200 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_edit_processor
);
2204 ProcessorBox::rb_controls ()
2206 if (_current_processor_box
== 0) {
2210 _current_processor_box
->for_selected_processors (&ProcessorBox::toggle_processor_controls
);
2214 ProcessorBox::route_property_changed (const PropertyChange
& what_changed
)
2216 if (!what_changed
.contains (ARDOUR::Properties::name
)) {
2220 ENSURE_GUI_THREAD (*this, &ProcessorBox::route_property_changed
, what_changed
);
2222 boost::shared_ptr
<Processor
> processor
;
2223 boost::shared_ptr
<PluginInsert
> plugin_insert
;
2224 boost::shared_ptr
<Send
> send
;
2226 list
<ProcessorEntry
*> children
= processor_display
.children();
2228 for (list
<ProcessorEntry
*>::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
2230 processor
= (*iter
)->processor ();
2232 Window
* w
= get_processor_ui (processor
);
2238 /* rename editor windows for sends and plugins */
2240 if ((send
= boost::dynamic_pointer_cast
<Send
> (processor
)) != 0) {
2241 w
->set_title (send
->name ());
2242 } else if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (processor
)) != 0) {
2243 w
->set_title (generate_processor_title (plugin_insert
));
2249 ProcessorBox::generate_processor_title (boost::shared_ptr
<PluginInsert
> pi
)
2251 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
2252 string::size_type email_pos
;
2254 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
2255 maker
= maker
.substr (0, email_pos
- 1);
2258 if (maker
.length() > 32) {
2259 maker
= maker
.substr (0, 32);
2263 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);
2267 ProcessorBox::on_size_allocate (Allocation
& a
)
2269 HBox::on_size_allocate (a
);
2271 list
<ProcessorEntry
*> children
= processor_display
.children ();
2272 for (list
<ProcessorEntry
*>::const_iterator i
= children
.begin(); i
!= children
.end(); ++i
) {
2273 (*i
)->set_pixel_width (a
.get_width ());
2277 /** @param p Processor.
2278 * @return the UI window for \a p.
2281 ProcessorBox::get_processor_ui (boost::shared_ptr
<Processor
> p
) const
2283 list
<ProcessorWindowProxy
*>::const_iterator i
= _processor_window_proxies
.begin ();
2284 while (i
!= _processor_window_proxies
.end()) {
2285 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2287 return (*i
)->get ();
2293 /* we shouldn't get here, because the ProcessorUIList should always contain
2294 an entry for each processor.
2300 /** Make a note of the UI window that a processor is using.
2301 * @param p Processor.
2302 * @param w UI window.
2305 ProcessorBox::set_processor_ui (boost::shared_ptr
<Processor
> p
, Gtk::Window
* w
)
2307 list
<ProcessorWindowProxy
*>::iterator i
= _processor_window_proxies
.begin ();
2311 while (i
!= _processor_window_proxies
.end()) {
2312 boost::shared_ptr
<Processor
> t
= (*i
)->processor().lock ();
2321 /* we shouldn't get here, because the ProcessorUIList should always contain
2322 an entry for each processor.
2328 ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr
<Delivery
> w
)
2330 boost::shared_ptr
<Delivery
> d
= w
.lock ();
2335 list
<ProcessorEntry
*> children
= processor_display
.children ();
2336 list
<ProcessorEntry
*>::const_iterator i
= children
.begin();
2337 while (i
!= children
.end() && (*i
)->processor() != d
) {
2341 if (i
== children
.end()) {
2342 processor_display
.set_active (0);
2344 processor_display
.set_active (*i
);
2349 ProcessorBox::hide_things ()
2351 list
<ProcessorEntry
*> c
= processor_display
.children ();
2352 for (list
<ProcessorEntry
*>::iterator i
= c
.begin(); i
!= c
.end(); ++i
) {
2353 (*i
)->hide_things ();
2357 ProcessorWindowProxy::ProcessorWindowProxy (
2358 string
const & name
,
2359 XMLNode
const * node
,
2361 boost::weak_ptr
<Processor
> processor
2363 : WindowProxy
<Gtk::Window
> (name
, node
)
2365 , _processor_box (box
)
2366 , _processor (processor
)
2373 ProcessorWindowProxy::show ()
2375 boost::shared_ptr
<Processor
> p
= _processor
.lock ();
2380 _processor_box
->toggle_edit_processor (p
);