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.
23 #include <sigc++/bind.h>
25 #include <pbd/convert.h>
27 #include <glibmm/miscutils.h>
29 #include <gtkmm/messagedialog.h>
31 #include <gtkmm2ext/gtk_ui.h>
32 #include <gtkmm2ext/utils.h>
33 #include <gtkmm2ext/choice.h>
34 #include <gtkmm2ext/utils.h>
35 #include <gtkmm2ext/stop_signal.h>
36 #include <gtkmm2ext/doi.h>
38 #include <ardour/ardour.h>
39 #include <ardour/session.h>
40 #include <ardour/audioengine.h>
41 #include <ardour/route.h>
42 #include <ardour/audio_track.h>
43 #include <ardour/audio_diskstream.h>
44 #include <ardour/send.h>
45 #include <ardour/insert.h>
46 #include <ardour/ladspa_plugin.h>
47 #include <ardour/connection.h>
48 #include <ardour/session_connection.h>
49 #include <ardour/profile.h>
51 #include "ardour_ui.h"
52 #include "ardour_dialog.h"
53 #include "public_editor.h"
54 #include "redirect_box.h"
56 #include "plugin_selector.h"
57 #include "route_redirect_selection.h"
60 #include "plugin_ui.h"
62 #include "io_selector.h"
64 #include "gui_thread.h"
68 #ifdef HAVE_AUDIOUNITS
73 using namespace ARDOUR
;
77 using namespace Gtkmm2ext
;
79 RedirectBox
* RedirectBox::_current_redirect_box
= 0;
80 RefPtr
<Action
> RedirectBox::cut_action
;
81 RefPtr
<Action
> RedirectBox::paste_action
;
82 bool RedirectBox::get_colors
= true;
83 Gdk::Color
* RedirectBox::active_redirect_color
;
84 Gdk::Color
* RedirectBox::inactive_redirect_color
;
86 RedirectBox::RedirectBox (Placement pcmnt
, Session
& sess
, PluginSelector
&plugsel
,
87 RouteRedirectSelection
& rsel
, bool owner_is_mixer
)
89 _owner_is_mixer (owner_is_mixer
),
91 _plugin_selector(plugsel
),
95 active_redirect_color
= new Gdk::Color
;
96 inactive_redirect_color
= new Gdk::Color
;
97 set_color (*active_redirect_color
, rgba_from_style ("RedirectSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_ACTIVE
, false ));
98 set_color (*inactive_redirect_color
, rgba_from_style ("RedirectSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL
, false ));
104 send_action_menu
= 0;
105 redirect_drag_in_progress
= false;
106 no_redirect_redisplay
= false;
107 ignore_delete
= false;
109 model
= ListStore::create(columns
);
111 RefPtr
<TreeSelection
> selection
= redirect_display
.get_selection();
112 selection
->set_mode (Gtk::SELECTION_MULTIPLE
);
113 selection
->signal_changed().connect (mem_fun (*this, &RedirectBox::selection_changed
));
115 redirect_display
.set_model (model
);
116 redirect_display
.append_column (X_("notshown"), columns
.text
);
117 redirect_display
.set_name ("RedirectSelector");
118 redirect_display
.set_headers_visible (false);
119 redirect_display
.set_reorderable (true);
120 redirect_display
.set_size_request (-1, 40);
121 redirect_display
.get_column(0)->set_sizing(TREE_VIEW_COLUMN_FIXED
);
122 redirect_display
.get_column(0)->set_fixed_width(48);
123 redirect_display
.add_object_drag (columns
.redirect
.index(), "redirects");
124 redirect_display
.signal_drop
.connect (mem_fun (*this, &RedirectBox::object_drop
));
126 TreeViewColumn
* name_col
= redirect_display
.get_column(0);
127 CellRendererText
* renderer
= dynamic_cast<CellRendererText
*>(redirect_display
.get_column_cell_renderer (0));
128 name_col
->add_attribute(renderer
->property_foreground_gdk(), columns
.color
);
130 redirect_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
132 model
->signal_row_deleted().connect (mem_fun (*this, &RedirectBox::row_deleted
));
134 redirect_scroller
.add (redirect_display
);
135 redirect_eventbox
.add (redirect_scroller
);
137 redirect_scroller
.set_size_request (-1, 40);
139 pack_start (redirect_eventbox
, true, true);
141 redirect_eventbox
.signal_enter_notify_event().connect (bind (sigc::ptr_fun (RedirectBox::enter_box
), this));
143 redirect_display
.signal_button_press_event().connect (mem_fun(*this, &RedirectBox::redirect_button_press_event
), false);
144 redirect_display
.signal_button_release_event().connect (mem_fun(*this, &RedirectBox::redirect_button_release_event
));
147 RedirectBox::~RedirectBox ()
152 RedirectBox::set_route (boost::shared_ptr
<Route
> r
)
155 connections
.clear ();
157 /* since we're dealing with a new route, any existing limit on redisplay
161 no_redirect_redisplay
= false;
164 connections
.push_back (_route
->redirects_changed
.connect (mem_fun(*this, &RedirectBox::redisplay_redirects
)));
165 connections
.push_back (_route
->GoingAway
.connect (mem_fun (*this, &RedirectBox::route_going_away
)));
166 connections
.push_back (_route
->name_changed
.connect (mem_fun(*this, &RedirectBox::route_name_changed
)));
168 redisplay_redirects (0);
172 RedirectBox::route_going_away ()
174 /* don't keep updating display as redirects are deleted */
175 no_redirect_redisplay
= true;
179 RedirectBox::object_drop (const list
<boost::shared_ptr
<Redirect
> >& redirects
)
181 paste_redirect_list (redirects
);
185 RedirectBox::update()
187 redisplay_redirects (0);
191 RedirectBox::set_width (Width w
)
200 redisplay_redirects (0);
204 RedirectBox::remove_redirect_gui (boost::shared_ptr
<Redirect
> redirect
)
206 boost::shared_ptr
<Insert
> insert
;
207 boost::shared_ptr
<Send
> send
;
208 boost::shared_ptr
<PortInsert
> port_insert
;
210 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) != 0) {
212 if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (insert
)) != 0) {
213 PortInsertUI
*io_selector
= reinterpret_cast<PortInsertUI
*> (port_insert
->get_gui());
214 port_insert
->set_gui (0);
218 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (insert
)) != 0) {
219 SendUIWindow
*sui
= reinterpret_cast<SendUIWindow
*> (send
->get_gui());
226 RedirectBox::build_send_action_menu ()
229 using namespace Menu_Helpers
;
231 send_action_menu
= new Menu
;
232 send_action_menu
->set_name ("ArdourContextMenu");
233 MenuList
& items
= send_action_menu
->items();
235 items
.push_back (MenuElem (_("New send"), mem_fun(*this, &RedirectBox::new_send
)));
236 items
.push_back (MenuElem (_("Show send controls"), mem_fun(*this, &RedirectBox::show_send_controls
)));
240 RedirectBox::show_send_controls ()
246 RedirectBox::new_send ()
252 RedirectBox::show_redirect_menu (gint arg
)
254 if (redirect_menu
== 0) {
255 redirect_menu
= build_redirect_menu ();
258 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/redirectmenu/newplugin"));
260 if (plugin_menu_item
) {
261 plugin_menu_item
->set_submenu (*_plugin_selector
.plugin_menu());
264 cut_action
->set_sensitive (can_cut_redirects ());
266 paste_action
->set_sensitive (!_rr_selection
.redirects
.empty());
268 redirect_menu
->popup (1, arg
);
272 RedirectBox::redirect_drag_begin (GdkDragContext
*context
)
274 redirect_drag_in_progress
= true;
278 RedirectBox::redirect_drag_end (GdkDragContext
*context
)
280 redirect_drag_in_progress
= false;
284 RedirectBox::redirect_button_press_event (GdkEventButton
*ev
)
287 TreeModel::Path path
;
288 TreeViewColumn
* column
;
291 boost::shared_ptr
<Redirect
> redirect
;
293 bool selected
= false;
295 if (redirect_display
.get_path_at_pos ((int)ev
->x
, (int)ev
->y
, path
, column
, cellx
, celly
)) {
296 if ((iter
= model
->get_iter (path
))) {
297 redirect
= (*iter
)[columns
.redirect
];
298 selected
= redirect_display
.get_selection()->is_selected (iter
);
303 if (redirect
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
305 if (_session
.engine().connected()) {
306 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
307 edit_redirect (redirect
);
311 } else if (redirect
&& ev
->button
== 1 && selected
) {
313 // this is purely informational but necessary
314 RedirectSelected (redirect
); // emit
316 } else if (!redirect
&& ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
) {
319 _plugin_selector
.show_manager ();
327 RedirectBox::redirect_button_release_event (GdkEventButton
*ev
)
330 TreeModel::Path path
;
331 TreeViewColumn
* column
;
334 boost::shared_ptr
<Redirect
> redirect
;
338 if (redirect_display
.get_path_at_pos ((int)ev
->x
, (int)ev
->y
, path
, column
, cellx
, celly
)) {
339 if ((iter
= model
->get_iter (path
))) {
340 redirect
= (*iter
)[columns
.redirect
];
344 if (redirect
&& Keyboard::is_delete_event (ev
)) {
346 Glib::signal_idle().connect (bind (mem_fun(*this, &RedirectBox::idle_delete_redirect
), boost::weak_ptr
<Redirect
>(redirect
)));
349 } else if (Keyboard::is_context_menu_event (ev
)) {
351 show_redirect_menu(ev
->time
);
354 } else if (redirect
&& Keyboard::is_button2_event (ev
)
356 && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))
360 /* button2-click with no modifiers */
362 redirect
->set_active (!redirect
->active(), this);
371 RedirectBox::build_redirect_menu ()
373 redirect_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/redirectmenu") );
374 redirect_menu
->set_name ("ArdourContextMenu");
378 return redirect_menu
;
382 RedirectBox::selection_changed ()
384 bool sensitive
= (redirect_display
.get_selection()->count_selected_rows()) ? true : false;
385 ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions
, sensitive
);
389 RedirectBox::select_all_redirects ()
391 redirect_display
.get_selection()->select_all();
395 RedirectBox::deselect_all_redirects ()
397 redirect_display
.get_selection()->unselect_all();
401 RedirectBox::choose_plugin ()
403 _plugin_selector
.set_interested_object (*this);
407 RedirectBox::use_plugins (const SelectedPlugins
& plugins
)
409 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
411 boost::shared_ptr
<Redirect
> redirect (new PluginInsert (_session
, *p
, _placement
));
413 uint32_t err_streams
;
415 if (Config
->get_new_plugins_active()) {
416 redirect
->set_active (true, this);
419 if (_route
->add_redirect (redirect
, this, &err_streams
)) {
420 weird_plugin_dialog (**p
, err_streams
, _route
);
423 if (Profile
->get_sae()) {
424 redirect
->set_active (true, 0);
426 redirect
->active_changed
.connect (bind (mem_fun (*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
)));
432 RedirectBox::weird_plugin_dialog (Plugin
& p
, uint32_t streams
, boost::shared_ptr
<IO
> io
)
434 ArdourDialog
dialog (_("ardour: weird plugin dialog"));
437 /* i hate this kind of code */
439 if (streams
> (unsigned)p
.get_info()->n_inputs
) {
440 label
.set_text (string_compose (_(
441 "You attempted to add a plugin (%1).\n"
442 "The plugin has %2 inputs\n"
443 "but at the insertion point, there are\n"
444 "%3 active signal streams.\n"
446 "This makes no sense - you are throwing away\n"
447 "part of the signal."),
449 p
.get_info()->n_inputs
,
451 } else if (streams
< (unsigned)p
.get_info()->n_inputs
) {
452 label
.set_text (string_compose (_(
453 "You attempted to add a plugin (%1).\n"
454 "The plugin has %2 inputs\n"
455 "but at the insertion point there are\n"
456 "only %3 active signal streams.\n"
458 "This makes no sense - unless the plugin supports\n"
459 "side-chain inputs. A future version of %4 will\n"
460 "support this type of configuration."),
462 p
.get_info()->n_inputs
,
463 streams
, PROGRAM_NAME
));
465 label
.set_text (string_compose (_(
466 "You attempted to add a plugin (%1).\n"
468 "The I/O configuration doesn't make sense:\n"
470 "The plugin has %2 inputs and %3 outputs.\n"
471 "The track/bus has %4 inputs and %5 outputs.\n"
472 "The insertion point, has %6 active signals.\n"
474 "%7 does not understand what to do in such situations.\n"),
476 p
.get_info()->n_inputs
,
477 p
.get_info()->n_outputs
,
480 streams
, PROGRAM_NAME
));
483 dialog
.set_border_width (PublicEditor::window_border_width
);
485 label
.set_alignment (0.5, 0.5);
486 dialog
.get_vbox()->pack_start (label
);
487 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
489 dialog
.set_name (X_("PluginIODialog"));
490 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
491 dialog
.set_modal (true);
498 RedirectBox::choose_insert ()
500 boost::shared_ptr
<Redirect
> redirect (new PortInsert (_session
, _placement
));
501 redirect
->active_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
)));
502 _route
->add_redirect (redirect
, this);
506 RedirectBox::choose_send ()
508 boost::shared_ptr
<Send
> send (new Send (_session
, _placement
));
510 /* XXX need redirect lock on route */
513 send
->ensure_io (0, _route
->max_redirect_outs(), false, this);
514 } catch (AudioEngine::PortRegistrationFailure
& err
) {
515 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
519 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
, false, true);
523 boost::shared_ptr
<Redirect
> r
= boost::static_pointer_cast
<Redirect
>(send
);
525 ios
->selector().Finished
.connect (bind (mem_fun(*this, &RedirectBox::send_io_finished
), boost::weak_ptr
<Redirect
>(r
), ios
));
529 RedirectBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Redirect
> weak_redirect
, IOSelectorWindow
* ios
)
531 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
538 case IOSelector::Cancelled
:
539 // redirect will go away when all shared_ptrs to it vanish
542 case IOSelector::Accepted
:
543 _route
->add_redirect (redirect
, this);
544 if (Profile
->get_sae()) {
545 redirect
->set_active (true, 0);
550 delete_when_idle (ios
);
554 RedirectBox::redisplay_redirects (void *src
)
556 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::redisplay_redirects
), src
));
558 if (no_redirect_redisplay
) {
562 ignore_delete
= true;
564 ignore_delete
= false;
566 redirect_active_connections
.clear ();
567 redirect_name_connections
.clear ();
569 void (RedirectBox::*pmf
)(boost::shared_ptr
<Redirect
>) = &RedirectBox::add_redirect_to_display
;
570 _route
->foreach_redirect (this, pmf
);
572 switch (_placement
) {
574 build_redirect_tooltip(redirect_eventbox
, _("Pre-fader inserts, sends & plugins:"));
577 build_redirect_tooltip(redirect_eventbox
, _("Post-fader inserts, sends & plugins:"));
583 RedirectBox::add_redirect_to_display (boost::shared_ptr
<Redirect
> redirect
)
585 if (redirect
->placement() != _placement
) {
589 Gtk::TreeModel::Row row
= *(model
->append());
591 row
[columns
.text
] = redirect_name (redirect
);
592 row
[columns
.redirect
] = redirect
;
594 show_redirect_active (redirect
);
596 redirect_active_connections
.push_back (redirect
->active_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
))));
597 redirect_name_connections
.push_back (redirect
->name_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_name
), boost::weak_ptr
<Redirect
>(redirect
))));
601 RedirectBox::redirect_name (boost::weak_ptr
<Redirect
> weak_redirect
)
603 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
609 boost::shared_ptr
<Send
> send
;
612 if (!redirect
->active()) {
616 if ((send
= boost::dynamic_pointer_cast
<Send
> (redirect
)) != 0) {
620 /* grab the send name out of its overall name */
622 string::size_type lbracket
, rbracket
;
623 lbracket
= send
->name().find ('[');
624 rbracket
= send
->name().find (']');
628 name_display
+= send
->name().substr (lbracket
+1, lbracket
-rbracket
-1);
631 name_display
+= PBD::short_version (send
->name().substr (lbracket
+1, lbracket
-rbracket
-1), 4);
639 name_display
+= redirect
->name();
642 name_display
+= PBD::short_version (redirect
->name(), 5);
648 if (!redirect
->active()) {
656 RedirectBox::build_redirect_tooltip (EventBox
& box
, string start
)
660 Gtk::TreeModel::Children children
= model
->children();
661 for(Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
662 Gtk::TreeModel::Row row
= *iter
;
664 tip
+= row
[columns
.text
];
666 ARDOUR_UI::instance()->tooltips().set_tip (box
, tip
);
670 RedirectBox::show_redirect_name (void* src
, boost::weak_ptr
<Redirect
> redirect
)
672 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_name
), src
, redirect
));
673 show_redirect_active (redirect
);
677 RedirectBox::show_redirect_active_r (Redirect
* r
, void *src
, boost::weak_ptr
<Redirect
> weak_redirect
)
679 show_redirect_active (weak_redirect
);
683 RedirectBox::show_redirect_active (boost::weak_ptr
<Redirect
> weak_redirect
)
685 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
691 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_active
), weak_redirect
));
693 Gtk::TreeModel::Children children
= model
->children();
694 Gtk::TreeModel::Children::iterator iter
= children
.begin();
696 while (iter
!= children
.end()) {
698 boost::shared_ptr
<Redirect
> r
= (*iter
)[columns
.redirect
];
702 (*iter
)[columns
.text
] = redirect_name (r
);
704 if (redirect
->active()) {
705 (*iter
)[columns
.color
] = *active_redirect_color
;
707 (*iter
)[columns
.color
] = *inactive_redirect_color
;
717 RedirectBox::row_deleted (const Gtk::TreeModel::Path
& path
)
719 if (!ignore_delete
) {
720 compute_redirect_sort_keys ();
725 RedirectBox::compute_redirect_sort_keys ()
727 uint32_t sort_key
= 0;
728 Gtk::TreeModel::Children children
= model
->children();
730 for (Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
731 boost::shared_ptr
<Redirect
> r
= (*iter
)[columns
.redirect
];
732 r
->set_sort_key (sort_key
);
736 if (_route
->sort_redirects ()) {
738 redisplay_redirects (0);
740 /* now tell them about the problem */
742 ArdourDialog
dialog (_("ardour: weird plugin dialog"));
746 You cannot reorder the plugins/sends/inserts\n\
747 in that way because the inputs and\n\
748 outputs will not work correctly."));
750 dialog
.get_vbox()->set_border_width (12);
751 dialog
.get_vbox()->pack_start (label
);
752 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
754 dialog
.set_name (X_("PluginIODialog"));
755 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
756 dialog
.set_modal (true);
764 RedirectBox::rename_redirects ()
766 vector
<boost::shared_ptr
<Redirect
> > to_be_renamed
;
768 get_selected_redirects (to_be_renamed
);
770 if (to_be_renamed
.empty()) {
774 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
775 rename_redirect (*i
);
780 RedirectBox::can_cut_redirects ()
782 vector
<boost::shared_ptr
<Redirect
> > sel
;
783 get_selected_redirects (sel
);
785 /* cut_redirects () does not cut inserts or sends */
786 for (vector
<boost::shared_ptr
<Redirect
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
788 if (boost::dynamic_pointer_cast
<PluginInsert
>(*i
) != 0) {
797 RedirectBox::cut_redirects ()
799 vector
<boost::shared_ptr
<Redirect
> > to_be_removed
;
801 get_selected_redirects (to_be_removed
);
803 if (to_be_removed
.empty()) {
807 /* this essentially transfers ownership of the redirect
808 of the redirect from the route to the mixer
812 _rr_selection
.set (to_be_removed
);
814 no_redirect_redisplay
= true;
815 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
816 // Do not cut inserts or sends
817 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0) {
818 void* gui
= (*i
)->get_gui ();
821 static_cast<Gtk::Widget
*>(gui
)->hide ();
824 if (_route
->remove_redirect (*i
, this)) {
826 _rr_selection
.remove (*i
);
829 _rr_selection
.remove (*i
);
833 no_redirect_redisplay
= false;
834 redisplay_redirects (this);
838 RedirectBox::copy_redirects ()
840 vector
<boost::shared_ptr
<Redirect
> > to_be_copied
;
841 vector
<boost::shared_ptr
<Redirect
> > copies
;
843 get_selected_redirects (to_be_copied
);
845 if (to_be_copied
.empty()) {
849 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
850 // Do not copy inserts
851 if ((boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0) ||
852 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0)) {
853 copies
.push_back (Redirect::clone (*i
));
857 _rr_selection
.set (copies
);
862 RedirectBox::delete_redirects ()
864 vector
<boost::shared_ptr
<Redirect
> > to_be_deleted
;
866 get_selected_redirects (to_be_deleted
);
868 if (to_be_deleted
.empty()) {
872 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_deleted
.begin(); i
!= to_be_deleted
.end(); ++i
) {
874 void* gui
= (*i
)->get_gui ();
877 static_cast<Gtk::Widget
*>(gui
)->hide ();
880 _route
->remove_redirect( *i
, this);
883 no_redirect_redisplay
= false;
884 redisplay_redirects (this);
888 RedirectBox::idle_delete_redirect (boost::weak_ptr
<Redirect
> weak_redirect
)
890 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
896 /* NOT copied to _mixer.selection() */
898 no_redirect_redisplay
= true;
900 void* gui
= redirect
->get_gui ();
903 static_cast<Gtk::Widget
*>(gui
)->hide ();
906 _route
->remove_redirect (redirect
, this);
907 no_redirect_redisplay
= false;
908 redisplay_redirects (this);
914 RedirectBox::rename_redirect (boost::shared_ptr
<Redirect
> redirect
)
916 ArdourPrompter
name_prompter (true);
918 name_prompter
.set_prompt (_("rename redirect"));
919 name_prompter
.set_initial_text (redirect
->name());
920 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
921 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
922 name_prompter
.show_all ();
924 switch (name_prompter
.run ()) {
926 case Gtk::RESPONSE_ACCEPT
:
927 name_prompter
.get_result (result
);
928 if (result
.length()) {
930 string test
= result
;
932 while (tries
< 100) {
933 if (_session
.io_name_is_legal (test
)) {
938 test
= string_compose ("%1-%2", result
, tries
);
942 redirect
->set_name (result
, this);
944 ARDOUR_UI::instance()->popup_error
945 (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result
));
955 RedirectBox::cut_redirect (boost::shared_ptr
<Redirect
> redirect
)
957 /* this essentially transfers ownership of the redirect
958 of the redirect from the route to the mixer
962 _rr_selection
.add (redirect
);
964 void* gui
= redirect
->get_gui ();
967 static_cast<Gtk::Widget
*>(gui
)->hide ();
970 no_redirect_redisplay
= true;
971 if (_route
->remove_redirect (redirect
, this)) {
972 _rr_selection
.remove (redirect
);
974 no_redirect_redisplay
= false;
975 redisplay_redirects (this);
979 RedirectBox::copy_redirect (boost::shared_ptr
<Redirect
> redirect
)
981 boost::shared_ptr
<Redirect
> copy
= Redirect::clone (redirect
);
982 _rr_selection
.add (copy
);
986 RedirectBox::paste_redirects ()
988 if (_rr_selection
.redirects
.empty()) {
992 paste_redirect_list (_rr_selection
.redirects
);
996 RedirectBox::paste_redirect_list (const list
<boost::shared_ptr
<Redirect
> >& redirects
)
998 list
<boost::shared_ptr
<Redirect
> > copies
;
1000 for (list
<boost::shared_ptr
<Redirect
> >::const_iterator i
= redirects
.begin(); i
!= redirects
.end(); ++i
) {
1002 boost::shared_ptr
<Redirect
> copy
= Redirect::clone (*i
);
1004 copy
->set_placement (_placement
, this);
1005 copies
.push_back (copy
);
1008 if (_route
->add_redirects (copies
, this)) {
1011 "Copying the set of redirects on the clipboard failed,\n\
1012 probably because the I/O configuration of the plugins\n\
1013 could not match the configuration of this track.");
1014 MessageDialog
am (msg
);
1020 RedirectBox::activate_redirect (boost::shared_ptr
<Redirect
> r
)
1022 r
->set_active (true, 0);
1026 RedirectBox::deactivate_redirect (boost::shared_ptr
<Redirect
> r
)
1028 r
->set_active (false, 0);
1032 RedirectBox::get_selected_redirects (vector
<boost::shared_ptr
<Redirect
> >& redirects
)
1034 vector
<Gtk::TreeModel::Path
> pathlist
= redirect_display
.get_selection()->get_selected_rows();
1036 for (vector
<Gtk::TreeModel::Path
>::iterator iter
= pathlist
.begin(); iter
!= pathlist
.end(); ++iter
) {
1037 redirects
.push_back ((*(model
->get_iter(*iter
)))[columns
.redirect
]);
1042 RedirectBox::for_selected_redirects (void (RedirectBox::*pmf
)(boost::shared_ptr
<Redirect
>))
1044 vector
<Gtk::TreeModel::Path
> pathlist
= redirect_display
.get_selection()->get_selected_rows();
1046 for (vector
<Gtk::TreeModel::Path
>::iterator iter
= pathlist
.begin(); iter
!= pathlist
.end(); ++iter
) {
1047 boost::shared_ptr
<Redirect
> redirect
= (*(model
->get_iter(*iter
)))[columns
.redirect
];
1048 (this->*pmf
)(redirect
);
1053 RedirectBox::clone_redirects ()
1055 RouteSelection
& routes (_rr_selection
.routes
);
1057 if (!routes
.empty()) {
1058 if (_route
->copy_redirects (*routes
.front(), _placement
)) {
1060 "Copying the set of redirects on the clipboard failed,\n\
1061 probably because the I/O configuration of the plugins\n\
1062 could not match the configuration of this track.");
1063 MessageDialog
am (msg
);
1070 RedirectBox::all_redirects_active (bool state
)
1072 _route
->all_redirects_active (_placement
, state
);
1076 RedirectBox::clear_redirects ()
1079 vector
<string
> choices
;
1081 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1082 if (_placement
== PreFader
) {
1083 prompt
= _("Do you really want to remove all pre-fader redirects from this track?\n"
1084 "(this cannot be undone)");
1086 prompt
= _("Do you really want to remove all post-fader redirects from this track?\n"
1087 "(this cannot be undone)");
1090 if (_placement
== PreFader
) {
1091 prompt
= _("Do you really want to remove all pre-fader redirects from this bus?\n"
1092 "(this cannot be undone)");
1094 prompt
= _("Do you really want to remove all post-fader redirects from this bus?\n"
1095 "(this cannot be undone)");
1099 choices
.push_back (_("Cancel"));
1100 choices
.push_back (_("Yes, remove them all"));
1102 Gtkmm2ext::Choice
prompter (prompt
, choices
);
1104 if (prompter
.run () == 1) {
1105 _route
->clear_redirects (_placement
, this);
1110 RedirectBox::edit_redirect (boost::shared_ptr
<Redirect
> redirect
)
1112 boost::shared_ptr
<Insert
> insert
;
1114 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1116 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1121 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) == 0) {
1125 if (!_session
.engine().connected()) {
1129 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (redirect
);
1131 SendUIWindow
*send_ui
;
1133 if (send
->get_gui() == 0) {
1135 send_ui
= new SendUIWindow (send
, _session
);
1137 send_ui
->set_title (send
->name());
1139 send
->set_gui (send_ui
);
1142 send_ui
= reinterpret_cast<SendUIWindow
*> (send
->get_gui());
1145 if (send_ui
->is_visible()) {
1146 send_ui
->get_window()->raise ();
1148 send_ui
->show_all ();
1149 send_ui
->present ();
1154 /* it's an insert */
1156 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1157 boost::shared_ptr
<PortInsert
> port_insert
;
1159 if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (insert
)) != 0) {
1161 PluginUIWindow
*plugin_ui
;
1163 /* these are both allowed to be null */
1165 Container
* toplevel
= get_toplevel();
1166 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1168 if (plugin_insert
->get_gui() == 0) {
1170 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1172 plugin_ui
->set_title (generate_redirect_title (plugin_insert
));
1174 plugin_insert
->set_gui (plugin_ui
);
1177 plugin_ui
= reinterpret_cast<PluginUIWindow
*> (plugin_insert
->get_gui());
1178 plugin_ui
->set_parent (win
);
1181 if (plugin_ui
->is_visible()) {
1182 plugin_ui
->get_window()->raise ();
1184 plugin_ui
->show_all ();
1185 plugin_ui
->present ();
1188 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (insert
)) != 0) {
1190 if (!_session
.engine().connected()) {
1191 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1196 PortInsertWindow
*io_selector
;
1198 if (port_insert
->get_gui() == 0) {
1199 io_selector
= new PortInsertWindow (_session
, port_insert
);
1200 port_insert
->set_gui (io_selector
);
1203 io_selector
= reinterpret_cast<PortInsertWindow
*> (port_insert
->get_gui());
1206 if (io_selector
->is_visible()) {
1207 io_selector
->get_window()->raise ();
1209 io_selector
->show_all ();
1210 io_selector
->present ();
1217 RedirectBox::enter_box (GdkEventCrossing
*ev
, RedirectBox
* rb
)
1219 switch (ev
->detail
) {
1220 case GDK_NOTIFY_INFERIOR
:
1223 case GDK_NOTIFY_VIRTUAL
:
1227 _current_redirect_box
= rb
;
1234 RedirectBox::register_actions ()
1236 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("redirectmenu"));
1237 Glib::RefPtr
<Action
> act
;
1240 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"), sigc::ptr_fun (RedirectBox::rb_choose_plugin
));
1242 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"), sigc::ptr_fun (RedirectBox::rb_choose_insert
));
1243 ActionManager::jack_sensitive_actions
.push_back (act
);
1244 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."), sigc::ptr_fun (RedirectBox::rb_choose_send
));
1245 ActionManager::jack_sensitive_actions
.push_back (act
);
1247 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear"), sigc::ptr_fun (RedirectBox::rb_clear
));
1249 /* standard editing stuff */
1250 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"), sigc::ptr_fun (RedirectBox::rb_cut
));
1251 ActionManager::plugin_selection_sensitive_actions
.push_back (cut_action
);
1252 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"), sigc::ptr_fun (RedirectBox::rb_copy
));
1253 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1255 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"), sigc::ptr_fun (RedirectBox::rb_delete
));
1256 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1258 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"), sigc::ptr_fun (RedirectBox::rb_paste
));
1259 act
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"), sigc::ptr_fun (RedirectBox::rb_rename
));
1260 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1261 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"), sigc::ptr_fun (RedirectBox::rb_select_all
));
1262 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"), sigc::ptr_fun (RedirectBox::rb_deselect_all
));
1265 act
= ActionManager::register_action (popup_act_grp
, X_("activate"), _("Activate"), sigc::ptr_fun (RedirectBox::rb_activate
));
1266 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1267 act
= ActionManager::register_action (popup_act_grp
, X_("deactivate"), _("Deactivate"), sigc::ptr_fun (RedirectBox::rb_deactivate
));
1268 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1269 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"), sigc::ptr_fun (RedirectBox::rb_activate_all
));
1270 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"), sigc::ptr_fun (RedirectBox::rb_deactivate_all
));
1273 act
= ActionManager::register_action (popup_act_grp
, X_("edit"), _("Edit"), sigc::ptr_fun (RedirectBox::rb_edit
));
1274 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1276 ActionManager::add_action_group (popup_act_grp
);
1282 RedirectBox::rb_choose_plugin ()
1284 if (_current_redirect_box
== 0) {
1287 _current_redirect_box
->choose_plugin ();
1291 RedirectBox::rb_choose_insert ()
1293 if (_current_redirect_box
== 0) {
1296 _current_redirect_box
->choose_insert ();
1300 RedirectBox::rb_choose_send ()
1302 if (_current_redirect_box
== 0) {
1305 _current_redirect_box
->choose_send ();
1309 RedirectBox::rb_clear ()
1311 if (_current_redirect_box
== 0) {
1315 _current_redirect_box
->clear_redirects ();
1319 RedirectBox::rb_cut ()
1321 if (_current_redirect_box
== 0) {
1325 _current_redirect_box
->cut_redirects ();
1329 RedirectBox::rb_delete ()
1331 if (_current_redirect_box
== 0) {
1335 _current_redirect_box
->delete_redirects ();
1339 RedirectBox::rb_copy ()
1341 if (_current_redirect_box
== 0) {
1344 _current_redirect_box
->copy_redirects ();
1348 RedirectBox::rb_paste ()
1350 if (_current_redirect_box
== 0) {
1354 _current_redirect_box
->paste_redirects ();
1358 RedirectBox::rb_rename ()
1360 if (_current_redirect_box
== 0) {
1363 _current_redirect_box
->rename_redirects ();
1367 RedirectBox::rb_select_all ()
1369 if (_current_redirect_box
== 0) {
1373 _current_redirect_box
->select_all_redirects ();
1377 RedirectBox::rb_deselect_all ()
1379 if (_current_redirect_box
== 0) {
1383 _current_redirect_box
->deselect_all_redirects ();
1387 RedirectBox::rb_activate ()
1389 if (_current_redirect_box
== 0) {
1393 _current_redirect_box
->for_selected_redirects (&RedirectBox::activate_redirect
);
1397 RedirectBox::rb_deactivate ()
1399 if (_current_redirect_box
== 0) {
1402 _current_redirect_box
->for_selected_redirects (&RedirectBox::deactivate_redirect
);
1406 RedirectBox::rb_activate_all ()
1408 if (_current_redirect_box
== 0) {
1412 _current_redirect_box
->all_redirects_active (true);
1416 RedirectBox::rb_deactivate_all ()
1418 if (_current_redirect_box
== 0) {
1421 _current_redirect_box
->all_redirects_active (false);
1425 RedirectBox::rb_edit ()
1427 if (_current_redirect_box
== 0) {
1431 _current_redirect_box
->for_selected_redirects (&RedirectBox::edit_redirect
);
1435 RedirectBox::route_name_changed (void* src
)
1437 boost::shared_ptr
<Redirect
> redirect
;
1438 boost::shared_ptr
<Insert
> insert
;
1439 Gtk::TreeModel::Children children
= model
->children();
1441 for (Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1442 Gtk::TreeModel::Row row
= *iter
;
1444 redirect
= row
[columns
.redirect
];
1446 void* gui
= redirect
->get_gui();
1452 /* rename editor windows for sends and plugins */
1454 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) == 0) {
1455 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (redirect
);
1456 static_cast<Window
*>(gui
)->set_title (send
->name());
1458 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1460 if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (insert
)) != 0) {
1461 static_cast<Window
*>(gui
)->set_title (generate_redirect_title (plugin_insert
));
1468 RedirectBox::generate_redirect_title (boost::shared_ptr
<PluginInsert
> pi
)
1470 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
1471 string::size_type email_pos
;
1473 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
1474 maker
= maker
.substr (0, email_pos
- 1);
1477 if (maker
.length() > 32) {
1478 maker
= maker
.substr (0, 32);
1482 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);