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"
53 using namespace ARDOUR;
56 using namespace Gtkmm2ext;
58 using Gtkmm2ext::Keyboard;
60 EditorRoutes::EditorRoutes (Editor* e)
61 : EditorComponent (e),
62 _ignore_reorder (false),
63 _no_redisplay (false),
64 _redisplay_does_not_sync_order_keys (false),
65 _redisplay_does_not_reset_order_keys (false),
68 _scroller.add (_display);
69 _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
71 _model = ListStore::create (_columns);
72 _display.set_model (_model);
74 // Record enable toggle
75 CellRendererPixbufToggle* rec_col_renderer = manage (new CellRendererPixbufToggle());
77 rec_col_renderer->set_active_pixbuf (::get_icon("rec-enabled"));
78 rec_col_renderer->set_inactive_pixbuf (::get_icon("act-disabled"));
79 rec_col_renderer->signal_toggled().connect (mem_fun (*this, &EditorRoutes::on_tv_rec_enable_toggled));
81 TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer));
83 rec_state_column->add_attribute(rec_col_renderer->property_active(), _columns.rec_enabled);
84 rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
87 CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
89 mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
90 mute_col_renderer->set_pixbuf (1, ::get_icon("mute-enabled"));
91 mute_col_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
93 TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
95 mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
98 CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
100 solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
101 solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
102 solo_col_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
104 TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
106 solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
108 // Solo isolate toggle
109 CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti());
111 solo_iso_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
112 solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolated"));
113 solo_iso_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled));
115 TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("I", *solo_iso_renderer));
117 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state);
119 _display.append_column (*rec_state_column);
120 _display.append_column (*mute_state_column);
121 _display.append_column (*solo_state_column);
122 _display.append_column (*solo_isolate_state_column);
123 _display.append_column (_("Show"), _columns.visible);
124 _display.append_column (_("Name"), _columns.text);
126 _display.set_headers_visible (true);
127 _display.set_name ("TrackListDisplay");
128 _display.get_selection()->set_mode (SELECTION_SINGLE);
129 _display.set_reorderable (true);
130 _display.set_rules_hint (true);
131 _display.set_size_request (100, -1);
132 _display.add_object_drag (_columns.route.index(), "routes");
134 CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (5));
137 TreeViewColumn* name_column = _display.get_column (5);
138 assert (name_column);
140 name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
141 name_cell->property_editable() = true;
142 name_cell->signal_edited().connect (mem_fun (*this, &EditorRoutes::name_edit));
144 CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (4));
146 visible_cell->property_activatable() = true;
147 visible_cell->property_radio() = false;
148 visible_cell->signal_toggled().connect (mem_fun (*this, &EditorRoutes::visible_changed));
150 _model->signal_row_deleted().connect (mem_fun (*this, &EditorRoutes::route_deleted));
151 _model->signal_rows_reordered().connect (mem_fun (*this, &EditorRoutes::reordered));
152 _display.signal_button_press_event().connect (mem_fun (*this, &EditorRoutes::button_press), false);
154 Route::SyncOrderKeys.connect (mem_fun (*this, &EditorRoutes::sync_order_keys));
158 EditorRoutes::connect_to_session (Session* s)
160 EditorComponent::connect_to_session (s);
164 _session->SoloChanged.connect (mem_fun (*this, &EditorRoutes::solo_changed_so_update_mute));
168 EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
170 // Get the model row that has been toggled.
171 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
173 row[_columns.name_editable] = !row[_columns.rec_enabled];
175 TimeAxisView *tv = row[_columns.tv];
176 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
178 if (atv != 0 && atv->is_audio_track()){
179 boost::shared_ptr<RouteList> rl (new RouteList);
180 rl->push_back (atv->route());
181 _session->set_record_enable (rl, !atv->track()->record_enabled(), Session::rt_cleanup);
186 EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
188 // Get the model row that has been toggled.
189 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
191 TimeAxisView *tv = row[_columns.tv];
192 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
195 boost::shared_ptr<RouteList> rl (new RouteList);
196 rl->push_back (atv->route());
197 _session->set_mute (rl, !atv->route()->muted(), Session::rt_cleanup);
202 EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
204 // Get the model row that has been toggled.
205 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
207 TimeAxisView *tv = row[_columns.tv];
208 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
211 boost::shared_ptr<RouteList> rl (new RouteList);
212 rl->push_back (atv->route());
213 _session->set_solo (rl, !atv->route()->soloed(), Session::rt_cleanup);
218 EditorRoutes::on_tv_solo_isolate_toggled (Glib::ustring const & path_string)
220 // Get the model row that has been toggled.
221 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
223 TimeAxisView *tv = row[_columns.tv];
224 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
227 atv->route()->set_solo_isolated (!atv->route()->solo_isolated(), this);
232 EditorRoutes::build_menu ()
234 using namespace Menu_Helpers;
239 MenuList& items = _menu->items();
240 _menu->set_name ("ArdourContextMenu");
242 items.push_back (MenuElem (_("Show All"), mem_fun (*this, &EditorRoutes::show_all_routes)));
243 items.push_back (MenuElem (_("Hide All"), mem_fun (*this, &EditorRoutes::hide_all_routes)));
244 items.push_back (MenuElem (_("Show All Audio Tracks"), mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
245 items.push_back (MenuElem (_("Hide All Audio Tracks"), mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
246 items.push_back (MenuElem (_("Show All Audio Busses"), mem_fun (*this, &EditorRoutes::show_all_audiobus)));
247 items.push_back (MenuElem (_("Hide All Audio Busses"), mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
248 items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
252 EditorRoutes::show_menu ()
258 _menu->popup (1, gtk_get_current_event_time());
262 EditorRoutes::redisplay ()
264 TreeModel::Children rows = _model->children();
265 TreeModel::Children::iterator i;
273 for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
274 TimeAxisView *tv = (*i)[_columns.tv];
275 boost::shared_ptr<Route> route = (*i)[_columns.route];
278 // just a "title" row
282 if (!_redisplay_does_not_reset_order_keys) {
283 /* this reorder is caused by user action, so reassign sort order keys
286 route->set_order_key (N_ ("editor"), n);
289 bool visible = (*i)[_columns.visible];
291 /* show or hide the TimeAxisView */
293 tv->set_marked_for_display (true);
294 position += tv->show_at (position, n, &_editor->edit_controls_vbox);
295 tv->clip_to_viewport ();
297 tv->set_marked_for_display (false);
304 /* whenever we go idle, update the track view list to reflect the new order.
305 we can't do this here, because we could mess up something that is traversing
306 the track order and has caused a redisplay of the list.
308 Glib::signal_idle().connect (mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
310 _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
311 _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
313 if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
315 We're increasing the size of the canvas while the bottom is visible.
316 We scroll down to keep in step with the controls layout.
318 _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
321 if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
322 _session->sync_order_keys (N_ ("editor"));
327 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
329 /* this could require an order reset & sync */
330 _session->set_remote_control_ids();
331 _ignore_reorder = true;
333 _ignore_reorder = false;
338 EditorRoutes::visible_changed (Glib::ustring const & path)
342 if ((iter = _model->get_iter (path))) {
343 TimeAxisView* tv = (*iter)[_columns.tv];
345 bool visible = (*iter)[_columns.visible];
346 (*iter)[_columns.visible] = !visible;
350 _redisplay_does_not_reset_order_keys = true;
351 _session->set_remote_control_ids();
353 _redisplay_does_not_reset_order_keys = false;
357 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
361 _redisplay_does_not_sync_order_keys = true;
362 suspend_redisplay ();
364 for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
366 row = *(_model->append ());
368 row[_columns.text] = (*x)->route()->name();
369 row[_columns.visible] = (*x)->marked_for_display();
370 row[_columns.tv] = *x;
371 row[_columns.route] = (*x)->route ();
372 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
374 _ignore_reorder = true;
376 /* added a new fresh one at the end */
377 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
378 (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
381 _ignore_reorder = false;
383 boost::weak_ptr<Route> wr ((*x)->route());
384 (*x)->route()->gui_changed.connect (mem_fun (*this, &EditorRoutes::handle_gui_changes));
385 (*x)->route()->NameChanged.connect (bind (mem_fun (*this, &EditorRoutes::route_name_changed), wr));
386 (*x)->GoingAway.connect (bind (mem_fun (*this, &EditorRoutes::route_removed), *x));
388 if ((*x)->is_track()) {
389 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
390 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &EditorRoutes::update_rec_display));
393 (*x)->route()->mute_changed.connect (mem_fun (*this, &EditorRoutes::update_mute_display));
394 (*x)->route()->solo_changed.connect (mem_fun (*this, &EditorRoutes::update_solo_display));
395 (*x)->route()->solo_isolated_changed.connect (mem_fun (*this, &EditorRoutes::update_solo_isolate_display));
398 update_rec_display ();
400 _redisplay_does_not_sync_order_keys = false;
404 EditorRoutes::handle_gui_changes (string const & what, void *src)
406 ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRoutes::handle_gui_changes), what, src));
408 if (what == "track_height") {
409 /* Optional :make tracks change height while it happens, instead
412 //update_canvas_now ();
416 if (what == "visible_tracks") {
422 EditorRoutes::route_removed (TimeAxisView *tv)
424 ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRoutes::route_removed), tv));
426 TreeModel::Children rows = _model->children();
427 TreeModel::Children::iterator ri;
429 /* the core model has changed, there is no need to sync
433 _redisplay_does_not_sync_order_keys = true;
435 for (ri = rows.begin(); ri != rows.end(); ++ri) {
436 if ((*ri)[_columns.tv] == tv) {
442 _redisplay_does_not_sync_order_keys = false;
446 EditorRoutes::route_name_changed (boost::weak_ptr<Route> r)
448 ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRoutes::route_name_changed), r));
450 boost::shared_ptr<Route> route = r.lock ();
455 TreeModel::Children rows = _model->children();
456 TreeModel::Children::iterator i;
458 for (i = rows.begin(); i != rows.end(); ++i) {
459 boost::shared_ptr<Route> t = (*i)[_columns.route];
461 (*i)[_columns.text] = route->name();
468 EditorRoutes::update_visibility ()
470 TreeModel::Children rows = _model->children();
471 TreeModel::Children::iterator i;
473 suspend_redisplay ();
475 for (i = rows.begin(); i != rows.end(); ++i) {
476 TimeAxisView *tv = (*i)[_columns.tv];
477 (*i)[_columns.visible] = tv->marked_for_display ();
478 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
485 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
487 TreeModel::Children rows = _model->children();
488 TreeModel::Children::iterator i;
490 for (i = rows.begin(); i != rows.end(); ++i) {
491 if ((*i)[_columns.tv] == &tv) {
492 (*i)[_columns.visible] = false;
499 EditorRoutes::show_track_in_display (TimeAxisView& tv)
501 TreeModel::Children rows = _model->children();
502 TreeModel::Children::iterator i;
504 for (i = rows.begin(); i != rows.end(); ++i) {
505 if ((*i)[_columns.tv] == &tv) {
506 (*i)[_columns.visible] = true;
513 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
518 /** If src != "editor", take editor order keys from each route and use them to rearrange the
519 * route list so that the visual arrangement of routes matches the order keys from the routes.
522 EditorRoutes::sync_order_keys (string const & src)
524 vector<int> neworder;
525 TreeModel::Children rows = _model->children();
526 TreeModel::Children::iterator ri;
528 if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
532 for (ri = rows.begin(); ri != rows.end(); ++ri) {
533 neworder.push_back (0);
536 bool changed = false;
539 for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
540 boost::shared_ptr<Route> route = (*ri)[_columns.route];
543 int new_key = route->order_key (N_ ("editor"));
545 neworder[new_key] = old_key;
547 if (new_key != old_key) {
553 _redisplay_does_not_reset_order_keys = true;
554 _model->reorder (neworder);
555 _redisplay_does_not_reset_order_keys = false;
561 EditorRoutes::hide_all_tracks (bool /*with_select*/)
563 TreeModel::Children rows = _model->children();
564 TreeModel::Children::iterator i;
566 suspend_redisplay ();
568 for (i = rows.begin(); i != rows.end(); ++i) {
570 TreeModel::Row row = (*i);
571 TimeAxisView *tv = row[_columns.tv];
577 row[_columns.visible] = false;
582 /* XXX this seems like a hack and half, but its not clear where to put this
586 //reset_scrolling_region ();
590 EditorRoutes::set_all_tracks_visibility (bool yn)
592 TreeModel::Children rows = _model->children();
593 TreeModel::Children::iterator i;
595 suspend_redisplay ();
597 for (i = rows.begin(); i != rows.end(); ++i) {
599 TreeModel::Row row = (*i);
600 TimeAxisView* tv = row[_columns.tv];
606 (*i)[_columns.visible] = yn;
613 EditorRoutes::set_all_audio_visibility (int tracks, bool yn)
615 TreeModel::Children rows = _model->children();
616 TreeModel::Children::iterator i;
618 suspend_redisplay ();
620 for (i = rows.begin(); i != rows.end(); ++i) {
621 TreeModel::Row row = (*i);
622 TimeAxisView* tv = row[_columns.tv];
623 AudioTimeAxisView* atv;
629 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
632 (*i)[_columns.visible] = yn;
636 if (atv->is_audio_track()) {
637 (*i)[_columns.visible] = yn;
642 if (!atv->is_audio_track()) {
643 (*i)[_columns.visible] = yn;
654 EditorRoutes::hide_all_routes ()
656 set_all_tracks_visibility (false);
660 EditorRoutes::show_all_routes ()
662 set_all_tracks_visibility (true);
666 EditorRoutes::show_all_audiobus ()
668 set_all_audio_visibility (2, true);
671 EditorRoutes::hide_all_audiobus ()
673 set_all_audio_visibility (2, false);
677 EditorRoutes::show_all_audiotracks()
679 set_all_audio_visibility (1, true);
682 EditorRoutes::hide_all_audiotracks ()
684 set_all_audio_visibility (1, false);
688 EditorRoutes::button_press (GdkEventButton* ev)
690 if (Keyboard::is_context_menu_event (ev)) {
699 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
704 struct EditorOrderRouteSorter {
705 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
706 /* use of ">" forces the correct sort order */
707 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
712 EditorRoutes::initial_display ()
714 boost::shared_ptr<RouteList> routes = _session->get_routes();
715 RouteList r (*routes);
716 EditorOrderRouteSorter sorter;
720 suspend_redisplay ();
723 _editor->handle_new_route (r);
725 /* don't show master bus in a new session */
727 if (ARDOUR_UI::instance()->session_is_new ()) {
729 TreeModel::Children rows = _model->children();
730 TreeModel::Children::iterator i;
732 _no_redisplay = true;
734 for (i = rows.begin(); i != rows.end(); ++i) {
735 TimeAxisView *tv = (*i)[_columns.tv];
736 RouteTimeAxisView *rtv;
738 if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
739 if (rtv->route()->is_master()) {
740 _display.get_selection()->unselect (i);
745 _no_redisplay = false;
753 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
755 _redisplay_does_not_sync_order_keys = true;
756 _session->set_remote_control_ids();
758 _redisplay_does_not_sync_order_keys = false;
762 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
764 const SelectionData& data,
765 guint info, guint time)
767 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
768 _display.on_drag_data_received (context, x, y, data, info, time);
772 context->drag_finish (true, false, time);
776 EditorRoutes::move_selected_tracks (bool up)
778 if (_editor->selection->tracks.empty()) {
782 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
783 std::list<ViewRoute> view_routes;
784 std::vector<int> neworder;
785 TreeModel::Children rows = _model->children();
786 TreeModel::Children::iterator ri;
788 for (ri = rows.begin(); ri != rows.end(); ++ri) {
789 TimeAxisView* tv = (*ri)[_columns.tv];
790 boost::shared_ptr<Route> route = (*ri)[_columns.route];
792 view_routes.push_back (ViewRoute (tv, route));
795 list<ViewRoute>::iterator trailing;
796 list<ViewRoute>::iterator leading;
800 trailing = view_routes.begin();
801 leading = view_routes.begin();
805 while (leading != view_routes.end()) {
806 if (_editor->selection->selected (leading->first)) {
807 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
808 leading = view_routes.erase (leading);
817 /* if we could use reverse_iterator in list::insert, this code
818 would be a beautiful reflection of the code above. but we can't
819 and so it looks like a bit of a mess.
822 trailing = view_routes.end();
823 leading = view_routes.end();
825 --leading; if (leading == view_routes.begin()) { return; }
831 if (_editor->selection->selected (leading->first)) {
832 list<ViewRoute>::iterator tmp;
834 /* need to insert *after* trailing, not *before* it,
835 which is what insert (iter, val) normally does.
841 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
843 /* can't use iter = cont.erase (iter); form here, because
844 we need iter to move backwards.
852 if (leading == view_routes.begin()) {
853 /* the one we've just inserted somewhere else
854 was the first in the list. erase this copy,
855 and then break, because we're done.
860 view_routes.erase (leading);
869 if (leading == view_routes.begin()) {
878 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
879 neworder.push_back (leading->second->order_key (N_ ("editor")));
882 _model->reorder (neworder);
884 _session->sync_order_keys (N_ ("editor"));
888 EditorRoutes::update_rec_display ()
890 TreeModel::Children rows = _model->children();
891 TreeModel::Children::iterator i;
893 for (i = rows.begin(); i != rows.end(); ++i) {
894 boost::shared_ptr<Route> route = (*i)[_columns.route];
896 if (boost::dynamic_pointer_cast<Track>(route)) {
897 (*i)[_columns.rec_enabled] = route->record_enabled ();
898 (*i)[_columns.name_editable] = !route->record_enabled ();
904 EditorRoutes::update_mute_display (void* /*src*/)
906 TreeModel::Children rows = _model->children();
907 TreeModel::Children::iterator i;
909 for (i = rows.begin(); i != rows.end(); ++i) {
910 boost::shared_ptr<Route> route = (*i)[_columns.route];
911 (*i)[_columns.mute_state] = RouteUI::mute_visual_state (*_session, route) > 0 ? 1 : 0;
916 EditorRoutes::update_solo_display (void* /*src*/)
918 TreeModel::Children rows = _model->children();
919 TreeModel::Children::iterator i;
921 for (i = rows.begin(); i != rows.end(); ++i) {
922 boost::shared_ptr<Route> route = (*i)[_columns.route];
923 (*i)[_columns.solo_state] = RouteUI::solo_visual_state (route) > 0 ? 1 : 0;
928 EditorRoutes::update_solo_isolate_display (void* /*src*/)
930 TreeModel::Children rows = _model->children();
931 TreeModel::Children::iterator i;
933 for (i = rows.begin(); i != rows.end(); ++i) {
934 boost::shared_ptr<Route> route = (*i)[_columns.route];
935 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_visual_state (route) > 0 ? 1 : 0;
940 EditorRoutes::views () const
942 list<TimeAxisView*> v;
943 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
944 v.push_back ((*i)[_columns.tv]);
951 EditorRoutes::clear ()
953 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
955 _display.set_model (_model);
959 EditorRoutes::name_edit (Glib::ustring const & path, Glib::ustring const & new_text)
961 TreeIter iter = _model->get_iter (path);
966 boost::shared_ptr<Route> route = (*iter)[_columns.route];
968 if (route && route->name() != new_text) {
969 route->set_name (new_text);
974 EditorRoutes::solo_changed_so_update_mute ()
976 ENSURE_GUI_THREAD (mem_fun (*this, &EditorRoutes::solo_changed_so_update_mute));
978 update_mute_display (this);
982 EditorRoutes::show_tracks_with_regions_at_playhead ()
984 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
986 set<TimeAxisView*> show;
987 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
988 TimeAxisView* tav = _editor->axis_view_from_route (*i);
994 suspend_redisplay ();
996 TreeModel::Children rows = _model->children ();
997 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
998 TimeAxisView* tv = (*i)[_columns.tv];
999 (*i)[_columns.visible] = (show.find (tv) != show.end());
1002 resume_redisplay ();