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>
37 #include <gtkmm2ext/window_title.h>
39 #include <ardour/ardour.h>
40 #include <ardour/session.h>
41 #include <ardour/audioengine.h>
42 #include <ardour/route.h>
43 #include <ardour/audio_track.h>
44 #include <ardour/audio_diskstream.h>
45 #include <ardour/send.h>
46 #include <ardour/insert.h>
47 #include <ardour/ladspa_plugin.h>
48 #include <ardour/connection.h>
49 #include <ardour/session_connection.h>
50 #include <ardour/profile.h>
52 #include "ardour_ui.h"
53 #include "ardour_dialog.h"
54 #include "public_editor.h"
55 #include "redirect_box.h"
57 #include "plugin_selector.h"
58 #include "route_redirect_selection.h"
61 #include "plugin_ui.h"
63 #include "io_selector.h"
65 #include "gui_thread.h"
69 #ifdef HAVE_AUDIOUNITS
74 using namespace ARDOUR
;
78 using namespace Gtkmm2ext
;
80 RedirectBox
* RedirectBox::_current_redirect_box
= 0;
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_object_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
)
154 connections
.clear ();
158 connections
.push_back (_route
->redirects_changed
.connect (mem_fun(*this, &RedirectBox::redisplay_redirects
)));
159 connections
.push_back (_route
->GoingAway
.connect (mem_fun (*this, &RedirectBox::route_going_away
)));
161 redisplay_redirects (0);
165 RedirectBox::route_going_away ()
167 /* don't keep updating display as redirects are deleted */
168 no_redirect_redisplay
= true;
172 RedirectBox::object_drop (string type
, uint32_t cnt
, const boost::shared_ptr
<Redirect
>* ptr
)
174 cerr
<< "Object drop, type = " << type
<< " cnt = " << cnt
<< endl
;
176 if (type
!= "redirects" || cnt
== 0 || !ptr
) {
180 /* do something with the dropped redirects */
182 list
<boost::shared_ptr
<Redirect
> > redirects
;
184 for (uint32_t n
= 0; n
< cnt
; ++n
) {
185 redirects
.push_back (ptr
[n
]);
188 paste_redirect_list (redirects
);
192 RedirectBox::update()
194 redisplay_redirects (0);
199 RedirectBox::set_width (Width w
)
208 redisplay_redirects (0);
212 RedirectBox::remove_redirect_gui (boost::shared_ptr
<Redirect
> redirect
)
214 boost::shared_ptr
<Insert
> insert
;
215 boost::shared_ptr
<Send
> send
;
216 boost::shared_ptr
<PortInsert
> port_insert
;
218 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) != 0) {
220 if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (insert
)) != 0) {
221 PortInsertUI
*io_selector
= reinterpret_cast<PortInsertUI
*> (port_insert
->get_gui());
222 port_insert
->set_gui (0);
226 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (insert
)) != 0) {
227 SendUIWindow
*sui
= reinterpret_cast<SendUIWindow
*> (send
->get_gui());
234 RedirectBox::build_send_action_menu ()
237 using namespace Menu_Helpers
;
239 send_action_menu
= new Menu
;
240 send_action_menu
->set_name ("ArdourContextMenu");
241 MenuList
& items
= send_action_menu
->items();
243 items
.push_back (MenuElem (_("New send"), mem_fun(*this, &RedirectBox::new_send
)));
244 items
.push_back (MenuElem (_("Show send controls"), mem_fun(*this, &RedirectBox::show_send_controls
)));
248 RedirectBox::show_send_controls ()
254 RedirectBox::new_send ()
260 RedirectBox::show_redirect_menu (gint arg
)
262 if (redirect_menu
== 0) {
263 redirect_menu
= build_redirect_menu ();
266 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/redirectmenu/newplugin"));
268 if (plugin_menu_item
) {
269 plugin_menu_item
->set_submenu (_plugin_selector
.plugin_menu());
272 paste_action
->set_sensitive (!_rr_selection
.redirects
.empty());
274 redirect_menu
->popup (1, arg
);
278 RedirectBox::redirect_drag_begin (GdkDragContext
*context
)
280 redirect_drag_in_progress
= true;
284 RedirectBox::redirect_drag_end (GdkDragContext
*context
)
286 redirect_drag_in_progress
= false;
290 RedirectBox::redirect_button_press_event (GdkEventButton
*ev
)
293 TreeModel::Path path
;
294 TreeViewColumn
* column
;
297 boost::shared_ptr
<Redirect
> redirect
;
299 bool selected
= false;
301 if (redirect_display
.get_path_at_pos ((int)ev
->x
, (int)ev
->y
, path
, column
, cellx
, celly
)) {
302 if ((iter
= model
->get_iter (path
))) {
303 redirect
= (*iter
)[columns
.redirect
];
304 selected
= redirect_display
.get_selection()->is_selected (iter
);
309 if (redirect
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
311 if (_session
.engine().connected()) {
312 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
313 edit_redirect (redirect
);
317 } else if (redirect
&& ev
->button
== 1 && selected
) {
319 // this is purely informational but necessary
320 RedirectSelected (redirect
); // emit
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
) && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))) {
356 /* button2-click with no modifiers */
358 redirect
->set_active (!redirect
->active(), this);
367 RedirectBox::build_redirect_menu ()
369 redirect_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/redirectmenu") );
370 redirect_menu
->set_name ("ArdourContextMenu");
374 return redirect_menu
;
378 RedirectBox::selection_changed ()
380 bool sensitive
= (redirect_display
.get_selection()->count_selected_rows()) ? true : false;
381 ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions
, sensitive
);
385 RedirectBox::select_all_redirects ()
387 redirect_display
.get_selection()->select_all();
391 RedirectBox::deselect_all_redirects ()
393 redirect_display
.get_selection()->unselect_all();
397 RedirectBox::choose_plugin ()
399 _plugin_selector
.set_interested_object (*this);
403 RedirectBox::use_plugins (const SelectedPlugins
& plugins
)
405 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
407 boost::shared_ptr
<Redirect
> redirect (new PluginInsert (_session
, *p
, _placement
));
409 uint32_t err_streams
;
411 if (_route
->add_redirect (redirect
, this, &err_streams
)) {
412 weird_plugin_dialog (**p
, err_streams
, _route
);
415 if (Profile
->get_sae()) {
416 redirect
->set_active (true, 0);
418 redirect
->active_changed
.connect (bind (mem_fun (*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
)));
424 RedirectBox::weird_plugin_dialog (Plugin
& p
, uint32_t streams
, boost::shared_ptr
<IO
> io
)
426 ArdourDialog
dialog (_("ardour: weird plugin dialog"));
429 /* i hate this kind of code */
431 if (streams
> (unsigned)p
.get_info()->n_inputs
) {
432 label
.set_text (string_compose (_(
433 "You attempted to add a plugin (%1).\n"
434 "The plugin has %2 inputs\n"
435 "but at the insertion point, there are\n"
436 "%3 active signal streams.\n"
438 "This makes no sense - you are throwing away\n"
439 "part of the signal."),
441 p
.get_info()->n_inputs
,
443 } else if (streams
< (unsigned)p
.get_info()->n_inputs
) {
444 label
.set_text (string_compose (_(
445 "You attempted to add a plugin (%1).\n"
446 "The plugin has %2 inputs\n"
447 "but at the insertion point there are\n"
448 "only %3 active signal streams.\n"
450 "This makes no sense - unless the plugin supports\n"
451 "side-chain inputs. A future version of Ardour will\n"
452 "support this type of configuration."),
454 p
.get_info()->n_inputs
,
457 label
.set_text (string_compose (_(
458 "You attempted to add a plugin (%1).\n"
460 "The I/O configuration doesn't make sense:\n"
462 "The plugin has %2 inputs and %3 outputs.\n"
463 "The track/bus has %4 inputs and %5 outputs.\n"
464 "The insertion point, has %6 active signals.\n"
466 "Ardour does not understand what to do in such situations.\n"),
468 p
.get_info()->n_inputs
,
469 p
.get_info()->n_outputs
,
475 dialog
.set_border_width (PublicEditor::window_border_width
);
477 label
.set_alignment (0.5, 0.5);
478 dialog
.get_vbox()->pack_start (label
);
479 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
481 dialog
.set_name (X_("PluginIODialog"));
482 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
483 dialog
.set_modal (true);
490 RedirectBox::choose_insert ()
492 boost::shared_ptr
<Redirect
> redirect (new PortInsert (_session
, _placement
));
493 redirect
->active_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
)));
494 _route
->add_redirect (redirect
, this);
498 RedirectBox::choose_send ()
500 boost::shared_ptr
<Send
> send (new Send (_session
, _placement
));
502 /* XXX need redirect lock on route */
505 send
->ensure_io (0, _route
->max_redirect_outs(), false, this);
506 } catch (AudioEngine::PortRegistrationFailure
& err
) {
507 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
511 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
, false, true);
515 boost::shared_ptr
<Redirect
> r
= boost::static_pointer_cast
<Redirect
>(send
);
517 ios
->selector().Finished
.connect (bind (mem_fun(*this, &RedirectBox::send_io_finished
), boost::weak_ptr
<Redirect
>(r
), ios
));
521 RedirectBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Redirect
> weak_redirect
, IOSelectorWindow
* ios
)
523 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
530 case IOSelector::Cancelled
:
531 // redirect will go away when all shared_ptrs to it vanish
534 case IOSelector::Accepted
:
535 _route
->add_redirect (redirect
, this);
536 if (Profile
->get_sae()) {
537 redirect
->set_active (true, 0);
542 delete_when_idle (ios
);
546 RedirectBox::redisplay_redirects (void *src
)
548 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::redisplay_redirects
), src
));
550 if (no_redirect_redisplay
) {
554 ignore_delete
= true;
556 ignore_delete
= false;
558 redirect_active_connections
.clear ();
559 redirect_name_connections
.clear ();
561 void (RedirectBox::*pmf
)(boost::shared_ptr
<Redirect
>) = &RedirectBox::add_redirect_to_display
;
562 _route
->foreach_redirect (this, pmf
);
564 switch (_placement
) {
566 build_redirect_tooltip(redirect_eventbox
, _("Pre-fader inserts, sends & plugins:"));
569 build_redirect_tooltip(redirect_eventbox
, _("Post-fader inserts, sends & plugins:"));
575 RedirectBox::add_redirect_to_display (boost::shared_ptr
<Redirect
> redirect
)
577 if (redirect
->placement() != _placement
) {
581 Gtk::TreeModel::Row row
= *(model
->append());
583 row
[columns
.text
] = redirect_name (redirect
);
584 row
[columns
.redirect
] = redirect
;
586 show_redirect_active (redirect
);
588 redirect_active_connections
.push_back (redirect
->active_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
))));
589 redirect_name_connections
.push_back (redirect
->name_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_name
), boost::weak_ptr
<Redirect
>(redirect
))));
593 RedirectBox::redirect_name (boost::weak_ptr
<Redirect
> weak_redirect
)
595 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
601 boost::shared_ptr
<Send
> send
;
604 if (!redirect
->active()) {
608 if ((send
= boost::dynamic_pointer_cast
<Send
> (redirect
)) != 0) {
612 /* grab the send name out of its overall name */
614 string::size_type lbracket
, rbracket
;
615 lbracket
= send
->name().find ('[');
616 rbracket
= send
->name().find (']');
620 name_display
+= send
->name().substr (lbracket
+1, lbracket
-rbracket
-1);
623 name_display
+= PBD::short_version (send
->name().substr (lbracket
+1, lbracket
-rbracket
-1), 4);
631 name_display
+= redirect
->name();
634 name_display
+= PBD::short_version (redirect
->name(), 5);
640 if (!redirect
->active()) {
648 RedirectBox::build_redirect_tooltip (EventBox
& box
, string start
)
652 Gtk::TreeModel::Children children
= model
->children();
653 for(Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
654 Gtk::TreeModel::Row row
= *iter
;
656 tip
+= row
[columns
.text
];
658 ARDOUR_UI::instance()->tooltips().set_tip (box
, tip
);
662 RedirectBox::show_redirect_name (void* src
, boost::weak_ptr
<Redirect
> redirect
)
664 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_name
), src
, redirect
));
665 show_redirect_active (redirect
);
669 RedirectBox::show_redirect_active_r (Redirect
* r
, void *src
, boost::weak_ptr
<Redirect
> weak_redirect
)
671 show_redirect_active (weak_redirect
);
675 RedirectBox::show_redirect_active (boost::weak_ptr
<Redirect
> weak_redirect
)
677 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
683 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_active
), weak_redirect
));
685 Gtk::TreeModel::Children children
= model
->children();
686 Gtk::TreeModel::Children::iterator iter
= children
.begin();
688 while (iter
!= children
.end()) {
690 boost::shared_ptr
<Redirect
> r
= (*iter
)[columns
.redirect
];
694 (*iter
)[columns
.text
] = redirect_name (r
);
696 if (redirect
->active()) {
697 (*iter
)[columns
.color
] = *active_redirect_color
;
699 (*iter
)[columns
.color
] = *inactive_redirect_color
;
709 RedirectBox::row_deleted (const Gtk::TreeModel::Path
& path
)
711 if (!ignore_delete
) {
712 compute_redirect_sort_keys ();
717 RedirectBox::compute_redirect_sort_keys ()
719 uint32_t sort_key
= 0;
720 Gtk::TreeModel::Children children
= model
->children();
722 for (Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
723 boost::shared_ptr
<Redirect
> r
= (*iter
)[columns
.redirect
];
724 r
->set_sort_key (sort_key
);
728 if (_route
->sort_redirects ()) {
730 redisplay_redirects (0);
732 /* now tell them about the problem */
734 ArdourDialog
dialog (_("ardour: weird plugin dialog"));
738 You cannot reorder this set of redirects\n\
739 in that way because the inputs and\n\
740 outputs do not work correctly."));
742 dialog
.get_vbox()->pack_start (label
);
743 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
745 dialog
.set_name (X_("PluginIODialog"));
746 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
747 dialog
.set_modal (true);
755 RedirectBox::rename_redirects ()
757 vector
<boost::shared_ptr
<Redirect
> > to_be_renamed
;
759 get_selected_redirects (to_be_renamed
);
761 if (to_be_renamed
.empty()) {
765 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
766 rename_redirect (*i
);
771 RedirectBox::cut_redirects ()
773 vector
<boost::shared_ptr
<Redirect
> > to_be_removed
;
775 get_selected_redirects (to_be_removed
);
777 if (to_be_removed
.empty()) {
781 /* this essentially transfers ownership of the redirect
782 of the redirect from the route to the mixer
786 _rr_selection
.set (to_be_removed
);
788 no_redirect_redisplay
= true;
789 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
790 // Do not cut inserts or sends
791 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0) {
792 void* gui
= (*i
)->get_gui ();
795 static_cast<Gtk::Widget
*>(gui
)->hide ();
798 if (_route
->remove_redirect (*i
, this)) {
800 _rr_selection
.remove (*i
);
803 _rr_selection
.remove (*i
);
807 no_redirect_redisplay
= false;
808 redisplay_redirects (this);
812 RedirectBox::copy_redirects ()
814 vector
<boost::shared_ptr
<Redirect
> > to_be_copied
;
815 vector
<boost::shared_ptr
<Redirect
> > copies
;
817 get_selected_redirects (to_be_copied
);
819 if (to_be_copied
.empty()) {
823 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
824 // Do not copy inserts or sends
825 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0) {
826 copies
.push_back (Redirect::clone (*i
));
830 _rr_selection
.set (copies
);
835 RedirectBox::delete_redirects ()
837 vector
<boost::shared_ptr
<Redirect
> > to_be_deleted
;
839 get_selected_redirects (to_be_deleted
);
841 if (to_be_deleted
.empty()) {
845 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_deleted
.begin(); i
!= to_be_deleted
.end(); ++i
) {
847 void* gui
= (*i
)->get_gui ();
850 static_cast<Gtk::Widget
*>(gui
)->hide ();
853 _route
->remove_redirect( *i
, this);
856 no_redirect_redisplay
= false;
857 redisplay_redirects (this);
861 RedirectBox::idle_delete_redirect (boost::weak_ptr
<Redirect
> weak_redirect
)
863 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
869 /* NOT copied to _mixer.selection() */
871 no_redirect_redisplay
= true;
873 void* gui
= redirect
->get_gui ();
876 static_cast<Gtk::Widget
*>(gui
)->hide ();
879 _route
->remove_redirect (redirect
, this);
880 no_redirect_redisplay
= false;
881 redisplay_redirects (this);
887 RedirectBox::rename_redirect (boost::shared_ptr
<Redirect
> redirect
)
889 ArdourPrompter
name_prompter (true);
891 name_prompter
.set_prompt (_("rename redirect"));
892 name_prompter
.set_initial_text (redirect
->name());
893 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
894 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
895 name_prompter
.show_all ();
897 switch (name_prompter
.run ()) {
899 case Gtk::RESPONSE_ACCEPT
:
900 name_prompter
.get_result (result
);
901 if (result
.length()) {
902 redirect
->set_name (result
, this);
911 RedirectBox::cut_redirect (boost::shared_ptr
<Redirect
> redirect
)
913 /* this essentially transfers ownership of the redirect
914 of the redirect from the route to the mixer
918 _rr_selection
.add (redirect
);
920 void* gui
= redirect
->get_gui ();
923 static_cast<Gtk::Widget
*>(gui
)->hide ();
926 no_redirect_redisplay
= true;
927 if (_route
->remove_redirect (redirect
, this)) {
928 _rr_selection
.remove (redirect
);
930 no_redirect_redisplay
= false;
931 redisplay_redirects (this);
935 RedirectBox::copy_redirect (boost::shared_ptr
<Redirect
> redirect
)
937 boost::shared_ptr
<Redirect
> copy
= Redirect::clone (redirect
);
938 _rr_selection
.add (copy
);
942 RedirectBox::paste_redirects ()
944 if (_rr_selection
.redirects
.empty()) {
948 paste_redirect_list (_rr_selection
.redirects
);
952 RedirectBox::paste_redirect_list (list
<boost::shared_ptr
<Redirect
> >& redirects
)
954 list
<boost::shared_ptr
<Redirect
> > copies
;
956 for (list
<boost::shared_ptr
<Redirect
> >::iterator i
= redirects
.begin(); i
!= redirects
.end(); ++i
) {
958 boost::shared_ptr
<Redirect
> copy
= Redirect::clone (*i
);
960 copy
->set_placement (_placement
, this);
961 copies
.push_back (copy
);
964 if (_route
->add_redirects (copies
, this)) {
967 "Copying the set of redirects on the clipboard failed,\n\
968 probably because the I/O configuration of the plugins\n\
969 could not match the configuration of this track.");
970 MessageDialog
am (msg
);
976 RedirectBox::activate_redirect (boost::shared_ptr
<Redirect
> r
)
978 r
->set_active (true, 0);
982 RedirectBox::deactivate_redirect (boost::shared_ptr
<Redirect
> r
)
984 r
->set_active (false, 0);
988 RedirectBox::get_selected_redirects (vector
<boost::shared_ptr
<Redirect
> >& redirects
)
990 vector
<Gtk::TreeModel::Path
> pathlist
= redirect_display
.get_selection()->get_selected_rows();
992 for (vector
<Gtk::TreeModel::Path
>::iterator iter
= pathlist
.begin(); iter
!= pathlist
.end(); ++iter
) {
993 redirects
.push_back ((*(model
->get_iter(*iter
)))[columns
.redirect
]);
998 RedirectBox::for_selected_redirects (void (RedirectBox::*pmf
)(boost::shared_ptr
<Redirect
>))
1000 vector
<Gtk::TreeModel::Path
> pathlist
= redirect_display
.get_selection()->get_selected_rows();
1002 for (vector
<Gtk::TreeModel::Path
>::iterator iter
= pathlist
.begin(); iter
!= pathlist
.end(); ++iter
) {
1003 boost::shared_ptr
<Redirect
> redirect
= (*(model
->get_iter(*iter
)))[columns
.redirect
];
1004 (this->*pmf
)(redirect
);
1009 RedirectBox::clone_redirects ()
1011 RouteSelection
& routes (_rr_selection
.routes
);
1013 if (!routes
.empty()) {
1014 if (_route
->copy_redirects (*routes
.front(), _placement
)) {
1016 "Copying the set of redirects on the clipboard failed,\n\
1017 probably because the I/O configuration of the plugins\n\
1018 could not match the configuration of this track.");
1019 MessageDialog
am (msg
);
1026 RedirectBox::all_redirects_active (bool state
)
1028 _route
->all_redirects_active (_placement
, state
);
1032 RedirectBox::clear_redirects ()
1035 vector
<string
> choices
;
1037 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1038 if (_placement
== PreFader
) {
1039 prompt
= _("Do you really want to remove all pre-fader redirects from this track?\n"
1040 "(this cannot be undone)");
1042 prompt
= _("Do you really want to remove all post-fader redirects from this track?\n"
1043 "(this cannot be undone)");
1046 if (_placement
== PreFader
) {
1047 prompt
= _("Do you really want to remove all pre-fader redirects from this bus?\n"
1048 "(this cannot be undone)");
1050 prompt
= _("Do you really want to remove all post-fader redirects from this bus?\n"
1051 "(this cannot be undone)");
1055 choices
.push_back (_("Cancel"));
1056 choices
.push_back (_("Yes, remove them all"));
1058 Gtkmm2ext::Choice
prompter (prompt
, choices
);
1060 if (prompter
.run () == 1) {
1061 _route
->clear_redirects (_placement
, this);
1066 RedirectBox::edit_redirect (boost::shared_ptr
<Redirect
> redirect
)
1068 boost::shared_ptr
<Insert
> insert
;
1070 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1072 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1077 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) == 0) {
1081 if (!_session
.engine().connected()) {
1085 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (redirect
);
1087 SendUIWindow
*send_ui
;
1089 if (send
->get_gui() == 0) {
1091 send_ui
= new SendUIWindow (send
, _session
);
1093 WindowTitle
title(Glib::get_application_name());
1094 title
+= send
->name();
1095 send_ui
->set_title (title
.get_string());
1097 send
->set_gui (send_ui
);
1100 send_ui
= reinterpret_cast<SendUIWindow
*> (send
->get_gui());
1103 if (send_ui
->is_visible()) {
1104 send_ui
->get_window()->raise ();
1106 send_ui
->show_all ();
1107 send_ui
->present ();
1112 /* it's an insert */
1114 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1115 boost::shared_ptr
<PortInsert
> port_insert
;
1117 if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (insert
)) != 0) {
1119 PluginUIWindow
*plugin_ui
;
1121 /* these are both allowed to be null */
1123 Container
* toplevel
= get_toplevel();
1124 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1126 if (plugin_insert
->get_gui() == 0) {
1128 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1130 WindowTitle
title(Glib::get_application_name());
1131 title
+= generate_redirect_title (plugin_insert
);
1132 plugin_ui
->set_title (title
.get_string());
1134 plugin_insert
->set_gui (plugin_ui
);
1136 // change window title when route name is changed
1137 _route
->name_changed
.connect (bind (mem_fun(*this, &RedirectBox::route_name_changed
), plugin_ui
, boost::weak_ptr
<PluginInsert
> (plugin_insert
)));
1140 plugin_ui
= reinterpret_cast<PluginUIWindow
*> (plugin_insert
->get_gui());
1141 plugin_ui
->set_parent (win
);
1144 if (plugin_ui
->is_visible()) {
1145 plugin_ui
->get_window()->raise ();
1147 plugin_ui
->show_all ();
1148 plugin_ui
->present ();
1151 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (insert
)) != 0) {
1153 if (!_session
.engine().connected()) {
1154 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1159 PortInsertWindow
*io_selector
;
1161 if (port_insert
->get_gui() == 0) {
1162 io_selector
= new PortInsertWindow (_session
, port_insert
);
1163 port_insert
->set_gui (io_selector
);
1166 io_selector
= reinterpret_cast<PortInsertWindow
*> (port_insert
->get_gui());
1169 if (io_selector
->is_visible()) {
1170 io_selector
->get_window()->raise ();
1172 io_selector
->show_all ();
1173 io_selector
->present ();
1180 RedirectBox::enter_box (GdkEventCrossing
*ev
, RedirectBox
* rb
)
1182 switch (ev
->detail
) {
1183 case GDK_NOTIFY_INFERIOR
:
1186 case GDK_NOTIFY_VIRTUAL
:
1190 _current_redirect_box
= rb
;
1197 RedirectBox::register_actions ()
1199 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("redirectmenu"));
1200 Glib::RefPtr
<Action
> act
;
1203 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"), sigc::ptr_fun (RedirectBox::rb_choose_plugin
));
1205 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"), sigc::ptr_fun (RedirectBox::rb_choose_insert
));
1206 ActionManager::jack_sensitive_actions
.push_back (act
);
1207 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."), sigc::ptr_fun (RedirectBox::rb_choose_send
));
1208 ActionManager::jack_sensitive_actions
.push_back (act
);
1210 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear"), sigc::ptr_fun (RedirectBox::rb_clear
));
1212 /* standard editing stuff */
1213 act
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"), sigc::ptr_fun (RedirectBox::rb_cut
));
1214 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1215 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"), sigc::ptr_fun (RedirectBox::rb_copy
));
1216 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1218 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"), sigc::ptr_fun (RedirectBox::rb_delete
));
1219 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1221 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"), sigc::ptr_fun (RedirectBox::rb_paste
));
1222 act
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"), sigc::ptr_fun (RedirectBox::rb_rename
));
1223 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1224 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"), sigc::ptr_fun (RedirectBox::rb_select_all
));
1225 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"), sigc::ptr_fun (RedirectBox::rb_deselect_all
));
1228 act
= ActionManager::register_action (popup_act_grp
, X_("activate"), _("Activate"), sigc::ptr_fun (RedirectBox::rb_activate
));
1229 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1230 act
= ActionManager::register_action (popup_act_grp
, X_("deactivate"), _("Deactivate"), sigc::ptr_fun (RedirectBox::rb_deactivate
));
1231 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1232 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"), sigc::ptr_fun (RedirectBox::rb_activate_all
));
1233 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"), sigc::ptr_fun (RedirectBox::rb_deactivate_all
));
1236 act
= ActionManager::register_action (popup_act_grp
, X_("edit"), _("Edit"), sigc::ptr_fun (RedirectBox::rb_edit
));
1237 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1239 ActionManager::add_action_group (popup_act_grp
);
1245 RedirectBox::rb_choose_plugin ()
1247 if (_current_redirect_box
== 0) {
1250 _current_redirect_box
->choose_plugin ();
1254 RedirectBox::rb_choose_insert ()
1256 if (_current_redirect_box
== 0) {
1259 _current_redirect_box
->choose_insert ();
1263 RedirectBox::rb_choose_send ()
1265 if (_current_redirect_box
== 0) {
1268 _current_redirect_box
->choose_send ();
1272 RedirectBox::rb_clear ()
1274 if (_current_redirect_box
== 0) {
1278 _current_redirect_box
->clear_redirects ();
1282 RedirectBox::rb_cut ()
1284 if (_current_redirect_box
== 0) {
1288 _current_redirect_box
->cut_redirects ();
1292 RedirectBox::rb_delete ()
1294 if (_current_redirect_box
== 0) {
1298 _current_redirect_box
->delete_redirects ();
1302 RedirectBox::rb_copy ()
1304 if (_current_redirect_box
== 0) {
1307 _current_redirect_box
->copy_redirects ();
1311 RedirectBox::rb_paste ()
1313 if (_current_redirect_box
== 0) {
1317 _current_redirect_box
->paste_redirects ();
1321 RedirectBox::rb_rename ()
1323 if (_current_redirect_box
== 0) {
1326 _current_redirect_box
->rename_redirects ();
1330 RedirectBox::rb_select_all ()
1332 if (_current_redirect_box
== 0) {
1336 _current_redirect_box
->select_all_redirects ();
1340 RedirectBox::rb_deselect_all ()
1342 if (_current_redirect_box
== 0) {
1346 _current_redirect_box
->deselect_all_redirects ();
1350 RedirectBox::rb_activate ()
1352 if (_current_redirect_box
== 0) {
1356 _current_redirect_box
->for_selected_redirects (&RedirectBox::activate_redirect
);
1360 RedirectBox::rb_deactivate ()
1362 if (_current_redirect_box
== 0) {
1365 _current_redirect_box
->for_selected_redirects (&RedirectBox::deactivate_redirect
);
1369 RedirectBox::rb_activate_all ()
1371 if (_current_redirect_box
== 0) {
1375 _current_redirect_box
->all_redirects_active (true);
1379 RedirectBox::rb_deactivate_all ()
1381 if (_current_redirect_box
== 0) {
1384 _current_redirect_box
->all_redirects_active (false);
1388 RedirectBox::rb_edit ()
1390 if (_current_redirect_box
== 0) {
1394 _current_redirect_box
->for_selected_redirects (&RedirectBox::edit_redirect
);
1398 RedirectBox::route_name_changed (void* src
, PluginUIWindow
* plugin_ui
, boost::weak_ptr
<PluginInsert
> wpi
)
1400 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RedirectBox::route_name_changed
), src
, plugin_ui
, wpi
));
1401 boost::shared_ptr
<PluginInsert
> pi (wpi
.lock());
1405 WindowTitle
title(Glib::get_application_name());
1406 title
+= generate_redirect_title (pi
);
1407 plugin_ui
->set_title (title
.get_string());
1412 RedirectBox::generate_redirect_title (boost::shared_ptr
<PluginInsert
> pi
)
1414 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
1415 string::size_type email_pos
;
1417 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
1418 maker
= maker
.substr (0, email_pos
- 1);
1421 if (maker
.length() > 32) {
1422 maker
= maker
.substr (0, 32);
1426 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);