2 Copyright (C) 2000-2009 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.
27 #include "pbd/unknown_type.h"
28 #include "pbd/unwind.h"
30 #include "ardour/debug.h"
31 #include "ardour/route.h"
32 #include "ardour/midi_track.h"
33 #include "ardour/session.h"
35 #include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
36 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
37 #include "gtkmm2ext/treeutils.h"
41 #include "ardour_ui.h"
42 #include "audio_time_axis.h"
43 #include "midi_time_axis.h"
44 #include "mixer_strip.h"
45 #include "gui_thread.h"
48 #include "route_sorter.h"
49 #include "editor_group_tabs.h"
50 #include "editor_routes.h"
55 using namespace ARDOUR;
56 using namespace ARDOUR_UI_UTILS;
59 using namespace Gtkmm2ext;
61 using Gtkmm2ext::Keyboard;
69 EditorRoutes::EditorRoutes (Editor* e)
71 , _ignore_reorder (false)
72 , _no_redisplay (false)
73 , _adding_routes (false)
74 , _route_deletion_in_progress (false)
77 , selection_countdown (0)
80 static const int column_width = 22;
82 _scroller.add (_display);
83 _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
85 _model = ListStore::create (_columns);
86 _display.set_model (_model);
88 // Record enable toggle
89 CellRendererPixbufMulti* rec_col_renderer = manage (new CellRendererPixbufMulti());
91 rec_col_renderer->set_pixbuf (0, ::get_icon("record-normal-disabled"));
92 rec_col_renderer->set_pixbuf (1, ::get_icon("record-normal-in-progress"));
93 rec_col_renderer->set_pixbuf (2, ::get_icon("record-normal-enabled"));
94 rec_col_renderer->set_pixbuf (3, ::get_icon("record-step"));
95 rec_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_rec_enable_changed));
97 TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer));
99 rec_state_column->add_attribute(rec_col_renderer->property_state(), _columns.rec_state);
100 rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
102 rec_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
103 rec_state_column->set_alignment(ALIGN_CENTER);
104 rec_state_column->set_expand(false);
105 rec_state_column->set_fixed_width(column_width);
109 CellRendererPixbufMulti* input_active_col_renderer = manage (new CellRendererPixbufMulti());
110 input_active_col_renderer->set_pixbuf (0, ::get_icon("midi-input-inactive"));
111 input_active_col_renderer->set_pixbuf (1, ::get_icon("midi-input-active"));
112 input_active_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_input_active_changed));
114 TreeViewColumn* input_active_column = manage (new TreeViewColumn ("I", *input_active_col_renderer));
116 input_active_column->add_attribute(input_active_col_renderer->property_state(), _columns.is_input_active);
117 input_active_column->add_attribute (input_active_col_renderer->property_visible(), _columns.is_midi);
119 input_active_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
120 input_active_column->set_alignment(ALIGN_CENTER);
121 input_active_column->set_expand(false);
122 input_active_column->set_fixed_width(column_width);
124 // Mute enable toggle
125 CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
127 mute_col_renderer->set_pixbuf (Gtkmm2ext::Off, ::get_icon("mute-disabled"));
128 mute_col_renderer->set_pixbuf (Gtkmm2ext::ImplicitActive, ::get_icon("muted-by-others"));
129 mute_col_renderer->set_pixbuf (Gtkmm2ext::ExplicitActive, ::get_icon("mute-enabled"));
130 mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
132 TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
134 mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
135 mute_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
136 mute_state_column->set_alignment(ALIGN_CENTER);
137 mute_state_column->set_expand(false);
138 mute_state_column->set_fixed_width(15);
140 // Solo enable toggle
141 CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
143 solo_col_renderer->set_pixbuf (Gtkmm2ext::Off, ::get_icon("solo-disabled"));
144 solo_col_renderer->set_pixbuf (Gtkmm2ext::ExplicitActive, ::get_icon("solo-enabled"));
145 solo_col_renderer->set_pixbuf (Gtkmm2ext::ImplicitActive, ::get_icon("soloed-by-others"));
146 solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
148 TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
150 solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
151 solo_state_column->add_attribute(solo_col_renderer->property_visible(), _columns.solo_visible);
152 solo_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
153 solo_state_column->set_alignment(ALIGN_CENTER);
154 solo_state_column->set_expand(false);
155 solo_state_column->set_fixed_width(column_width);
157 // Solo isolate toggle
158 CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti());
160 solo_iso_renderer->set_pixbuf (0, ::get_icon("solo-isolate-disabled"));
161 solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolate-enabled"));
162 solo_iso_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled));
164 TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("SI", *solo_iso_renderer));
166 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state);
167 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_visible(), _columns.solo_visible);
168 solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
169 solo_isolate_state_column->set_alignment(ALIGN_CENTER);
170 solo_isolate_state_column->set_expand(false);
171 solo_isolate_state_column->set_fixed_width(column_width);
174 CellRendererPixbufMulti* solo_safe_renderer = manage (new CellRendererPixbufMulti ());
176 solo_safe_renderer->set_pixbuf (0, ::get_icon("solo-safe-disabled"));
177 solo_safe_renderer->set_pixbuf (1, ::get_icon("solo-safe-enabled"));
178 solo_safe_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_safe_toggled));
180 TreeViewColumn* solo_safe_state_column = manage (new TreeViewColumn(_("SS"), *solo_safe_renderer));
181 solo_safe_state_column->add_attribute(solo_safe_renderer->property_state(), _columns.solo_safe_state);
182 solo_safe_state_column->add_attribute(solo_safe_renderer->property_visible(), _columns.solo_visible);
183 solo_safe_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
184 solo_safe_state_column->set_alignment(ALIGN_CENTER);
185 solo_safe_state_column->set_expand(false);
186 solo_safe_state_column->set_fixed_width(column_width);
188 _name_column = _display.append_column ("", _columns.text) - 1;
189 _visible_column = _display.append_column ("", _columns.visible) - 1;
190 _active_column = _display.append_column ("", _columns.active) - 1;
192 _display.append_column (*input_active_column);
193 _display.append_column (*rec_state_column);
194 _display.append_column (*mute_state_column);
195 _display.append_column (*solo_state_column);
196 _display.append_column (*solo_isolate_state_column);
197 _display.append_column (*solo_safe_state_column);
204 { 0, _("Name"), _("Track/Bus Name") },
205 { 1, _("V"), _("Track/Bus visible ?") },
206 { 2, _("A"), _("Track/Bus active ?") },
207 { 3, _("I"), _("MIDI input enabled") },
208 { 4, _("R"), _("Record enabled") },
209 { 5, _("M"), _("Muted") },
210 { 6, _("S"), _("Soloed") },
211 { 7, _("SI"), _("Solo Isolated") },
212 { 8, _("SS"), _("Solo Safe (Locked)") },
216 for (int i = 0; ci[i].index >= 0; ++i) {
217 col = _display.get_column (ci[i].index);
218 l = manage (new Label (ci[i].label));
219 ARDOUR_UI::instance()->set_tip (*l, ci[i].tooltip);
220 col->set_widget (*l);
224 _display.set_headers_visible (true);
225 _display.get_selection()->set_mode (SELECTION_SINGLE);
226 _display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
227 _display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::selection_changed));
228 _display.set_reorderable (true);
229 _display.set_name (X_("EditGroupList"));
230 _display.set_rules_hint (true);
231 _display.set_size_request (100, -1);
232 _display.add_object_drag (_columns.route.index(), "routes");
234 CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (_name_column));
237 name_cell->signal_editing_started().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit_started));
239 TreeViewColumn* name_column = _display.get_column (_name_column);
241 assert (name_column);
243 name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
244 name_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
245 name_column->set_expand(true);
246 name_column->set_min_width(50);
248 name_cell->property_editable() = true;
249 name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit));
251 // Set the visible column cell renderer to radio toggle
252 CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (_visible_column));
254 visible_cell->property_activatable() = true;
255 visible_cell->property_radio() = false;
256 visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::visible_changed));
258 TreeViewColumn* visible_col = dynamic_cast<TreeViewColumn*> (_display.get_column (_visible_column));
259 visible_col->set_expand(false);
260 visible_col->set_sizing(TREE_VIEW_COLUMN_FIXED);
261 visible_col->set_fixed_width(30);
262 visible_col->set_alignment(ALIGN_CENTER);
264 CellRendererToggle* active_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (_active_column));
266 active_cell->property_activatable() = true;
267 active_cell->property_radio() = false;
268 active_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::active_changed));
270 TreeViewColumn* active_col = dynamic_cast<TreeViewColumn*> (_display.get_column (_active_column));
271 active_col->set_expand (false);
272 active_col->set_sizing (TREE_VIEW_COLUMN_FIXED);
273 active_col->set_fixed_width (30);
274 active_col->set_alignment (ALIGN_CENTER);
276 _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::row_deleted));
277 _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered));
279 _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false);
280 _scroller.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorRoutes::key_press), false);
282 _scroller.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditorRoutes::focus_in), false);
283 _scroller.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditorRoutes::focus_out));
285 _display.signal_enter_notify_event().connect (sigc::mem_fun (*this, &EditorRoutes::enter_notify), false);
286 _display.signal_leave_notify_event().connect (sigc::mem_fun (*this, &EditorRoutes::leave_notify), false);
288 _display.set_enable_search (false);
290 Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this), gui_context());
294 EditorRoutes::focus_in (GdkEventFocus*)
296 Window* win = dynamic_cast<Window*> (_scroller.get_toplevel ());
299 old_focus = win->get_focus ();
306 /* try to do nothing on focus in (doesn't work, hence selection_count nonsense) */
311 EditorRoutes::focus_out (GdkEventFocus*)
314 old_focus->grab_focus ();
322 EditorRoutes::enter_notify (GdkEventCrossing*)
328 /* arm counter so that ::selection_filter() will deny selecting anything for the
329 next two attempts to change selection status.
331 selection_countdown = 2;
332 _scroller.grab_focus ();
333 Keyboard::magic_widget_grab_focus ();
338 EditorRoutes::leave_notify (GdkEventCrossing*)
340 selection_countdown = 0;
343 old_focus->grab_focus ();
347 Keyboard::magic_widget_drop_focus ();
352 EditorRoutes::set_session (Session* s)
354 SessionHandlePtr::set_session (s);
359 _session->SoloChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::solo_changed_so_update_mute, this), gui_context());
360 _session->RecordStateChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
365 EditorRoutes::on_input_active_changed (std::string const & path_string)
367 // Get the model row that has been toggled.
368 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
370 TimeAxisView* tv = row[_columns.tv];
371 RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
374 boost::shared_ptr<MidiTrack> mt;
375 mt = rtv->midi_track();
377 mt->set_input_active (!mt->input_active());
383 EditorRoutes::on_tv_rec_enable_changed (std::string const & path_string)
386 // Get the model row that has been toggled.
387 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
389 TimeAxisView* tv = row[_columns.tv];
390 RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
392 if (rtv && rtv->track()) {
393 boost::shared_ptr<RouteList> rl (new RouteList);
394 rl->push_back (rtv->route());
395 _session->set_record_enabled (rl, !rtv->track()->record_enabled(), Session::rt_cleanup);
400 EditorRoutes::on_tv_mute_enable_toggled (std::string const & path_string)
402 // Get the model row that has been toggled.
403 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
405 TimeAxisView *tv = row[_columns.tv];
406 RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
409 boost::shared_ptr<RouteList> rl (new RouteList);
410 rl->push_back (rtv->route());
411 _session->set_mute (rl, !rtv->route()->muted(), Session::rt_cleanup);
416 EditorRoutes::on_tv_solo_enable_toggled (std::string const & path_string)
418 // Get the model row that has been toggled.
419 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
421 TimeAxisView *tv = row[_columns.tv];
422 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
425 boost::shared_ptr<RouteList> rl (new RouteList);
426 rl->push_back (rtv->route());
427 if (Config->get_solo_control_is_listen_control()) {
428 _session->set_listen (rl, !rtv->route()->listening_via_monitor(), Session::rt_cleanup);
430 _session->set_solo (rl, !rtv->route()->self_soloed(), Session::rt_cleanup);
436 EditorRoutes::on_tv_solo_isolate_toggled (std::string const & path_string)
438 // Get the model row that has been toggled.
439 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
441 TimeAxisView *tv = row[_columns.tv];
442 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
445 rtv->route()->set_solo_isolated (!rtv->route()->solo_isolated(), this);
450 EditorRoutes::on_tv_solo_safe_toggled (std::string const & path_string)
452 // Get the model row that has been toggled.
453 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
455 TimeAxisView *tv = row[_columns.tv];
456 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
459 rtv->route()->set_solo_safe (!rtv->route()->solo_safe(), this);
464 EditorRoutes::build_menu ()
466 using namespace Menu_Helpers;
471 MenuList& items = _menu->items();
472 _menu->set_name ("ArdourContextMenu");
474 items.push_back (MenuElem (_("Show All"), sigc::mem_fun (*this, &EditorRoutes::show_all_routes)));
475 items.push_back (MenuElem (_("Hide All"), sigc::mem_fun (*this, &EditorRoutes::hide_all_routes)));
476 items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
477 items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
478 items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus)));
479 items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
480 items.push_back (MenuElem (_("Show All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_miditracks)));
481 items.push_back (MenuElem (_("Hide All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_miditracks)));
482 items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
486 EditorRoutes::show_menu ()
492 _menu->popup (1, gtk_get_current_event_time());
496 EditorRoutes::redisplay ()
498 if (_no_redisplay || !_session || _session->deletion_in_progress() || _redisplaying) {
501 _redisplaying = true; // tv->show_at() below causes recursive redisplay via handle_gui_changes()
503 TreeModel::Children rows = _model->children();
504 TreeModel::Children::iterator i;
507 /* n will be the count of tracks plus children (updated by TimeAxisView::show_at),
508 so we will use that to know where to put things.
512 for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
513 TimeAxisView *tv = (*i)[_columns.tv];
514 boost::shared_ptr<Route> route = (*i)[_columns.route];
517 // just a "title" row
521 bool visible = tv->marked_for_display ();
523 /* show or hide the TimeAxisView */
525 position += tv->show_at (position, n, &_editor->edit_controls_vbox);
533 /* whenever we go idle, update the track view list to reflect the new order.
534 we can't do this here, because we could mess up something that is traversing
535 the track order and has caused a redisplay of the list.
537 Glib::signal_idle().connect (sigc::mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
539 _editor->reset_controls_layout_height (position);
540 _editor->reset_controls_layout_width ();
541 _editor->_full_canvas_height = position;
543 if ((_editor->vertical_adjustment.get_value() + _editor->_visible_canvas_height) > _editor->vertical_adjustment.get_upper()) {
545 We're increasing the size of the canvas while the bottom is visible.
546 We scroll down to keep in step with the controls layout.
548 _editor->vertical_adjustment.set_value (_editor->_full_canvas_height - _editor->_visible_canvas_height);
550 _redisplaying = false;
554 EditorRoutes::row_deleted (Gtk::TreeModel::Path const &)
556 /* this happens as the second step of a DnD within the treeview, and
557 when a route is actually removed. we don't differentiate between
560 note that the sync_orders_keys() step may not actually change any
561 RID's (e.g. the last track may be removed, so all other tracks keep
562 the same RID), which means that no redisplay would happen. so we
563 have to force a redisplay.
566 DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
569 sync_order_keys_from_treeview ();
573 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
575 /* reordering implies that RID's will change, so sync_order_keys() will
579 DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
580 sync_order_keys_from_treeview ();
584 EditorRoutes::visible_changed (std::string const & path)
586 if (_session && _session->deletion_in_progress()) {
593 if ((iter = _model->get_iter (path))) {
594 TimeAxisView* tv = (*iter)[_columns.tv];
596 bool visible = (*iter)[_columns.visible];
598 if (tv->set_marked_for_display (!visible)) {
599 update_visibility ();
606 EditorRoutes::active_changed (std::string const & path)
608 if (_session && _session->deletion_in_progress ()) {
612 Gtk::TreeModel::Row row = *_model->get_iter (path);
613 boost::shared_ptr<Route> route = row[_columns.route];
614 bool const active = row[_columns.active];
615 route->set_active (!active, this);
619 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
621 PBD::Unwinder<bool> at (_adding_routes, true);
623 bool from_scratch = (_model->children().size() == 0);
624 Gtk::TreeModel::Children::iterator insert_iter = _model->children().end();
626 for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) {
627 boost::shared_ptr<Route> r = (*it)[_columns.route];
629 if (r->order_key() == (routes.front()->route()->order_key() + routes.size())) {
636 _editor->selection->tracks.clear();
641 _display.set_model (Glib::RefPtr<ListStore>());
643 for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
645 boost::shared_ptr<MidiTrack> midi_trk = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
647 TreeModel::Row row = *(_model->insert (insert_iter));
649 row[_columns.text] = (*x)->route()->name();
650 row[_columns.visible] = (*x)->marked_for_display();
651 row[_columns.active] = (*x)->route()->active ();
652 row[_columns.tv] = *x;
653 row[_columns.route] = (*x)->route ();
654 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
657 row[_columns.is_input_active] = midi_trk->input_active ();
658 row[_columns.is_midi] = true;
660 row[_columns.is_input_active] = false;
661 row[_columns.is_midi] = false;
664 row[_columns.mute_state] = (*x)->route()->muted() ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off;
665 row[_columns.solo_state] = RouteUI::solo_active_state ((*x)->route());
666 row[_columns.solo_visible] = !(*x)->route()->is_master ();
667 row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated();
668 row[_columns.solo_safe_state] = (*x)->route()->solo_safe();
669 row[_columns.name_editable] = true;
672 _editor->selection->add(*x);
675 boost::weak_ptr<Route> wr ((*x)->route());
677 (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
678 (*x)->route()->PropertyChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::route_property_changed, this, _1, wr), gui_context());
680 if ((*x)->is_track()) {
681 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
682 t->RecordEnableChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
685 if ((*x)->is_midi_track()) {
686 boost::shared_ptr<MidiTrack> t = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
687 t->StepEditStatusChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
688 t->InputActiveChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_input_active_display, this), gui_context());
691 (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
692 (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
693 (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
694 (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
695 (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context());
696 (*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ());
700 update_rec_display ();
701 update_mute_display ();
702 update_solo_display (true);
703 update_solo_isolate_display ();
704 update_solo_safe_display ();
705 update_input_active_display ();
706 update_active_display ();
708 _display.set_model (_model);
710 /* now update route order keys from the treeview/track display order */
712 sync_order_keys_from_treeview ();
716 EditorRoutes::handle_gui_changes (string const & what, void*)
718 if (_adding_routes) {
722 if (what == "track_height") {
723 /* Optional :make tracks change height while it happens, instead
729 if (what == "visible_tracks") {
735 EditorRoutes::route_removed (TimeAxisView *tv)
737 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
739 TreeModel::Children rows = _model->children();
740 TreeModel::Children::iterator ri;
742 for (ri = rows.begin(); ri != rows.end(); ++ri) {
743 if ((*ri)[_columns.tv] == tv) {
744 PBD::Unwinder<bool> uw (_route_deletion_in_progress, true);
750 /* the deleted signal for the treeview/model will take
756 EditorRoutes::route_property_changed (const PropertyChange& what_changed, boost::weak_ptr<Route> r)
758 if (!what_changed.contains (ARDOUR::Properties::name)) {
762 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
764 boost::shared_ptr<Route> route = r.lock ();
770 TreeModel::Children rows = _model->children();
771 TreeModel::Children::iterator i;
773 for (i = rows.begin(); i != rows.end(); ++i) {
774 boost::shared_ptr<Route> t = (*i)[_columns.route];
776 (*i)[_columns.text] = route->name();
783 EditorRoutes::update_active_display ()
785 if (_queue_mute_rec_solo_etc == 0) {
786 Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
788 _queue_mute_rec_solo_etc |= 16;
792 EditorRoutes::update_visibility ()
794 TreeModel::Children rows = _model->children();
795 TreeModel::Children::iterator i;
797 DisplaySuspender ds ();
799 for (i = rows.begin(); i != rows.end(); ++i) {
800 TimeAxisView *tv = (*i)[_columns.tv];
801 (*i)[_columns.visible] = tv->marked_for_display ();
804 /* force route order keys catch up with visibility changes
807 sync_order_keys_from_treeview ();
811 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
813 TreeModel::Children rows = _model->children();
814 TreeModel::Children::iterator i;
816 for (i = rows.begin(); i != rows.end(); ++i) {
817 if ((*i)[_columns.tv] == &tv) {
818 tv.set_marked_for_display (false);
819 (*i)[_columns.visible] = false;
827 EditorRoutes::show_track_in_display (TimeAxisView& tv)
829 TreeModel::Children rows = _model->children();
830 TreeModel::Children::iterator i;
833 for (i = rows.begin(); i != rows.end(); ++i) {
834 if ((*i)[_columns.tv] == &tv) {
835 tv.set_marked_for_display (true);
836 (*i)[_columns.visible] = true;
844 EditorRoutes::reset_remote_control_ids ()
846 if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) {
850 TreeModel::Children rows = _model->children();
857 DEBUG_TRACE (DEBUG::OrderKeys, "editor reset remote control ids\n");
859 TreeModel::Children::iterator ri;
860 bool rid_change = false;
862 uint32_t invisible_key = UINT32_MAX;
864 for (ri = rows.begin(); ri != rows.end(); ++ri) {
866 boost::shared_ptr<Route> route = (*ri)[_columns.route];
867 bool visible = (*ri)[_columns.visible];
870 if (!route->is_master() && !route->is_monitor()) {
872 uint32_t new_rid = (visible ? rid : invisible_key--);
874 if (new_rid != route->remote_control_id()) {
875 route->set_remote_control_id_explicit (new_rid);
887 /* tell the world that we changed the remote control IDs */
888 _session->notify_remote_id_change ();
894 EditorRoutes::sync_order_keys_from_treeview ()
896 if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
900 TreeModel::Children rows = _model->children();
907 DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from treeview\n");
909 TreeModel::Children::iterator ri;
910 bool changed = false;
911 bool rid_change = false;
914 uint32_t invisible_key = UINT32_MAX;
916 for (ri = rows.begin(); ri != rows.end(); ++ri) {
918 boost::shared_ptr<Route> route = (*ri)[_columns.route];
919 bool visible = (*ri)[_columns.visible];
921 uint32_t old_key = route->order_key ();
923 if (order != old_key) {
924 route->set_order_key (order);
929 if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) {
931 uint32_t new_rid = (visible ? rid : invisible_key--);
933 if (new_rid != route->remote_control_id()) {
934 route->set_remote_control_id_explicit (new_rid);
948 /* tell the world that we changed the editor sort keys */
949 _session->sync_order_keys ();
953 /* tell the world that we changed the remote control IDs */
954 _session->notify_remote_id_change ();
959 EditorRoutes::sync_treeview_from_order_keys ()
961 /* Some route order key(s) have been changed, make sure that
962 we update out tree/list model and GUI to reflect the change.
965 if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
969 DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from order keys.\n");
971 /* we could get here after either a change in the Mixer or Editor sort
972 * order, but either way, the mixer order keys reflect the intended
973 * order for the GUI, so reorder the treeview model to match it.
976 vector<int> neworder;
977 TreeModel::Children rows = _model->children();
978 uint32_t old_order = 0;
979 bool changed = false;
985 OrderKeySortedRoutes sorted_routes;
987 for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
988 boost::shared_ptr<Route> route = (*ri)[_columns.route];
989 sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key ()));
992 SortByNewDisplayOrder cmp;
994 sort (sorted_routes.begin(), sorted_routes.end(), cmp);
995 neworder.assign (sorted_routes.size(), 0);
999 for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) {
1001 neworder[n] = sr->old_display_order;
1003 if (sr->old_display_order != n) {
1007 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("EDITOR change order for %1 from %2 to %3\n",
1008 sr->route->name(), sr->old_display_order, n));
1012 Unwinder<bool> uw (_ignore_reorder, true);
1013 _model->reorder (neworder);
1020 EditorRoutes::hide_all_tracks (bool /*with_select*/)
1022 TreeModel::Children rows = _model->children();
1023 TreeModel::Children::iterator i;
1025 DisplaySuspender ds;
1027 for (i = rows.begin(); i != rows.end(); ++i) {
1029 TreeModel::Row row = (*i);
1030 TimeAxisView *tv = row[_columns.tv];
1036 row[_columns.visible] = false;
1041 EditorRoutes::set_all_tracks_visibility (bool yn)
1043 TreeModel::Children rows = _model->children();
1044 TreeModel::Children::iterator i;
1046 DisplaySuspender ds;
1048 for (i = rows.begin(); i != rows.end(); ++i) {
1050 TreeModel::Row row = (*i);
1051 TimeAxisView* tv = row[_columns.tv];
1057 tv->set_marked_for_display (yn);
1058 (*i)[_columns.visible] = yn;
1061 /* force route order keys catch up with visibility changes
1064 sync_order_keys_from_treeview ();
1068 EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
1070 TreeModel::Children rows = _model->children();
1071 TreeModel::Children::iterator i;
1073 DisplaySuspender ds;
1075 for (i = rows.begin(); i != rows.end(); ++i) {
1077 TreeModel::Row row = (*i);
1078 TimeAxisView* tv = row[_columns.tv];
1080 AudioTimeAxisView* atv;
1081 MidiTimeAxisView* mtv;
1087 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1090 (*i)[_columns.visible] = yn;
1094 if (atv->is_audio_track()) {
1095 (*i)[_columns.visible] = yn;
1100 if (!atv->is_audio_track()) {
1101 (*i)[_columns.visible] = yn;
1106 else if ((mtv = dynamic_cast<MidiTimeAxisView*>(tv)) != 0) {
1109 (*i)[_columns.visible] = yn;
1113 if (mtv->is_midi_track()) {
1114 (*i)[_columns.visible] = yn;
1121 /* force route order keys catch up with visibility changes
1124 sync_order_keys_from_treeview ();
1128 EditorRoutes::hide_all_routes ()
1130 set_all_tracks_visibility (false);
1134 EditorRoutes::show_all_routes ()
1136 set_all_tracks_visibility (true);
1140 EditorRoutes::show_all_audiotracks()
1142 set_all_audio_midi_visibility (1, true);
1145 EditorRoutes::hide_all_audiotracks ()
1147 set_all_audio_midi_visibility (1, false);
1151 EditorRoutes::show_all_audiobus ()
1153 set_all_audio_midi_visibility (2, true);
1156 EditorRoutes::hide_all_audiobus ()
1158 set_all_audio_midi_visibility (2, false);
1162 EditorRoutes::show_all_miditracks()
1164 set_all_audio_midi_visibility (3, true);
1167 EditorRoutes::hide_all_miditracks ()
1169 set_all_audio_midi_visibility (3, false);
1173 EditorRoutes::key_press (GdkEventKey* ev)
1175 TreeViewColumn *col;
1176 boost::shared_ptr<RouteList> rl (new RouteList);
1179 switch (ev->keyval) {
1181 case GDK_ISO_Left_Tab:
1183 /* If we appear to be editing something, leave that cleanly and appropriately.
1185 if (name_editable) {
1186 name_editable->editing_done ();
1190 col = _display.get_column (_name_column); // select&focus on name column
1192 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1193 treeview_select_previous (_display, _model, col);
1195 treeview_select_next (_display, _model, col);
1202 if (get_relevant_routes (rl)) {
1203 _session->set_mute (rl, !rl->front()->muted(), Session::rt_cleanup);
1209 if (get_relevant_routes (rl)) {
1210 if (Config->get_solo_control_is_listen_control()) {
1211 _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
1213 _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
1220 if (get_relevant_routes (rl)) {
1221 _session->set_record_enabled (rl, !rl->front()->record_enabled(), Session::rt_cleanup);
1233 EditorRoutes::get_relevant_routes (boost::shared_ptr<RouteList> rl)
1236 RouteTimeAxisView* rtv;
1237 RefPtr<TreeSelection> selection = _display.get_selection();
1241 if (selection->count_selected_rows() != 0) {
1245 RefPtr<TreeModel> tm = RefPtr<TreeModel>::cast_dynamic (_model);
1246 iter = selection->get_selected (tm);
1249 /* use mouse pointer */
1254 _display.get_pointer (x, y);
1255 _display.convert_widget_to_bin_window_coords (x, y, bx, by);
1257 if (_display.get_path_at_pos (bx, by, path)) {
1258 iter = _model->get_iter (path);
1263 tv = (*iter)[_columns.tv];
1265 rtv = dynamic_cast<RouteTimeAxisView*>(tv);
1267 rl->push_back (rtv->route());
1272 return !rl->empty();
1276 EditorRoutes::button_press (GdkEventButton* ev)
1278 if (Keyboard::is_context_menu_event (ev)) {
1283 TreeModel::Path path;
1284 TreeViewColumn *tvc;
1288 if (!_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y)) {
1289 /* cancel selection */
1290 _display.get_selection()->unselect_all ();
1291 /* end any editing by grabbing focus */
1292 _display.grab_focus ();
1296 //Scroll editor canvas to selected track
1297 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1299 Gtk::TreeModel::Row row = *_model->get_iter (path);
1300 TimeAxisView *tv = row[_columns.tv];
1303 _editor->ensure_time_axis_view_is_visible (*tv, true);
1311 EditorRoutes::selection_changed ()
1313 if (_display.get_selection()->count_selected_rows() > 0) {
1316 TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
1317 TrackViewList selected;
1319 _editor->get_selection().clear_regions ();
1321 for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
1323 if ((iter = _model->get_iter (*i))) {
1325 TimeAxisView* tv = (*iter)[_columns.tv];
1326 selected.push_back (tv);
1331 _editor->get_selection().set (selected);
1332 _editor->ensure_time_axis_view_is_visible (*(selected.front()), true);
1335 _editor->get_selection().clear_tracks ();
1340 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
1342 if (selection_countdown) {
1343 if (--selection_countdown == 0) {
1346 /* no selection yet ... */
1353 struct EditorOrderRouteSorter {
1354 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
1355 if (a->is_master()) {
1356 /* master before everything else */
1358 } else if (b->is_master()) {
1359 /* everything else before master */
1362 return a->order_key () < b->order_key ();
1367 EditorRoutes::initial_display ()
1369 DisplaySuspender ds;
1376 boost::shared_ptr<RouteList> routes = _session->get_routes();
1378 if (ARDOUR_UI::instance()->session_is_new ()) {
1380 /* new session: stamp all routes with the right editor order
1384 _editor->add_routes (*(routes.get()));
1388 /* existing session: sort a copy of the route list by
1389 * editor-order and add its contents to the display.
1392 RouteList r (*routes);
1393 EditorOrderRouteSorter sorter;
1396 _editor->add_routes (r);
1402 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
1404 const SelectionData& data,
1405 guint info, guint time)
1407 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
1408 _display.on_drag_data_received (context, x, y, data, info, time);
1412 context->drag_finish (true, false, time);
1416 EditorRoutes::move_selected_tracks (bool up)
1418 if (_editor->selection->tracks.empty()) {
1422 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
1423 std::list<ViewRoute> view_routes;
1424 std::vector<int> neworder;
1425 TreeModel::Children rows = _model->children();
1426 TreeModel::Children::iterator ri;
1428 for (ri = rows.begin(); ri != rows.end(); ++ri) {
1429 TimeAxisView* tv = (*ri)[_columns.tv];
1430 boost::shared_ptr<Route> route = (*ri)[_columns.route];
1432 view_routes.push_back (ViewRoute (tv, route));
1435 list<ViewRoute>::iterator trailing;
1436 list<ViewRoute>::iterator leading;
1440 trailing = view_routes.begin();
1441 leading = view_routes.begin();
1445 while (leading != view_routes.end()) {
1446 if (_editor->selection->selected (leading->first)) {
1447 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
1448 leading = view_routes.erase (leading);
1457 /* if we could use reverse_iterator in list::insert, this code
1458 would be a beautiful reflection of the code above. but we can't
1459 and so it looks like a bit of a mess.
1462 trailing = view_routes.end();
1463 leading = view_routes.end();
1465 --leading; if (leading == view_routes.begin()) { return; }
1471 if (_editor->selection->selected (leading->first)) {
1472 list<ViewRoute>::iterator tmp;
1474 /* need to insert *after* trailing, not *before* it,
1475 which is what insert (iter, val) normally does.
1481 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
1483 /* can't use iter = cont.erase (iter); form here, because
1484 we need iter to move backwards.
1492 if (leading == view_routes.begin()) {
1493 /* the one we've just inserted somewhere else
1494 was the first in the list. erase this copy,
1495 and then break, because we're done.
1500 view_routes.erase (leading);
1509 if (leading == view_routes.begin()) {
1518 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
1519 uint32_t order = leading->second->order_key ();
1520 neworder.push_back (order);
1524 DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n");
1525 for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1526 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("\t%1\n", *i));
1528 DEBUG_TRACE (DEBUG::OrderKeys, "-------\n");
1530 for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1531 if (*i >= (int) neworder.size()) {
1532 cerr << "Trying to move something to " << *i << " of " << neworder.size() << endl;
1534 assert (*i < (int) neworder.size ());
1538 _model->reorder (neworder);
1542 EditorRoutes::update_input_active_display ()
1544 TreeModel::Children rows = _model->children();
1545 TreeModel::Children::iterator i;
1547 for (i = rows.begin(); i != rows.end(); ++i) {
1548 boost::shared_ptr<Route> route = (*i)[_columns.route];
1550 if (boost::dynamic_pointer_cast<Track> (route)) {
1551 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1554 (*i)[_columns.is_input_active] = mt->input_active();
1561 EditorRoutes::update_rec_display ()
1563 if (_queue_mute_rec_solo_etc == 0) {
1564 Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
1566 _queue_mute_rec_solo_etc |= 32;
1570 EditorRoutes::idle_update_mute_rec_solo_etc()
1572 const int what = _queue_mute_rec_solo_etc;
1573 _queue_mute_rec_solo_etc = 0;
1574 TreeModel::Children rows = _model->children();
1575 TreeModel::Children::iterator i;
1577 for (i = rows.begin(); i != rows.end(); ++i) {
1578 boost::shared_ptr<Route> route = (*i)[_columns.route];
1580 (*i)[_columns.mute_state] = RouteUI::mute_active_state (_session, route);
1583 (*i)[_columns.solo_state] = RouteUI::solo_active_state (route);
1586 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_active_state (route) ? 1 : 0;
1589 (*i)[_columns.solo_safe_state] = RouteUI::solo_safe_active_state (route) ? 1 : 0;
1592 (*i)[_columns.active] = route->active ();
1594 if (what & 32) { // rec
1596 if (boost::dynamic_pointer_cast<Track> (route)) {
1597 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1599 if (route->record_enabled()) {
1600 if (_session->record_status() == Session::Recording) {
1601 (*i)[_columns.rec_state] = 1;
1603 (*i)[_columns.rec_state] = 2;
1605 } else if (mt && mt->step_editing()) {
1606 (*i)[_columns.rec_state] = 3;
1608 (*i)[_columns.rec_state] = 0;
1611 (*i)[_columns.name_editable] = !route->record_enabled ();
1615 return false; // do not call again (until needed)
1620 EditorRoutes::update_mute_display ()
1622 if (_queue_mute_rec_solo_etc == 0) {
1623 Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
1625 _queue_mute_rec_solo_etc |= 1;
1629 EditorRoutes::update_solo_display (bool /* selfsoloed */)
1631 if (_queue_mute_rec_solo_etc == 0) {
1632 Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
1634 _queue_mute_rec_solo_etc |= 2;
1638 EditorRoutes::update_solo_isolate_display ()
1640 if (_queue_mute_rec_solo_etc == 0) {
1641 Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
1643 _queue_mute_rec_solo_etc |= 4;
1647 EditorRoutes::update_solo_safe_display ()
1649 if (_queue_mute_rec_solo_etc == 0) {
1650 Glib::signal_idle().connect (sigc::mem_fun (*this, &EditorRoutes::idle_update_mute_rec_solo_etc));
1652 _queue_mute_rec_solo_etc |= 4;
1656 EditorRoutes::views () const
1658 list<TimeAxisView*> v;
1659 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1660 v.push_back ((*i)[_columns.tv]);
1667 EditorRoutes::clear ()
1669 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1671 _display.set_model (_model);
1675 EditorRoutes::name_edit_started (CellEditable* ce, const Glib::ustring&)
1679 /* give it a special name */
1681 Gtk::Entry *e = dynamic_cast<Gtk::Entry*> (ce);
1684 e->set_name (X_("RouteNameEditorEntry"));
1689 EditorRoutes::name_edit (std::string const & path, std::string const & new_text)
1693 TreeIter iter = _model->get_iter (path);
1699 boost::shared_ptr<Route> route = (*iter)[_columns.route];
1701 if (route && route->name() != new_text) {
1702 route->set_name (new_text);
1707 EditorRoutes::solo_changed_so_update_mute ()
1709 update_mute_display ();
1713 EditorRoutes::show_tracks_with_regions_at_playhead ()
1715 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1717 set<TimeAxisView*> show;
1718 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1719 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1725 DisplaySuspender ds;
1727 TreeModel::Children rows = _model->children ();
1728 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1729 TimeAxisView* tv = (*i)[_columns.tv];
1730 (*i)[_columns.visible] = (show.find (tv) != show.end());