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;
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 (mem_fun (*this, &EditorRoutes::on_tv_rec_enable_toggled));
80 Gtk::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 (mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
92 Gtk::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 (mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
103 Gtk::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 _display.append_column (*rec_state_column);
108 _display.append_column (*mute_state_column);
109 _display.append_column (*solo_state_column);
110 _display.append_column (_("Show"), _columns.visible);
111 _display.append_column (_("Name"), _columns.text);
113 _display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
114 _display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
115 _display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
116 _display.get_column (3)->set_data (X_("colnum"), GUINT_TO_POINTER(3));
117 _display.get_column (4)->set_data (X_("colnum"), GUINT_TO_POINTER(4));
119 _display.set_headers_visible (true);
120 _display.set_name ("TrackListDisplay");
121 _display.get_selection()->set_mode (SELECTION_SINGLE);
122 _display.set_reorderable (true);
123 _display.set_rules_hint (true);
124 _display.set_size_request (100, -1);
125 _display.add_object_drag (_columns.route.index(), "routes");
127 CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (4));
130 Gtk::TreeViewColumn* name_column = _display.get_column (4);
131 assert (name_column);
133 name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
135 name_cell->property_editable() = true;
136 name_cell->signal_edited().connect (mem_fun (*this, &EditorRoutes::name_edit));
138 CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (3));
140 visible_cell->property_activatable() = true;
141 visible_cell->property_radio() = false;
143 _model->signal_row_deleted().connect (mem_fun (*this, &EditorRoutes::route_deleted));
144 _model->signal_row_changed().connect (mem_fun (*this, &EditorRoutes::changed));
145 _model->signal_rows_reordered().connect (mem_fun (*this, &EditorRoutes::reordered));
146 _display.signal_button_press_event().connect (mem_fun (*this, &EditorRoutes::button_press), false);
148 Route::SyncOrderKeys.connect (mem_fun (*this, &EditorRoutes::sync_order_keys));
152 EditorRoutes::connect_to_session (Session* s)
154 EditorComponent::connect_to_session (s);
158 _session->SoloChanged.connect (mem_fun (*this, &EditorRoutes::solo_changed_so_update_mute));
162 EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
164 // Get the model row that has been toggled.
165 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
167 row[_columns.name_editable] = !row[_columns.rec_enabled];
169 TimeAxisView *tv = row[_columns.tv];
170 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
172 if (atv != 0 && atv->is_audio_track()){
173 atv->reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !atv->track()->record_enabled(), this);
178 EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
180 // Get the model row that has been toggled.
181 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
183 TimeAxisView *tv = row[_columns.tv];
184 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
187 atv->reversibly_apply_route_boolean ("mute-enable change", &Route::set_mute, !atv->route()->muted(), this);
192 EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
194 // Get the model row that has been toggled.
195 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
197 TimeAxisView *tv = row[_columns.tv];
198 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
201 atv->reversibly_apply_route_boolean ("solo-enable change", &Route::set_solo, !atv->route()->soloed(), this);
206 EditorRoutes::build_menu ()
208 using namespace Menu_Helpers;
213 MenuList& items = _menu->items();
214 _menu->set_name ("ArdourContextMenu");
216 items.push_back (MenuElem (_("Show All"), mem_fun (*this, &EditorRoutes::show_all_routes)));
217 items.push_back (MenuElem (_("Hide All"), mem_fun (*this, &EditorRoutes::hide_all_routes)));
218 items.push_back (MenuElem (_("Show All Audio Tracks"), mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
219 items.push_back (MenuElem (_("Hide All Audio Tracks"), mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
220 items.push_back (MenuElem (_("Show All Audio Busses"), mem_fun (*this, &EditorRoutes::show_all_audiobus)));
221 items.push_back (MenuElem (_("Hide All Audio Busses"), mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
222 items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
226 EditorRoutes::show_menu ()
232 _menu->popup (1, gtk_get_current_event_time());
236 EditorRoutes::redisplay ()
238 TreeModel::Children rows = _model->children();
239 TreeModel::Children::iterator i;
247 for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
248 TimeAxisView *tv = (*i)[_columns.tv];
249 boost::shared_ptr<Route> route = (*i)[_columns.route];
252 // just a "title" row
256 if (!_redisplay_does_not_reset_order_keys) {
257 /* this reorder is caused by user action, so reassign sort order keys
260 route->set_order_key (N_ ("editor"), n);
263 bool visible = (*i)[_columns.visible];
265 /* show or hide the TimeAxisView */
267 tv->set_marked_for_display (true);
268 position += tv->show_at (position, n, &_editor->edit_controls_vbox);
269 tv->clip_to_viewport ();
271 tv->set_marked_for_display (false);
278 /* whenever we go idle, update the track view list to reflect the new order.
279 we can't do this here, because we could mess up something that is traversing
280 the track order and has caused a redisplay of the list.
282 Glib::signal_idle().connect (mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
284 _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
285 _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
287 if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
289 We're increasing the size of the canvas while the bottom is visible.
290 We scroll down to keep in step with the controls layout.
292 _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
295 if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
296 _session->sync_order_keys (N_ ("editor"));
301 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
303 /* this could require an order reset & sync */
304 _session->set_remote_control_ids();
305 _ignore_reorder = true;
307 _ignore_reorder = false;
312 EditorRoutes::changed (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &)
314 /* never reset order keys because of a property change */
315 _redisplay_does_not_reset_order_keys = true;
316 _session->set_remote_control_ids();
318 _redisplay_does_not_reset_order_keys = false;
322 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
326 _redisplay_does_not_sync_order_keys = true;
327 suspend_redisplay ();
329 for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
331 row = *(_model->append ());
333 row[_columns.text] = (*x)->route()->name();
334 row[_columns.visible] = (*x)->marked_for_display();
335 row[_columns.tv] = *x;
336 row[_columns.route] = (*x)->route ();
337 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
339 _ignore_reorder = true;
341 /* added a new fresh one at the end */
342 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
343 (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
346 _ignore_reorder = false;
348 boost::weak_ptr<Route> wr ((*x)->route());
349 (*x)->route()->gui_changed.connect (mem_fun (*this, &EditorRoutes::handle_gui_changes));
350 (*x)->route()->NameChanged.connect (bind (mem_fun (*this, &EditorRoutes::route_name_changed), wr));
351 (*x)->GoingAway.connect (bind (mem_fun (*this, &EditorRoutes::route_removed), *x));
353 if ((*x)->is_track()) {
354 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
355 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &EditorRoutes::update_rec_display));
358 (*x)->route()->mute_changed.connect (mem_fun (*this, &EditorRoutes::update_mute_display));
359 (*x)->route()->solo_changed.connect (mem_fun (*this, &EditorRoutes::update_solo_display));
362 update_rec_display ();
364 _redisplay_does_not_sync_order_keys = false;
368 EditorRoutes::handle_gui_changes (string const & what, void *src)
370 ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRoutes::handle_gui_changes), what, src));
372 if (what == "track_height") {
373 /* Optional :make tracks change height while it happens, instead
376 //update_canvas_now ();
380 if (what == "visible_tracks") {
386 EditorRoutes::route_removed (TimeAxisView *tv)
388 ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRoutes::route_removed), tv));
390 TreeModel::Children rows = _model->children();
391 TreeModel::Children::iterator ri;
393 /* the core model has changed, there is no need to sync
397 _redisplay_does_not_sync_order_keys = true;
399 for (ri = rows.begin(); ri != rows.end(); ++ri) {
400 if ((*ri)[_columns.tv] == tv) {
406 _redisplay_does_not_sync_order_keys = false;
410 EditorRoutes::route_name_changed (boost::weak_ptr<Route> r)
412 ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRoutes::route_name_changed), r));
414 boost::shared_ptr<Route> route = r.lock ();
419 TreeModel::Children rows = _model->children();
420 TreeModel::Children::iterator i;
422 for (i = rows.begin(); i != rows.end(); ++i) {
423 boost::shared_ptr<Route> t = (*i)[_columns.route];
425 (*i)[_columns.text] = route->name();
432 EditorRoutes::update_visibility ()
434 TreeModel::Children rows = _model->children();
435 TreeModel::Children::iterator i;
437 suspend_redisplay ();
439 for (i = rows.begin(); i != rows.end(); ++i) {
440 TimeAxisView *tv = (*i)[_columns.tv];
441 (*i)[_columns.visible] = tv->marked_for_display ();
442 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
449 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
451 TreeModel::Children rows = _model->children();
452 TreeModel::Children::iterator i;
454 for (i = rows.begin(); i != rows.end(); ++i) {
455 if ((*i)[_columns.tv] == &tv) {
456 (*i)[_columns.visible] = false;
463 EditorRoutes::show_track_in_display (TimeAxisView& tv)
465 TreeModel::Children rows = _model->children();
466 TreeModel::Children::iterator i;
468 for (i = rows.begin(); i != rows.end(); ++i) {
469 if ((*i)[_columns.tv] == &tv) {
470 (*i)[_columns.visible] = true;
477 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
482 /** If src != "editor", take editor order keys from each route and use them to rearrange the
483 * route list so that the visual arrangement of routes matches the order keys from the routes.
486 EditorRoutes::sync_order_keys (string const & src)
488 vector<int> neworder;
489 TreeModel::Children rows = _model->children();
490 TreeModel::Children::iterator ri;
492 if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
496 for (ri = rows.begin(); ri != rows.end(); ++ri) {
497 neworder.push_back (0);
500 bool changed = false;
503 for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
504 boost::shared_ptr<Route> route = (*ri)[_columns.route];
507 int new_key = route->order_key (N_ ("editor"));
509 neworder[new_key] = old_key;
511 if (new_key != old_key) {
517 _redisplay_does_not_reset_order_keys = true;
518 _model->reorder (neworder);
519 _redisplay_does_not_reset_order_keys = false;
525 EditorRoutes::hide_all_tracks (bool /*with_select*/)
527 TreeModel::Children rows = _model->children();
528 TreeModel::Children::iterator i;
530 suspend_redisplay ();
532 for (i = rows.begin(); i != rows.end(); ++i) {
534 TreeModel::Row row = (*i);
535 TimeAxisView *tv = row[_columns.tv];
541 row[_columns.visible] = false;
546 /* XXX this seems like a hack and half, but its not clear where to put this
550 //reset_scrolling_region ();
554 EditorRoutes::set_all_tracks_visibility (bool yn)
556 TreeModel::Children rows = _model->children();
557 TreeModel::Children::iterator i;
559 suspend_redisplay ();
561 for (i = rows.begin(); i != rows.end(); ++i) {
563 TreeModel::Row row = (*i);
564 TimeAxisView* tv = row[_columns.tv];
570 (*i)[_columns.visible] = yn;
577 EditorRoutes::set_all_audio_visibility (int tracks, bool yn)
579 TreeModel::Children rows = _model->children();
580 TreeModel::Children::iterator i;
582 suspend_redisplay ();
584 for (i = rows.begin(); i != rows.end(); ++i) {
585 TreeModel::Row row = (*i);
586 TimeAxisView* tv = row[_columns.tv];
587 AudioTimeAxisView* atv;
593 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
596 (*i)[_columns.visible] = yn;
600 if (atv->is_audio_track()) {
601 (*i)[_columns.visible] = yn;
606 if (!atv->is_audio_track()) {
607 (*i)[_columns.visible] = yn;
618 EditorRoutes::hide_all_routes ()
620 set_all_tracks_visibility (false);
624 EditorRoutes::show_all_routes ()
626 set_all_tracks_visibility (true);
630 EditorRoutes::show_all_audiobus ()
632 set_all_audio_visibility (2, true);
635 EditorRoutes::hide_all_audiobus ()
637 set_all_audio_visibility (2, false);
641 EditorRoutes::show_all_audiotracks()
643 set_all_audio_visibility (1, true);
646 EditorRoutes::hide_all_audiotracks ()
648 set_all_audio_visibility (1, false);
652 EditorRoutes::button_press (GdkEventButton* ev)
654 if (Keyboard::is_context_menu_event (ev)) {
660 TreeModel::Path path;
661 TreeViewColumn* column;
665 if (!_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
669 switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) {
672 /* allow normal processing to occur */
675 /* allow normal processing to occur */
678 /* allow normal processing to occur */
681 if ((iter = _model->get_iter (path))) {
682 TimeAxisView* tv = (*iter)[_columns.tv];
684 bool visible = (*iter)[_columns.visible];
685 (*iter)[_columns.visible] = !visible;
691 /* allow normal processing to occur */
702 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
707 struct EditorOrderRouteSorter {
708 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
709 /* use of ">" forces the correct sort order */
710 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
715 EditorRoutes::initial_display ()
717 boost::shared_ptr<RouteList> routes = _session->get_routes();
718 RouteList r (*routes);
719 EditorOrderRouteSorter sorter;
723 suspend_redisplay ();
726 _editor->handle_new_route (r);
728 /* don't show master bus in a new session */
730 if (ARDOUR_UI::instance()->session_is_new ()) {
732 TreeModel::Children rows = _model->children();
733 TreeModel::Children::iterator i;
735 _no_redisplay = true;
737 for (i = rows.begin(); i != rows.end(); ++i) {
738 TimeAxisView *tv = (*i)[_columns.tv];
739 RouteTimeAxisView *rtv;
741 if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
742 if (rtv->route()->is_master()) {
743 _display.get_selection()->unselect (i);
748 _no_redisplay = false;
756 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
758 _redisplay_does_not_sync_order_keys = true;
759 _session->set_remote_control_ids();
761 _redisplay_does_not_sync_order_keys = false;
765 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
767 const SelectionData& data,
768 guint info, guint time)
770 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
771 _display.on_drag_data_received (context, x, y, data, info, time);
775 context->drag_finish (true, false, time);
779 EditorRoutes::move_selected_tracks (bool up)
781 if (_editor->selection->tracks.empty()) {
785 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
786 std::list<ViewRoute> view_routes;
787 std::vector<int> neworder;
788 TreeModel::Children rows = _model->children();
789 TreeModel::Children::iterator ri;
791 for (ri = rows.begin(); ri != rows.end(); ++ri) {
792 TimeAxisView* tv = (*ri)[_columns.tv];
793 boost::shared_ptr<Route> route = (*ri)[_columns.route];
795 view_routes.push_back (ViewRoute (tv, route));
798 list<ViewRoute>::iterator trailing;
799 list<ViewRoute>::iterator leading;
803 trailing = view_routes.begin();
804 leading = view_routes.begin();
808 while (leading != view_routes.end()) {
809 if (_editor->selection->selected (leading->first)) {
810 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
811 leading = view_routes.erase (leading);
820 /* if we could use reverse_iterator in list::insert, this code
821 would be a beautiful reflection of the code above. but we can't
822 and so it looks like a bit of a mess.
825 trailing = view_routes.end();
826 leading = view_routes.end();
828 --leading; if (leading == view_routes.begin()) { return; }
834 if (_editor->selection->selected (leading->first)) {
835 list<ViewRoute>::iterator tmp;
837 /* need to insert *after* trailing, not *before* it,
838 which is what insert (iter, val) normally does.
844 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
846 /* can't use iter = cont.erase (iter); form here, because
847 we need iter to move backwards.
855 if (leading == view_routes.begin()) {
856 /* the one we've just inserted somewhere else
857 was the first in the list. erase this copy,
858 and then break, because we're done.
863 view_routes.erase (leading);
872 if (leading == view_routes.begin()) {
881 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
882 neworder.push_back (leading->second->order_key (N_ ("editor")));
885 _model->reorder (neworder);
887 _session->sync_order_keys (N_ ("editor"));
891 EditorRoutes::update_rec_display ()
893 TreeModel::Children rows = _model->children();
894 TreeModel::Children::iterator i;
896 for (i = rows.begin(); i != rows.end(); ++i) {
897 boost::shared_ptr<Route> route = (*i)[_columns.route];
899 if (boost::dynamic_pointer_cast<Track>(route)) {
900 (*i)[_columns.rec_enabled] = route->record_enabled ();
901 (*i)[_columns.name_editable] = !route->record_enabled ();
907 EditorRoutes::update_mute_display (void* /*src*/)
909 TreeModel::Children rows = _model->children();
910 TreeModel::Children::iterator i;
912 for (i = rows.begin(); i != rows.end(); ++i) {
913 boost::shared_ptr<Route> route = (*i)[_columns.route];
914 (*i)[_columns.mute_state] = RouteUI::mute_visual_state (*_session, route) > 0 ? 1 : 0;
919 EditorRoutes::update_solo_display (void* /*src*/)
921 TreeModel::Children rows = _model->children();
922 TreeModel::Children::iterator i;
924 for (i = rows.begin(); i != rows.end(); ++i) {
925 boost::shared_ptr<Route> route = (*i)[_columns.route];
926 (*i)[_columns.solo_state] = RouteUI::solo_visual_state (route) > 0 ? 1 : 0;
931 EditorRoutes::views () const
933 list<TimeAxisView*> v;
934 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
935 v.push_back ((*i)[_columns.tv]);
942 EditorRoutes::clear ()
944 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
946 _display.set_model (_model);
950 EditorRoutes::name_edit (Glib::ustring const & path, Glib::ustring const & new_text)
952 TreeIter iter = _model->get_iter (path);
957 boost::shared_ptr<Route> route = (*iter)[_columns.route];
959 if (route && route->name() != new_text) {
960 route->set_name (new_text);
965 EditorRoutes::solo_changed_so_update_mute ()
967 ENSURE_GUI_THREAD (mem_fun (*this, &EditorRoutes::solo_changed_so_update_mute));
969 update_mute_display (this);
973 EditorRoutes::show_tracks_with_regions_at_playhead ()
975 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
977 set<TimeAxisView*> show;
978 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
979 cout << "show " << (*i)->name() << "\n";
980 TimeAxisView* tav = _editor->axis_view_from_route (i->get ());
986 suspend_redisplay ();
988 TreeModel::Children rows = _model->children ();
989 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
990 TimeAxisView* tv = (*i)[_columns.tv];
991 (*i)[_columns.visible] = (show.find (tv) != show.end());