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::cut_action
;
82 RefPtr
<Action
> RedirectBox::paste_action
;
83 bool RedirectBox::get_colors
= true;
84 Gdk::Color
* RedirectBox::active_redirect_color
;
85 Gdk::Color
* RedirectBox::inactive_redirect_color
;
87 RedirectBox::RedirectBox (Placement pcmnt
, Session
& sess
, PluginSelector
&plugsel
,
88 RouteRedirectSelection
& rsel
, bool owner_is_mixer
)
90 _owner_is_mixer (owner_is_mixer
),
92 _plugin_selector(plugsel
),
96 active_redirect_color
= new Gdk::Color
;
97 inactive_redirect_color
= new Gdk::Color
;
98 set_color (*active_redirect_color
, rgba_from_style ("RedirectSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_ACTIVE
, false ));
99 set_color (*inactive_redirect_color
, rgba_from_style ("RedirectSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL
, false ));
105 send_action_menu
= 0;
106 redirect_drag_in_progress
= false;
107 no_redirect_redisplay
= false;
108 ignore_delete
= false;
110 model
= ListStore::create(columns
);
112 RefPtr
<TreeSelection
> selection
= redirect_display
.get_selection();
113 selection
->set_mode (Gtk::SELECTION_MULTIPLE
);
114 selection
->signal_changed().connect (mem_fun (*this, &RedirectBox::selection_changed
));
116 redirect_display
.set_model (model
);
117 redirect_display
.append_column (X_("notshown"), columns
.text
);
118 redirect_display
.set_name ("RedirectSelector");
119 redirect_display
.set_headers_visible (false);
120 redirect_display
.set_reorderable (true);
121 redirect_display
.set_size_request (-1, 40);
122 redirect_display
.get_column(0)->set_sizing(TREE_VIEW_COLUMN_FIXED
);
123 redirect_display
.get_column(0)->set_fixed_width(48);
124 redirect_display
.add_object_drag (columns
.redirect
.index(), "redirects");
125 redirect_display
.signal_drop
.connect (mem_fun (*this, &RedirectBox::object_drop
));
127 TreeViewColumn
* name_col
= redirect_display
.get_column(0);
128 CellRendererText
* renderer
= dynamic_cast<CellRendererText
*>(redirect_display
.get_column_cell_renderer (0));
129 name_col
->add_attribute(renderer
->property_foreground_gdk(), columns
.color
);
131 redirect_scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
133 model
->signal_row_deleted().connect (mem_fun (*this, &RedirectBox::row_deleted
));
135 redirect_scroller
.add (redirect_display
);
136 redirect_eventbox
.add (redirect_scroller
);
138 redirect_scroller
.set_size_request (-1, 40);
140 pack_start (redirect_eventbox
, true, true);
142 redirect_eventbox
.signal_enter_notify_event().connect (bind (sigc::ptr_fun (RedirectBox::enter_box
), this));
144 redirect_display
.signal_button_press_event().connect (mem_fun(*this, &RedirectBox::redirect_button_press_event
), false);
145 redirect_display
.signal_button_release_event().connect (mem_fun(*this, &RedirectBox::redirect_button_release_event
));
148 RedirectBox::~RedirectBox ()
153 RedirectBox::set_route (boost::shared_ptr
<Route
> r
)
155 connections
.clear ();
159 connections
.push_back (_route
->redirects_changed
.connect (mem_fun(*this, &RedirectBox::redisplay_redirects
)));
160 connections
.push_back (_route
->GoingAway
.connect (mem_fun (*this, &RedirectBox::route_going_away
)));
161 connections
.push_back (_route
->name_changed
.connect (mem_fun(*this, &RedirectBox::route_name_changed
)));
163 redisplay_redirects (0);
167 RedirectBox::route_going_away ()
169 /* don't keep updating display as redirects are deleted */
170 no_redirect_redisplay
= true;
174 RedirectBox::object_drop (const list
<boost::shared_ptr
<Redirect
> >& redirects
)
176 paste_redirect_list (redirects
);
180 RedirectBox::update()
182 redisplay_redirects (0);
186 RedirectBox::set_width (Width w
)
195 redisplay_redirects (0);
199 RedirectBox::remove_redirect_gui (boost::shared_ptr
<Redirect
> redirect
)
201 boost::shared_ptr
<Insert
> insert
;
202 boost::shared_ptr
<Send
> send
;
203 boost::shared_ptr
<PortInsert
> port_insert
;
205 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) != 0) {
207 if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (insert
)) != 0) {
208 PortInsertUI
*io_selector
= reinterpret_cast<PortInsertUI
*> (port_insert
->get_gui());
209 port_insert
->set_gui (0);
213 } else if ((send
= boost::dynamic_pointer_cast
<Send
> (insert
)) != 0) {
214 SendUIWindow
*sui
= reinterpret_cast<SendUIWindow
*> (send
->get_gui());
221 RedirectBox::build_send_action_menu ()
224 using namespace Menu_Helpers
;
226 send_action_menu
= new Menu
;
227 send_action_menu
->set_name ("ArdourContextMenu");
228 MenuList
& items
= send_action_menu
->items();
230 items
.push_back (MenuElem (_("New send"), mem_fun(*this, &RedirectBox::new_send
)));
231 items
.push_back (MenuElem (_("Show send controls"), mem_fun(*this, &RedirectBox::show_send_controls
)));
235 RedirectBox::show_send_controls ()
241 RedirectBox::new_send ()
247 RedirectBox::show_redirect_menu (gint arg
)
249 if (redirect_menu
== 0) {
250 redirect_menu
= build_redirect_menu ();
253 Gtk::MenuItem
* plugin_menu_item
= dynamic_cast<Gtk::MenuItem
*>(ActionManager::get_widget("/redirectmenu/newplugin"));
255 if (plugin_menu_item
) {
256 plugin_menu_item
->set_submenu (_plugin_selector
.plugin_menu());
259 cut_action
->set_sensitive (can_cut_redirects ());
261 paste_action
->set_sensitive (!_rr_selection
.redirects
.empty());
263 redirect_menu
->popup (1, arg
);
267 RedirectBox::redirect_drag_begin (GdkDragContext
*context
)
269 redirect_drag_in_progress
= true;
273 RedirectBox::redirect_drag_end (GdkDragContext
*context
)
275 redirect_drag_in_progress
= false;
279 RedirectBox::redirect_button_press_event (GdkEventButton
*ev
)
282 TreeModel::Path path
;
283 TreeViewColumn
* column
;
286 boost::shared_ptr
<Redirect
> redirect
;
288 bool selected
= false;
290 if (redirect_display
.get_path_at_pos ((int)ev
->x
, (int)ev
->y
, path
, column
, cellx
, celly
)) {
291 if ((iter
= model
->get_iter (path
))) {
292 redirect
= (*iter
)[columns
.redirect
];
293 selected
= redirect_display
.get_selection()->is_selected (iter
);
298 if (redirect
&& (Keyboard::is_edit_event (ev
) || (ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
))) {
300 if (_session
.engine().connected()) {
301 /* XXX giving an error message here is hard, because we may be in the midst of a button press */
302 edit_redirect (redirect
);
306 } else if (redirect
&& ev
->button
== 1 && selected
) {
308 // this is purely informational but necessary
309 RedirectSelected (redirect
); // emit
311 } else if (!redirect
&& ev
->button
== 1 && ev
->type
== GDK_2BUTTON_PRESS
) {
314 _plugin_selector
.show_manager ();
322 RedirectBox::redirect_button_release_event (GdkEventButton
*ev
)
325 TreeModel::Path path
;
326 TreeViewColumn
* column
;
329 boost::shared_ptr
<Redirect
> redirect
;
333 if (redirect_display
.get_path_at_pos ((int)ev
->x
, (int)ev
->y
, path
, column
, cellx
, celly
)) {
334 if ((iter
= model
->get_iter (path
))) {
335 redirect
= (*iter
)[columns
.redirect
];
339 if (redirect
&& Keyboard::is_delete_event (ev
)) {
341 Glib::signal_idle().connect (bind (mem_fun(*this, &RedirectBox::idle_delete_redirect
), boost::weak_ptr
<Redirect
>(redirect
)));
344 } else if (Keyboard::is_context_menu_event (ev
)) {
346 show_redirect_menu(ev
->time
);
349 } else if (redirect
&& Keyboard::is_button2_event (ev
) && (Keyboard::no_modifier_keys_pressed (ev
) && ((ev
->state
& Gdk::BUTTON2_MASK
) == Gdk::BUTTON2_MASK
))) {
351 /* button2-click with no modifiers */
353 redirect
->set_active (!redirect
->active(), this);
362 RedirectBox::build_redirect_menu ()
364 redirect_menu
= dynamic_cast<Gtk::Menu
*>(ActionManager::get_widget("/redirectmenu") );
365 redirect_menu
->set_name ("ArdourContextMenu");
369 return redirect_menu
;
373 RedirectBox::selection_changed ()
375 bool sensitive
= (redirect_display
.get_selection()->count_selected_rows()) ? true : false;
376 ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions
, sensitive
);
380 RedirectBox::select_all_redirects ()
382 redirect_display
.get_selection()->select_all();
386 RedirectBox::deselect_all_redirects ()
388 redirect_display
.get_selection()->unselect_all();
392 RedirectBox::choose_plugin ()
394 _plugin_selector
.set_interested_object (*this);
398 RedirectBox::use_plugins (const SelectedPlugins
& plugins
)
400 for (SelectedPlugins::const_iterator p
= plugins
.begin(); p
!= plugins
.end(); ++p
) {
402 boost::shared_ptr
<Redirect
> redirect (new PluginInsert (_session
, *p
, _placement
));
404 uint32_t err_streams
;
406 if (Config
->get_new_plugins_active()) {
407 redirect
->set_active (true, this);
410 if (_route
->add_redirect (redirect
, this, &err_streams
)) {
411 weird_plugin_dialog (**p
, err_streams
, _route
);
414 if (Profile
->get_sae()) {
415 redirect
->set_active (true, 0);
417 redirect
->active_changed
.connect (bind (mem_fun (*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
)));
423 RedirectBox::weird_plugin_dialog (Plugin
& p
, uint32_t streams
, boost::shared_ptr
<IO
> io
)
425 ArdourDialog
dialog (_("ardour: weird plugin dialog"));
428 /* i hate this kind of code */
430 if (streams
> (unsigned)p
.get_info()->n_inputs
) {
431 label
.set_text (string_compose (_(
432 "You attempted to add a plugin (%1).\n"
433 "The plugin has %2 inputs\n"
434 "but at the insertion point, there are\n"
435 "%3 active signal streams.\n"
437 "This makes no sense - you are throwing away\n"
438 "part of the signal."),
440 p
.get_info()->n_inputs
,
442 } else if (streams
< (unsigned)p
.get_info()->n_inputs
) {
443 label
.set_text (string_compose (_(
444 "You attempted to add a plugin (%1).\n"
445 "The plugin has %2 inputs\n"
446 "but at the insertion point there are\n"
447 "only %3 active signal streams.\n"
449 "This makes no sense - unless the plugin supports\n"
450 "side-chain inputs. A future version of Ardour will\n"
451 "support this type of configuration."),
453 p
.get_info()->n_inputs
,
456 label
.set_text (string_compose (_(
457 "You attempted to add a plugin (%1).\n"
459 "The I/O configuration doesn't make sense:\n"
461 "The plugin has %2 inputs and %3 outputs.\n"
462 "The track/bus has %4 inputs and %5 outputs.\n"
463 "The insertion point, has %6 active signals.\n"
465 "Ardour does not understand what to do in such situations.\n"),
467 p
.get_info()->n_inputs
,
468 p
.get_info()->n_outputs
,
474 dialog
.set_border_width (PublicEditor::window_border_width
);
476 label
.set_alignment (0.5, 0.5);
477 dialog
.get_vbox()->pack_start (label
);
478 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
480 dialog
.set_name (X_("PluginIODialog"));
481 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
482 dialog
.set_modal (true);
489 RedirectBox::choose_insert ()
491 boost::shared_ptr
<Redirect
> redirect (new PortInsert (_session
, _placement
));
492 redirect
->active_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
)));
493 _route
->add_redirect (redirect
, this);
497 RedirectBox::choose_send ()
499 boost::shared_ptr
<Send
> send (new Send (_session
, _placement
));
501 /* XXX need redirect lock on route */
504 send
->ensure_io (0, _route
->max_redirect_outs(), false, this);
505 } catch (AudioEngine::PortRegistrationFailure
& err
) {
506 error
<< string_compose (_("Cannot set up new send: %1"), err
.what()) << endmsg
;
510 IOSelectorWindow
*ios
= new IOSelectorWindow (_session
, send
, false, true);
514 boost::shared_ptr
<Redirect
> r
= boost::static_pointer_cast
<Redirect
>(send
);
516 ios
->selector().Finished
.connect (bind (mem_fun(*this, &RedirectBox::send_io_finished
), boost::weak_ptr
<Redirect
>(r
), ios
));
520 RedirectBox::send_io_finished (IOSelector::Result r
, boost::weak_ptr
<Redirect
> weak_redirect
, IOSelectorWindow
* ios
)
522 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
529 case IOSelector::Cancelled
:
530 // redirect will go away when all shared_ptrs to it vanish
533 case IOSelector::Accepted
:
534 _route
->add_redirect (redirect
, this);
535 if (Profile
->get_sae()) {
536 redirect
->set_active (true, 0);
541 delete_when_idle (ios
);
545 RedirectBox::redisplay_redirects (void *src
)
547 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::redisplay_redirects
), src
));
549 if (no_redirect_redisplay
) {
553 ignore_delete
= true;
555 ignore_delete
= false;
557 redirect_active_connections
.clear ();
558 redirect_name_connections
.clear ();
560 void (RedirectBox::*pmf
)(boost::shared_ptr
<Redirect
>) = &RedirectBox::add_redirect_to_display
;
561 _route
->foreach_redirect (this, pmf
);
563 switch (_placement
) {
565 build_redirect_tooltip(redirect_eventbox
, _("Pre-fader inserts, sends & plugins:"));
568 build_redirect_tooltip(redirect_eventbox
, _("Post-fader inserts, sends & plugins:"));
574 RedirectBox::add_redirect_to_display (boost::shared_ptr
<Redirect
> redirect
)
576 if (redirect
->placement() != _placement
) {
580 Gtk::TreeModel::Row row
= *(model
->append());
582 row
[columns
.text
] = redirect_name (redirect
);
583 row
[columns
.redirect
] = redirect
;
585 show_redirect_active (redirect
);
587 redirect_active_connections
.push_back (redirect
->active_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_active_r
), boost::weak_ptr
<Redirect
>(redirect
))));
588 redirect_name_connections
.push_back (redirect
->name_changed
.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_name
), boost::weak_ptr
<Redirect
>(redirect
))));
592 RedirectBox::redirect_name (boost::weak_ptr
<Redirect
> weak_redirect
)
594 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
600 boost::shared_ptr
<Send
> send
;
603 if (!redirect
->active()) {
607 if ((send
= boost::dynamic_pointer_cast
<Send
> (redirect
)) != 0) {
611 /* grab the send name out of its overall name */
613 string::size_type lbracket
, rbracket
;
614 lbracket
= send
->name().find ('[');
615 rbracket
= send
->name().find (']');
619 name_display
+= send
->name().substr (lbracket
+1, lbracket
-rbracket
-1);
622 name_display
+= PBD::short_version (send
->name().substr (lbracket
+1, lbracket
-rbracket
-1), 4);
630 name_display
+= redirect
->name();
633 name_display
+= PBD::short_version (redirect
->name(), 5);
639 if (!redirect
->active()) {
647 RedirectBox::build_redirect_tooltip (EventBox
& box
, string start
)
651 Gtk::TreeModel::Children children
= model
->children();
652 for(Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
653 Gtk::TreeModel::Row row
= *iter
;
655 tip
+= row
[columns
.text
];
657 ARDOUR_UI::instance()->tooltips().set_tip (box
, tip
);
661 RedirectBox::show_redirect_name (void* src
, boost::weak_ptr
<Redirect
> redirect
)
663 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_name
), src
, redirect
));
664 show_redirect_active (redirect
);
668 RedirectBox::show_redirect_active_r (Redirect
* r
, void *src
, boost::weak_ptr
<Redirect
> weak_redirect
)
670 show_redirect_active (weak_redirect
);
674 RedirectBox::show_redirect_active (boost::weak_ptr
<Redirect
> weak_redirect
)
676 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
682 ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_active
), weak_redirect
));
684 Gtk::TreeModel::Children children
= model
->children();
685 Gtk::TreeModel::Children::iterator iter
= children
.begin();
687 while (iter
!= children
.end()) {
689 boost::shared_ptr
<Redirect
> r
= (*iter
)[columns
.redirect
];
693 (*iter
)[columns
.text
] = redirect_name (r
);
695 if (redirect
->active()) {
696 (*iter
)[columns
.color
] = *active_redirect_color
;
698 (*iter
)[columns
.color
] = *inactive_redirect_color
;
708 RedirectBox::row_deleted (const Gtk::TreeModel::Path
& path
)
710 if (!ignore_delete
) {
711 compute_redirect_sort_keys ();
716 RedirectBox::compute_redirect_sort_keys ()
718 uint32_t sort_key
= 0;
719 Gtk::TreeModel::Children children
= model
->children();
721 for (Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
722 boost::shared_ptr
<Redirect
> r
= (*iter
)[columns
.redirect
];
723 r
->set_sort_key (sort_key
);
727 if (_route
->sort_redirects ()) {
729 redisplay_redirects (0);
731 /* now tell them about the problem */
733 ArdourDialog
dialog (_("ardour: weird plugin dialog"));
737 You cannot reorder this set of redirects\n\
738 in that way because the inputs and\n\
739 outputs do not work correctly."));
741 dialog
.get_vbox()->pack_start (label
);
742 dialog
.add_button (Stock::OK
, RESPONSE_ACCEPT
);
744 dialog
.set_name (X_("PluginIODialog"));
745 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
746 dialog
.set_modal (true);
754 RedirectBox::rename_redirects ()
756 vector
<boost::shared_ptr
<Redirect
> > to_be_renamed
;
758 get_selected_redirects (to_be_renamed
);
760 if (to_be_renamed
.empty()) {
764 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_renamed
.begin(); i
!= to_be_renamed
.end(); ++i
) {
765 rename_redirect (*i
);
770 RedirectBox::can_cut_redirects ()
772 vector
<boost::shared_ptr
<Redirect
> > sel
;
773 get_selected_redirects (sel
);
775 /* cut_redirects () does not cut inserts or sends */
776 for (vector
<boost::shared_ptr
<Redirect
> >::const_iterator i
= sel
.begin (); i
!= sel
.end (); ++i
) {
778 if (boost::dynamic_pointer_cast
<PluginInsert
>(*i
) != 0) {
787 RedirectBox::cut_redirects ()
789 vector
<boost::shared_ptr
<Redirect
> > to_be_removed
;
791 get_selected_redirects (to_be_removed
);
793 if (to_be_removed
.empty()) {
797 /* this essentially transfers ownership of the redirect
798 of the redirect from the route to the mixer
802 _rr_selection
.set (to_be_removed
);
804 no_redirect_redisplay
= true;
805 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_removed
.begin(); i
!= to_be_removed
.end(); ++i
) {
806 // Do not cut inserts or sends
807 if (boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0) {
808 void* gui
= (*i
)->get_gui ();
811 static_cast<Gtk::Widget
*>(gui
)->hide ();
814 if (_route
->remove_redirect (*i
, this)) {
816 _rr_selection
.remove (*i
);
819 _rr_selection
.remove (*i
);
823 no_redirect_redisplay
= false;
824 redisplay_redirects (this);
828 RedirectBox::copy_redirects ()
830 vector
<boost::shared_ptr
<Redirect
> > to_be_copied
;
831 vector
<boost::shared_ptr
<Redirect
> > copies
;
833 get_selected_redirects (to_be_copied
);
835 if (to_be_copied
.empty()) {
839 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_copied
.begin(); i
!= to_be_copied
.end(); ++i
) {
840 // Do not copy inserts
841 if ((boost::dynamic_pointer_cast
<PluginInsert
>((*i
)) != 0) ||
842 (boost::dynamic_pointer_cast
<Send
>((*i
)) != 0)) {
843 copies
.push_back (Redirect::clone (*i
));
847 _rr_selection
.set (copies
);
852 RedirectBox::delete_redirects ()
854 vector
<boost::shared_ptr
<Redirect
> > to_be_deleted
;
856 get_selected_redirects (to_be_deleted
);
858 if (to_be_deleted
.empty()) {
862 for (vector
<boost::shared_ptr
<Redirect
> >::iterator i
= to_be_deleted
.begin(); i
!= to_be_deleted
.end(); ++i
) {
864 void* gui
= (*i
)->get_gui ();
867 static_cast<Gtk::Widget
*>(gui
)->hide ();
870 _route
->remove_redirect( *i
, this);
873 no_redirect_redisplay
= false;
874 redisplay_redirects (this);
878 RedirectBox::idle_delete_redirect (boost::weak_ptr
<Redirect
> weak_redirect
)
880 boost::shared_ptr
<Redirect
> redirect (weak_redirect
.lock());
886 /* NOT copied to _mixer.selection() */
888 no_redirect_redisplay
= true;
890 void* gui
= redirect
->get_gui ();
893 static_cast<Gtk::Widget
*>(gui
)->hide ();
896 _route
->remove_redirect (redirect
, this);
897 no_redirect_redisplay
= false;
898 redisplay_redirects (this);
904 RedirectBox::rename_redirect (boost::shared_ptr
<Redirect
> redirect
)
906 ArdourPrompter
name_prompter (true);
908 name_prompter
.set_prompt (_("rename redirect"));
909 name_prompter
.set_initial_text (redirect
->name());
910 name_prompter
.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT
);
911 name_prompter
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
912 name_prompter
.show_all ();
914 switch (name_prompter
.run ()) {
916 case Gtk::RESPONSE_ACCEPT
:
917 name_prompter
.get_result (result
);
918 if (result
.length()) {
919 redirect
->set_name (result
, this);
928 RedirectBox::cut_redirect (boost::shared_ptr
<Redirect
> redirect
)
930 /* this essentially transfers ownership of the redirect
931 of the redirect from the route to the mixer
935 _rr_selection
.add (redirect
);
937 void* gui
= redirect
->get_gui ();
940 static_cast<Gtk::Widget
*>(gui
)->hide ();
943 no_redirect_redisplay
= true;
944 if (_route
->remove_redirect (redirect
, this)) {
945 _rr_selection
.remove (redirect
);
947 no_redirect_redisplay
= false;
948 redisplay_redirects (this);
952 RedirectBox::copy_redirect (boost::shared_ptr
<Redirect
> redirect
)
954 boost::shared_ptr
<Redirect
> copy
= Redirect::clone (redirect
);
955 _rr_selection
.add (copy
);
959 RedirectBox::paste_redirects ()
961 if (_rr_selection
.redirects
.empty()) {
965 paste_redirect_list (_rr_selection
.redirects
);
969 RedirectBox::paste_redirect_list (const list
<boost::shared_ptr
<Redirect
> >& redirects
)
971 list
<boost::shared_ptr
<Redirect
> > copies
;
973 for (list
<boost::shared_ptr
<Redirect
> >::const_iterator i
= redirects
.begin(); i
!= redirects
.end(); ++i
) {
975 boost::shared_ptr
<Redirect
> copy
= Redirect::clone (*i
);
977 copy
->set_placement (_placement
, this);
978 copies
.push_back (copy
);
981 if (_route
->add_redirects (copies
, this)) {
984 "Copying the set of redirects on the clipboard failed,\n\
985 probably because the I/O configuration of the plugins\n\
986 could not match the configuration of this track.");
987 MessageDialog
am (msg
);
993 RedirectBox::activate_redirect (boost::shared_ptr
<Redirect
> r
)
995 r
->set_active (true, 0);
999 RedirectBox::deactivate_redirect (boost::shared_ptr
<Redirect
> r
)
1001 r
->set_active (false, 0);
1005 RedirectBox::get_selected_redirects (vector
<boost::shared_ptr
<Redirect
> >& redirects
)
1007 vector
<Gtk::TreeModel::Path
> pathlist
= redirect_display
.get_selection()->get_selected_rows();
1009 for (vector
<Gtk::TreeModel::Path
>::iterator iter
= pathlist
.begin(); iter
!= pathlist
.end(); ++iter
) {
1010 redirects
.push_back ((*(model
->get_iter(*iter
)))[columns
.redirect
]);
1015 RedirectBox::for_selected_redirects (void (RedirectBox::*pmf
)(boost::shared_ptr
<Redirect
>))
1017 vector
<Gtk::TreeModel::Path
> pathlist
= redirect_display
.get_selection()->get_selected_rows();
1019 for (vector
<Gtk::TreeModel::Path
>::iterator iter
= pathlist
.begin(); iter
!= pathlist
.end(); ++iter
) {
1020 boost::shared_ptr
<Redirect
> redirect
= (*(model
->get_iter(*iter
)))[columns
.redirect
];
1021 (this->*pmf
)(redirect
);
1026 RedirectBox::clone_redirects ()
1028 RouteSelection
& routes (_rr_selection
.routes
);
1030 if (!routes
.empty()) {
1031 if (_route
->copy_redirects (*routes
.front(), _placement
)) {
1033 "Copying the set of redirects on the clipboard failed,\n\
1034 probably because the I/O configuration of the plugins\n\
1035 could not match the configuration of this track.");
1036 MessageDialog
am (msg
);
1043 RedirectBox::all_redirects_active (bool state
)
1045 _route
->all_redirects_active (_placement
, state
);
1049 RedirectBox::clear_redirects ()
1052 vector
<string
> choices
;
1054 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1055 if (_placement
== PreFader
) {
1056 prompt
= _("Do you really want to remove all pre-fader redirects from this track?\n"
1057 "(this cannot be undone)");
1059 prompt
= _("Do you really want to remove all post-fader redirects from this track?\n"
1060 "(this cannot be undone)");
1063 if (_placement
== PreFader
) {
1064 prompt
= _("Do you really want to remove all pre-fader redirects from this bus?\n"
1065 "(this cannot be undone)");
1067 prompt
= _("Do you really want to remove all post-fader redirects from this bus?\n"
1068 "(this cannot be undone)");
1072 choices
.push_back (_("Cancel"));
1073 choices
.push_back (_("Yes, remove them all"));
1075 Gtkmm2ext::Choice
prompter (prompt
, choices
);
1077 if (prompter
.run () == 1) {
1078 _route
->clear_redirects (_placement
, this);
1083 RedirectBox::edit_redirect (boost::shared_ptr
<Redirect
> redirect
)
1085 boost::shared_ptr
<Insert
> insert
;
1087 if (boost::dynamic_pointer_cast
<AudioTrack
>(_route
) != 0) {
1089 if (boost::dynamic_pointer_cast
<AudioTrack
> (_route
)->freeze_state() == AudioTrack::Frozen
) {
1094 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) == 0) {
1098 if (!_session
.engine().connected()) {
1102 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (redirect
);
1104 SendUIWindow
*send_ui
;
1106 if (send
->get_gui() == 0) {
1108 send_ui
= new SendUIWindow (send
, _session
);
1110 WindowTitle
title(Glib::get_application_name());
1111 title
+= send
->name();
1112 send_ui
->set_title (title
.get_string());
1114 send
->set_gui (send_ui
);
1117 send_ui
= reinterpret_cast<SendUIWindow
*> (send
->get_gui());
1120 if (send_ui
->is_visible()) {
1121 send_ui
->get_window()->raise ();
1123 send_ui
->show_all ();
1124 send_ui
->present ();
1129 /* it's an insert */
1131 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1132 boost::shared_ptr
<PortInsert
> port_insert
;
1134 if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (insert
)) != 0) {
1136 PluginUIWindow
*plugin_ui
;
1138 /* these are both allowed to be null */
1140 Container
* toplevel
= get_toplevel();
1141 Window
* win
= dynamic_cast<Gtk::Window
*>(toplevel
);
1143 if (plugin_insert
->get_gui() == 0) {
1145 plugin_ui
= new PluginUIWindow (win
, plugin_insert
);
1147 WindowTitle
title(Glib::get_application_name());
1148 title
+= generate_redirect_title (plugin_insert
);
1149 plugin_ui
->set_title (title
.get_string());
1151 plugin_insert
->set_gui (plugin_ui
);
1154 plugin_ui
= reinterpret_cast<PluginUIWindow
*> (plugin_insert
->get_gui());
1155 plugin_ui
->set_parent (win
);
1158 if (plugin_ui
->is_visible()) {
1159 plugin_ui
->get_window()->raise ();
1161 plugin_ui
->show_all ();
1162 plugin_ui
->present ();
1165 } else if ((port_insert
= boost::dynamic_pointer_cast
<PortInsert
> (insert
)) != 0) {
1167 if (!_session
.engine().connected()) {
1168 MessageDialog
msg ( _("Not connected to JACK - no I/O changes are possible"));
1173 PortInsertWindow
*io_selector
;
1175 if (port_insert
->get_gui() == 0) {
1176 io_selector
= new PortInsertWindow (_session
, port_insert
);
1177 port_insert
->set_gui (io_selector
);
1180 io_selector
= reinterpret_cast<PortInsertWindow
*> (port_insert
->get_gui());
1183 if (io_selector
->is_visible()) {
1184 io_selector
->get_window()->raise ();
1186 io_selector
->show_all ();
1187 io_selector
->present ();
1194 RedirectBox::enter_box (GdkEventCrossing
*ev
, RedirectBox
* rb
)
1196 switch (ev
->detail
) {
1197 case GDK_NOTIFY_INFERIOR
:
1200 case GDK_NOTIFY_VIRTUAL
:
1204 _current_redirect_box
= rb
;
1211 RedirectBox::register_actions ()
1213 Glib::RefPtr
<Gtk::ActionGroup
> popup_act_grp
= Gtk::ActionGroup::create(X_("redirectmenu"));
1214 Glib::RefPtr
<Action
> act
;
1217 ActionManager::register_action (popup_act_grp
, X_("newplugin"), _("New Plugin"), sigc::ptr_fun (RedirectBox::rb_choose_plugin
));
1219 act
= ActionManager::register_action (popup_act_grp
, X_("newinsert"), _("New Insert"), sigc::ptr_fun (RedirectBox::rb_choose_insert
));
1220 ActionManager::jack_sensitive_actions
.push_back (act
);
1221 act
= ActionManager::register_action (popup_act_grp
, X_("newsend"), _("New Send ..."), sigc::ptr_fun (RedirectBox::rb_choose_send
));
1222 ActionManager::jack_sensitive_actions
.push_back (act
);
1224 ActionManager::register_action (popup_act_grp
, X_("clear"), _("Clear"), sigc::ptr_fun (RedirectBox::rb_clear
));
1226 /* standard editing stuff */
1227 cut_action
= ActionManager::register_action (popup_act_grp
, X_("cut"), _("Cut"), sigc::ptr_fun (RedirectBox::rb_cut
));
1228 ActionManager::plugin_selection_sensitive_actions
.push_back (cut_action
);
1229 act
= ActionManager::register_action (popup_act_grp
, X_("copy"), _("Copy"), sigc::ptr_fun (RedirectBox::rb_copy
));
1230 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1232 act
= ActionManager::register_action (popup_act_grp
, X_("delete"), _("Delete"), sigc::ptr_fun (RedirectBox::rb_delete
));
1233 ActionManager::plugin_selection_sensitive_actions
.push_back(act
); // ??
1235 paste_action
= ActionManager::register_action (popup_act_grp
, X_("paste"), _("Paste"), sigc::ptr_fun (RedirectBox::rb_paste
));
1236 act
= ActionManager::register_action (popup_act_grp
, X_("rename"), _("Rename"), sigc::ptr_fun (RedirectBox::rb_rename
));
1237 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1238 ActionManager::register_action (popup_act_grp
, X_("selectall"), _("Select All"), sigc::ptr_fun (RedirectBox::rb_select_all
));
1239 ActionManager::register_action (popup_act_grp
, X_("deselectall"), _("Deselect All"), sigc::ptr_fun (RedirectBox::rb_deselect_all
));
1242 act
= ActionManager::register_action (popup_act_grp
, X_("activate"), _("Activate"), sigc::ptr_fun (RedirectBox::rb_activate
));
1243 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1244 act
= ActionManager::register_action (popup_act_grp
, X_("deactivate"), _("Deactivate"), sigc::ptr_fun (RedirectBox::rb_deactivate
));
1245 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1246 ActionManager::register_action (popup_act_grp
, X_("activate_all"), _("Activate all"), sigc::ptr_fun (RedirectBox::rb_activate_all
));
1247 ActionManager::register_action (popup_act_grp
, X_("deactivate_all"), _("Deactivate all"), sigc::ptr_fun (RedirectBox::rb_deactivate_all
));
1250 act
= ActionManager::register_action (popup_act_grp
, X_("edit"), _("Edit"), sigc::ptr_fun (RedirectBox::rb_edit
));
1251 ActionManager::plugin_selection_sensitive_actions
.push_back(act
);
1253 ActionManager::add_action_group (popup_act_grp
);
1259 RedirectBox::rb_choose_plugin ()
1261 if (_current_redirect_box
== 0) {
1264 _current_redirect_box
->choose_plugin ();
1268 RedirectBox::rb_choose_insert ()
1270 if (_current_redirect_box
== 0) {
1273 _current_redirect_box
->choose_insert ();
1277 RedirectBox::rb_choose_send ()
1279 if (_current_redirect_box
== 0) {
1282 _current_redirect_box
->choose_send ();
1286 RedirectBox::rb_clear ()
1288 if (_current_redirect_box
== 0) {
1292 _current_redirect_box
->clear_redirects ();
1296 RedirectBox::rb_cut ()
1298 if (_current_redirect_box
== 0) {
1302 _current_redirect_box
->cut_redirects ();
1306 RedirectBox::rb_delete ()
1308 if (_current_redirect_box
== 0) {
1312 _current_redirect_box
->delete_redirects ();
1316 RedirectBox::rb_copy ()
1318 if (_current_redirect_box
== 0) {
1321 _current_redirect_box
->copy_redirects ();
1325 RedirectBox::rb_paste ()
1327 if (_current_redirect_box
== 0) {
1331 _current_redirect_box
->paste_redirects ();
1335 RedirectBox::rb_rename ()
1337 if (_current_redirect_box
== 0) {
1340 _current_redirect_box
->rename_redirects ();
1344 RedirectBox::rb_select_all ()
1346 if (_current_redirect_box
== 0) {
1350 _current_redirect_box
->select_all_redirects ();
1354 RedirectBox::rb_deselect_all ()
1356 if (_current_redirect_box
== 0) {
1360 _current_redirect_box
->deselect_all_redirects ();
1364 RedirectBox::rb_activate ()
1366 if (_current_redirect_box
== 0) {
1370 _current_redirect_box
->for_selected_redirects (&RedirectBox::activate_redirect
);
1374 RedirectBox::rb_deactivate ()
1376 if (_current_redirect_box
== 0) {
1379 _current_redirect_box
->for_selected_redirects (&RedirectBox::deactivate_redirect
);
1383 RedirectBox::rb_activate_all ()
1385 if (_current_redirect_box
== 0) {
1389 _current_redirect_box
->all_redirects_active (true);
1393 RedirectBox::rb_deactivate_all ()
1395 if (_current_redirect_box
== 0) {
1398 _current_redirect_box
->all_redirects_active (false);
1402 RedirectBox::rb_edit ()
1404 if (_current_redirect_box
== 0) {
1408 _current_redirect_box
->for_selected_redirects (&RedirectBox::edit_redirect
);
1412 RedirectBox::route_name_changed (void* src
)
1414 boost::shared_ptr
<Redirect
> redirect
;
1415 boost::shared_ptr
<Insert
> insert
;
1416 Gtk::TreeModel::Children children
= model
->children();
1418 for (Gtk::TreeModel::Children::iterator iter
= children
.begin(); iter
!= children
.end(); ++iter
) {
1419 Gtk::TreeModel::Row row
= *iter
;
1421 redirect
= row
[columns
.redirect
];
1423 void* gui
= redirect
->get_gui();
1429 /* rename editor windows for sends and plugins */
1431 WindowTitle
title (Glib::get_application_name());
1433 if ((insert
= boost::dynamic_pointer_cast
<Insert
> (redirect
)) == 0) {
1434 boost::shared_ptr
<Send
> send
= boost::dynamic_pointer_cast
<Send
> (redirect
);
1435 title
+= send
->name();
1436 static_cast<Window
*>(gui
)->set_title (title
.get_string());
1438 boost::shared_ptr
<PluginInsert
> plugin_insert
;
1440 if ((plugin_insert
= boost::dynamic_pointer_cast
<PluginInsert
> (insert
)) != 0) {
1441 title
+= generate_redirect_title (plugin_insert
);
1443 static_cast<Window
*>(gui
)->set_title (title
.get_string());
1449 RedirectBox::generate_redirect_title (boost::shared_ptr
<PluginInsert
> pi
)
1451 string maker
= pi
->plugin()->maker() ? pi
->plugin()->maker() : "";
1452 string::size_type email_pos
;
1454 if ((email_pos
= maker
.find_first_of ('<')) != string::npos
) {
1455 maker
= maker
.substr (0, email_pos
- 1);
1458 if (maker
.length() > 32) {
1459 maker
= maker
.substr (0, 32);
1463 return string_compose(_("%1: %2 (by %3)"), _route
->name(), pi
->name(), maker
);