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 "ardour/diskstream.h"
28 #include "ardour/session.h"
32 #include "ardour_ui.h"
33 #include "audio_time_axis.h"
34 #include "midi_time_axis.h"
35 #include "mixer_strip.h"
36 #include "gui_thread.h"
39 #include "editor_group_tabs.h"
40 #include "editor_routes.h"
42 #include "pbd/unknown_type.h"
44 #include "ardour/route.h"
46 #include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
47 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
52 using namespace ARDOUR;
55 using namespace Gtkmm2ext;
57 using Gtkmm2ext::Keyboard;
59 EditorRoutes::EditorRoutes (Editor* e)
60 : EditorComponent (e),
61 _ignore_reorder (false),
62 _no_redisplay (false),
63 _redisplay_does_not_sync_order_keys (false),
64 _redisplay_does_not_reset_order_keys (false),
67 _scroller.add (_display);
68 _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
70 _model = ListStore::create (_columns);
71 _display.set_model (_model);
73 // Record enable toggle
74 CellRendererPixbufToggle* rec_col_renderer = manage (new CellRendererPixbufToggle());
76 rec_col_renderer->set_active_pixbuf (::get_icon("rec-enabled"));
77 rec_col_renderer->set_inactive_pixbuf (::get_icon("act-disabled"));
78 rec_col_renderer->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_rec_enable_toggled));
80 TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer));
82 rec_state_column->add_attribute(rec_col_renderer->property_active(), _columns.rec_enabled);
83 rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
86 CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
88 mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
89 mute_col_renderer->set_pixbuf (1, ::get_icon("mute-enabled"));
90 mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
92 TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
94 mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
97 CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
99 solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
100 solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
101 solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
103 TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
105 solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
107 // Solo isolate toggle
108 CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti());
110 solo_iso_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
111 solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolated"));
112 solo_iso_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled));
114 TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("I", *solo_iso_renderer));
116 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state);
118 _display.append_column (*rec_state_column);
119 _display.append_column (*mute_state_column);
120 _display.append_column (*solo_state_column);
121 _display.append_column (*solo_isolate_state_column);
122 _display.append_column (_("Show"), _columns.visible);
123 _display.append_column (_("Name"), _columns.text);
125 _display.set_headers_visible (true);
126 _display.set_name ("TrackListDisplay");
127 _display.get_selection()->set_mode (SELECTION_SINGLE);
128 _display.set_reorderable (true);
129 _display.set_rules_hint (true);
130 _display.set_size_request (100, -1);
131 _display.add_object_drag (_columns.route.index(), "routes");
133 CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (5));
136 TreeViewColumn* name_column = _display.get_column (5);
137 assert (name_column);
139 name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
140 name_cell->property_editable() = true;
141 name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit));
143 CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (4));
145 visible_cell->property_activatable() = true;
146 visible_cell->property_radio() = false;
147 visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::visible_changed));
149 _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::route_deleted));
150 _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered));
151 _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false);
153 Route::SyncOrderKeys.connect (*this, (sigc::mem_fun (*this, &EditorRoutes::sync_order_keys)));
157 EditorRoutes::set_session (Session* s)
159 EditorComponent::set_session (s);
164 _session->SoloChanged.connect (*this, (sigc::mem_fun (*this, &EditorRoutes::solo_changed_so_update_mute)));
169 EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
171 // Get the model row that has been toggled.
172 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
174 row[_columns.name_editable] = !row[_columns.rec_enabled];
176 TimeAxisView *tv = row[_columns.tv];
177 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
179 if (atv != 0 && atv->is_audio_track()){
180 boost::shared_ptr<RouteList> rl (new RouteList);
181 rl->push_back (atv->route());
182 _session->set_record_enable (rl, !atv->track()->record_enabled(), Session::rt_cleanup);
187 EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
189 // Get the model row that has been toggled.
190 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
192 TimeAxisView *tv = row[_columns.tv];
193 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
196 boost::shared_ptr<RouteList> rl (new RouteList);
197 rl->push_back (atv->route());
198 _session->set_mute (rl, !atv->route()->muted(), Session::rt_cleanup);
203 EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
205 // Get the model row that has been toggled.
206 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
208 TimeAxisView *tv = row[_columns.tv];
209 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
212 boost::shared_ptr<RouteList> rl (new RouteList);
213 rl->push_back (atv->route());
214 _session->set_solo (rl, !atv->route()->soloed(), Session::rt_cleanup);
219 EditorRoutes::on_tv_solo_isolate_toggled (Glib::ustring const & path_string)
221 // Get the model row that has been toggled.
222 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
224 TimeAxisView *tv = row[_columns.tv];
225 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
228 atv->route()->set_solo_isolated (!atv->route()->solo_isolated(), this);
233 EditorRoutes::build_menu ()
235 using namespace Menu_Helpers;
240 MenuList& items = _menu->items();
241 _menu->set_name ("ArdourContextMenu");
243 items.push_back (MenuElem (_("Show All"), sigc::mem_fun (*this, &EditorRoutes::show_all_routes)));
244 items.push_back (MenuElem (_("Hide All"), sigc::mem_fun (*this, &EditorRoutes::hide_all_routes)));
245 items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
246 items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
247 items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus)));
248 items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
249 items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
253 EditorRoutes::show_menu ()
259 _menu->popup (1, gtk_get_current_event_time());
263 EditorRoutes::redisplay ()
265 if (_no_redisplay || !_session) {
269 TreeModel::Children rows = _model->children();
270 TreeModel::Children::iterator i;
274 for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
275 TimeAxisView *tv = (*i)[_columns.tv];
276 boost::shared_ptr<Route> route = (*i)[_columns.route];
279 // just a "title" row
283 if (!_redisplay_does_not_reset_order_keys) {
284 /* this reorder is caused by user action, so reassign sort order keys
287 route->set_order_key (N_ ("editor"), n);
290 bool visible = (*i)[_columns.visible];
292 /* show or hide the TimeAxisView */
294 tv->set_marked_for_display (true);
295 position += tv->show_at (position, n, &_editor->edit_controls_vbox);
296 tv->clip_to_viewport ();
298 tv->set_marked_for_display (false);
305 /* whenever we go idle, update the track view list to reflect the new order.
306 we can't do this here, because we could mess up something that is traversing
307 the track order and has caused a redisplay of the list.
309 Glib::signal_idle().connect (sigc::mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
311 _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
312 _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
314 if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
316 We're increasing the size of the canvas while the bottom is visible.
317 We scroll down to keep in step with the controls layout.
319 _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
322 if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
323 _session->sync_order_keys (N_ ("editor"));
328 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
330 /* this could require an order reset & sync */
331 _session->set_remote_control_ids();
332 _ignore_reorder = true;
334 _ignore_reorder = false;
339 EditorRoutes::visible_changed (Glib::ustring const & path)
343 if ((iter = _model->get_iter (path))) {
344 TimeAxisView* tv = (*iter)[_columns.tv];
346 bool visible = (*iter)[_columns.visible];
347 (*iter)[_columns.visible] = !visible;
351 _redisplay_does_not_reset_order_keys = true;
352 _session->set_remote_control_ids();
354 _redisplay_does_not_reset_order_keys = false;
358 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
362 _redisplay_does_not_sync_order_keys = true;
363 suspend_redisplay ();
365 for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
367 row = *(_model->append ());
369 row[_columns.text] = (*x)->route()->name();
370 row[_columns.visible] = (*x)->marked_for_display();
371 row[_columns.tv] = *x;
372 row[_columns.route] = (*x)->route ();
373 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
375 _ignore_reorder = true;
377 /* added a new fresh one at the end */
378 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
379 (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
382 _ignore_reorder = false;
384 boost::weak_ptr<Route> wr ((*x)->route());
386 (*x)->route()->gui_changed.connect (*this, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2));
387 (*x)->route()->NameChanged.connect (*this, boost::bind (&EditorRoutes::route_name_changed, this, wr));
388 (*x)->GoingAway.connect (*this, boost::bind (&EditorRoutes::route_removed, this, *x));
390 if ((*x)->is_track()) {
391 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
392 t->diskstream()->RecordEnableChanged.connect (*this, boost::bind (&EditorRoutes::update_rec_display, this));
395 (*x)->route()->mute_changed.connect (*this, boost::bind (&EditorRoutes::update_mute_display, this));
396 (*x)->route()->solo_changed.connect (*this, boost::bind (&EditorRoutes::update_solo_display, this));
397 (*x)->route()->solo_isolated_changed.connect (*this, boost::bind (&EditorRoutes::update_solo_isolate_display, this));
400 update_rec_display ();
402 _redisplay_does_not_sync_order_keys = false;
406 EditorRoutes::handle_gui_changes (string const & what, void *src)
408 ENSURE_GUI_THREAD (*this, &EditorRoutes::handle_gui_changes, what, src)
410 if (what == "track_height") {
411 /* Optional :make tracks change height while it happens, instead
414 //update_canvas_now ();
418 if (what == "visible_tracks") {
424 EditorRoutes::route_removed (TimeAxisView *tv)
426 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
428 TreeModel::Children rows = _model->children();
429 TreeModel::Children::iterator ri;
431 /* the core model has changed, there is no need to sync
435 _redisplay_does_not_sync_order_keys = true;
437 for (ri = rows.begin(); ri != rows.end(); ++ri) {
438 if ((*ri)[_columns.tv] == tv) {
444 _redisplay_does_not_sync_order_keys = false;
448 EditorRoutes::route_name_changed (boost::weak_ptr<Route> r)
450 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
452 boost::shared_ptr<Route> route = r.lock ();
457 TreeModel::Children rows = _model->children();
458 TreeModel::Children::iterator i;
460 for (i = rows.begin(); i != rows.end(); ++i) {
461 boost::shared_ptr<Route> t = (*i)[_columns.route];
463 (*i)[_columns.text] = route->name();
470 EditorRoutes::update_visibility ()
472 TreeModel::Children rows = _model->children();
473 TreeModel::Children::iterator i;
475 suspend_redisplay ();
477 for (i = rows.begin(); i != rows.end(); ++i) {
478 TimeAxisView *tv = (*i)[_columns.tv];
479 (*i)[_columns.visible] = tv->marked_for_display ();
480 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
487 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
489 TreeModel::Children rows = _model->children();
490 TreeModel::Children::iterator i;
492 for (i = rows.begin(); i != rows.end(); ++i) {
493 if ((*i)[_columns.tv] == &tv) {
494 (*i)[_columns.visible] = false;
501 EditorRoutes::show_track_in_display (TimeAxisView& tv)
503 TreeModel::Children rows = _model->children();
504 TreeModel::Children::iterator i;
506 for (i = rows.begin(); i != rows.end(); ++i) {
507 if ((*i)[_columns.tv] == &tv) {
508 (*i)[_columns.visible] = true;
515 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
520 /** If src != "editor", take editor order keys from each route and use them to rearrange the
521 * route list so that the visual arrangement of routes matches the order keys from the routes.
524 EditorRoutes::sync_order_keys (string const & src)
526 vector<int> neworder;
527 TreeModel::Children rows = _model->children();
528 TreeModel::Children::iterator ri;
530 if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
534 for (ri = rows.begin(); ri != rows.end(); ++ri) {
535 neworder.push_back (0);
538 bool changed = false;
541 for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
542 boost::shared_ptr<Route> route = (*ri)[_columns.route];
545 int new_key = route->order_key (N_ ("editor"));
547 neworder[new_key] = old_key;
549 if (new_key != old_key) {
555 _redisplay_does_not_reset_order_keys = true;
556 _model->reorder (neworder);
557 _redisplay_does_not_reset_order_keys = false;
563 EditorRoutes::hide_all_tracks (bool /*with_select*/)
565 TreeModel::Children rows = _model->children();
566 TreeModel::Children::iterator i;
568 suspend_redisplay ();
570 for (i = rows.begin(); i != rows.end(); ++i) {
572 TreeModel::Row row = (*i);
573 TimeAxisView *tv = row[_columns.tv];
579 row[_columns.visible] = false;
584 /* XXX this seems like a hack and half, but its not clear where to put this
588 //reset_scrolling_region ();
592 EditorRoutes::set_all_tracks_visibility (bool yn)
594 TreeModel::Children rows = _model->children();
595 TreeModel::Children::iterator i;
597 suspend_redisplay ();
599 for (i = rows.begin(); i != rows.end(); ++i) {
601 TreeModel::Row row = (*i);
602 TimeAxisView* tv = row[_columns.tv];
608 (*i)[_columns.visible] = yn;
615 EditorRoutes::set_all_audio_visibility (int tracks, bool yn)
617 TreeModel::Children rows = _model->children();
618 TreeModel::Children::iterator i;
620 suspend_redisplay ();
622 for (i = rows.begin(); i != rows.end(); ++i) {
623 TreeModel::Row row = (*i);
624 TimeAxisView* tv = row[_columns.tv];
625 AudioTimeAxisView* atv;
631 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
634 (*i)[_columns.visible] = yn;
638 if (atv->is_audio_track()) {
639 (*i)[_columns.visible] = yn;
644 if (!atv->is_audio_track()) {
645 (*i)[_columns.visible] = yn;
656 EditorRoutes::hide_all_routes ()
658 set_all_tracks_visibility (false);
662 EditorRoutes::show_all_routes ()
664 set_all_tracks_visibility (true);
668 EditorRoutes::show_all_audiobus ()
670 set_all_audio_visibility (2, true);
673 EditorRoutes::hide_all_audiobus ()
675 set_all_audio_visibility (2, false);
679 EditorRoutes::show_all_audiotracks()
681 set_all_audio_visibility (1, true);
684 EditorRoutes::hide_all_audiotracks ()
686 set_all_audio_visibility (1, false);
690 EditorRoutes::button_press (GdkEventButton* ev)
692 if (Keyboard::is_context_menu_event (ev)) {
701 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
706 struct EditorOrderRouteSorter {
707 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
708 /* use of ">" forces the correct sort order */
709 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
714 EditorRoutes::initial_display ()
716 suspend_redisplay ();
724 boost::shared_ptr<RouteList> routes = _session->get_routes();
725 RouteList r (*routes);
726 EditorOrderRouteSorter sorter;
729 _editor->handle_new_route (r);
731 /* don't show master bus in a new session */
733 if (ARDOUR_UI::instance()->session_is_new ()) {
735 TreeModel::Children rows = _model->children();
736 TreeModel::Children::iterator i;
738 _no_redisplay = true;
740 for (i = rows.begin(); i != rows.end(); ++i) {
741 TimeAxisView *tv = (*i)[_columns.tv];
742 RouteTimeAxisView *rtv;
744 if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
745 if (rtv->route()->is_master()) {
746 _display.get_selection()->unselect (i);
751 _no_redisplay = false;
759 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
761 _redisplay_does_not_sync_order_keys = true;
762 _session->set_remote_control_ids();
764 _redisplay_does_not_sync_order_keys = false;
768 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
770 const SelectionData& data,
771 guint info, guint time)
773 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
774 _display.on_drag_data_received (context, x, y, data, info, time);
778 context->drag_finish (true, false, time);
782 EditorRoutes::move_selected_tracks (bool up)
784 if (_editor->selection->tracks.empty()) {
788 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
789 std::list<ViewRoute> view_routes;
790 std::vector<int> neworder;
791 TreeModel::Children rows = _model->children();
792 TreeModel::Children::iterator ri;
794 for (ri = rows.begin(); ri != rows.end(); ++ri) {
795 TimeAxisView* tv = (*ri)[_columns.tv];
796 boost::shared_ptr<Route> route = (*ri)[_columns.route];
798 view_routes.push_back (ViewRoute (tv, route));
801 list<ViewRoute>::iterator trailing;
802 list<ViewRoute>::iterator leading;
806 trailing = view_routes.begin();
807 leading = view_routes.begin();
811 while (leading != view_routes.end()) {
812 if (_editor->selection->selected (leading->first)) {
813 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
814 leading = view_routes.erase (leading);
823 /* if we could use reverse_iterator in list::insert, this code
824 would be a beautiful reflection of the code above. but we can't
825 and so it looks like a bit of a mess.
828 trailing = view_routes.end();
829 leading = view_routes.end();
831 --leading; if (leading == view_routes.begin()) { return; }
837 if (_editor->selection->selected (leading->first)) {
838 list<ViewRoute>::iterator tmp;
840 /* need to insert *after* trailing, not *before* it,
841 which is what insert (iter, val) normally does.
847 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
849 /* can't use iter = cont.erase (iter); form here, because
850 we need iter to move backwards.
858 if (leading == view_routes.begin()) {
859 /* the one we've just inserted somewhere else
860 was the first in the list. erase this copy,
861 and then break, because we're done.
866 view_routes.erase (leading);
875 if (leading == view_routes.begin()) {
884 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
885 neworder.push_back (leading->second->order_key (N_ ("editor")));
888 _model->reorder (neworder);
890 _session->sync_order_keys (N_ ("editor"));
894 EditorRoutes::update_rec_display ()
896 TreeModel::Children rows = _model->children();
897 TreeModel::Children::iterator i;
899 for (i = rows.begin(); i != rows.end(); ++i) {
900 boost::shared_ptr<Route> route = (*i)[_columns.route];
902 if (boost::dynamic_pointer_cast<Track>(route)) {
903 (*i)[_columns.rec_enabled] = route->record_enabled ();
904 (*i)[_columns.name_editable] = !route->record_enabled ();
910 EditorRoutes::update_mute_display ()
912 TreeModel::Children rows = _model->children();
913 TreeModel::Children::iterator i;
915 for (i = rows.begin(); i != rows.end(); ++i) {
916 boost::shared_ptr<Route> route = (*i)[_columns.route];
917 (*i)[_columns.mute_state] = RouteUI::mute_visual_state (_session, route) > 0 ? 1 : 0;
922 EditorRoutes::update_solo_display ()
924 TreeModel::Children rows = _model->children();
925 TreeModel::Children::iterator i;
927 for (i = rows.begin(); i != rows.end(); ++i) {
928 boost::shared_ptr<Route> route = (*i)[_columns.route];
929 (*i)[_columns.solo_state] = RouteUI::solo_visual_state (route) > 0 ? 1 : 0;
934 EditorRoutes::update_solo_isolate_display ()
936 TreeModel::Children rows = _model->children();
937 TreeModel::Children::iterator i;
939 for (i = rows.begin(); i != rows.end(); ++i) {
940 boost::shared_ptr<Route> route = (*i)[_columns.route];
941 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_visual_state (route) > 0 ? 1 : 0;
946 EditorRoutes::views () const
948 list<TimeAxisView*> v;
949 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
950 v.push_back ((*i)[_columns.tv]);
957 EditorRoutes::clear ()
959 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
961 _display.set_model (_model);
965 EditorRoutes::name_edit (Glib::ustring const & path, Glib::ustring const & new_text)
967 TreeIter iter = _model->get_iter (path);
972 boost::shared_ptr<Route> route = (*iter)[_columns.route];
974 if (route && route->name() != new_text) {
975 route->set_name (new_text);
980 EditorRoutes::solo_changed_so_update_mute ()
982 ENSURE_GUI_THREAD (*this, &EditorRoutes::solo_changed_so_update_mute)
983 update_mute_display ();
987 EditorRoutes::show_tracks_with_regions_at_playhead ()
989 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
991 set<TimeAxisView*> show;
992 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
993 TimeAxisView* tav = _editor->axis_view_from_route (*i);
999 suspend_redisplay ();
1001 TreeModel::Children rows = _model->children ();
1002 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1003 TimeAxisView* tv = (*i)[_columns.tv];
1004 (*i)[_columns.visible] = (show.find (tv) != show.end());
1007 resume_redisplay ();