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);
84 rec_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
85 rec_state_column->set_alignment(ALIGN_CENTER);
86 rec_state_column->set_expand(false);
87 rec_state_column->set_fixed_width(15);
90 CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
92 mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
93 mute_col_renderer->set_pixbuf (1, ::get_icon("mute-enabled"));
94 mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
96 TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
98 mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
99 mute_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
100 mute_state_column->set_alignment(ALIGN_CENTER);
101 mute_state_column->set_expand(false);
102 mute_state_column->set_fixed_width(15);
104 // Solo enable toggle
105 CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
107 solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
108 solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
109 solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
111 TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
113 solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
114 solo_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
115 solo_state_column->set_alignment(ALIGN_CENTER);
116 solo_state_column->set_expand(false);
117 solo_state_column->set_fixed_width(15);
119 // Solo isolate toggle
120 CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti());
122 solo_iso_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
123 solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolated"));
124 solo_iso_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled));
126 TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("I", *solo_iso_renderer));
128 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state);
129 solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
130 solo_isolate_state_column->set_alignment(ALIGN_CENTER);
131 solo_isolate_state_column->set_expand(false);
132 solo_isolate_state_column->set_fixed_width(15);
134 _display.append_column (*rec_state_column);
135 _display.append_column (*mute_state_column);
136 _display.append_column (*solo_state_column);
137 _display.append_column (*solo_isolate_state_column);
139 _display.append_column (_("Name"), _columns.text);
140 _display.append_column (_("V"), _columns.visible);
142 _display.set_headers_visible (true);
143 _display.set_name ("TrackListDisplay");
144 _display.get_selection()->set_mode (SELECTION_SINGLE);
145 _display.set_reorderable (true);
146 _display.set_rules_hint (true);
147 _display.set_size_request (100, -1);
148 _display.add_object_drag (_columns.route.index(), "routes");
150 CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (4));
154 TreeViewColumn* name_column = _display.get_column (4);
156 assert (name_column);
158 name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
159 name_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
160 name_column->set_expand(true);
161 name_column->set_min_width(50);
163 name_cell->property_editable() = true;
164 name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit));
166 // Set the visible column cell renderer to radio toggle
167 CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (5));
169 visible_cell->property_activatable() = true;
170 visible_cell->property_radio() = false;
171 visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::visible_changed));
173 TreeViewColumn* visible_col = dynamic_cast<TreeViewColumn*> (_display.get_column (5));
174 visible_col->set_expand(false);
175 visible_col->set_sizing(TREE_VIEW_COLUMN_FIXED);
176 visible_col->set_fixed_width(30);
177 visible_col->set_alignment(ALIGN_CENTER);
179 _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::route_deleted));
180 _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered));
182 _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false);
184 Route::SyncOrderKeys.connect (*this, ui_bind (&EditorRoutes::sync_order_keys, this, _1), gui_context());
188 EditorRoutes::set_session (Session* s)
190 EditorComponent::set_session (s);
195 _session->SoloChanged.connect (*this, boost::bind (&EditorRoutes::solo_changed_so_update_mute, this), gui_context());
200 EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
202 // Get the model row that has been toggled.
203 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
205 TimeAxisView *tv = row[_columns.tv];
206 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
208 if (atv != 0 && atv->is_audio_track()){
209 boost::shared_ptr<RouteList> rl (new RouteList);
210 rl->push_back (atv->route());
211 _session->set_record_enable (rl, !atv->track()->record_enabled(), Session::rt_cleanup);
216 EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
218 // Get the model row that has been toggled.
219 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
221 TimeAxisView *tv = row[_columns.tv];
222 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
225 boost::shared_ptr<RouteList> rl (new RouteList);
226 rl->push_back (atv->route());
227 _session->set_mute (rl, !atv->route()->muted(), Session::rt_cleanup);
232 EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
234 // Get the model row that has been toggled.
235 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
237 TimeAxisView *tv = row[_columns.tv];
238 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
241 boost::shared_ptr<RouteList> rl (new RouteList);
242 rl->push_back (atv->route());
243 _session->set_solo (rl, !atv->route()->soloed(), Session::rt_cleanup);
248 EditorRoutes::on_tv_solo_isolate_toggled (Glib::ustring const & path_string)
250 // Get the model row that has been toggled.
251 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
253 TimeAxisView *tv = row[_columns.tv];
254 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
257 atv->route()->set_solo_isolated (!atv->route()->solo_isolated(), this);
262 EditorRoutes::build_menu ()
264 using namespace Menu_Helpers;
269 MenuList& items = _menu->items();
270 _menu->set_name ("ArdourContextMenu");
272 items.push_back (MenuElem (_("Show All"), sigc::mem_fun (*this, &EditorRoutes::show_all_routes)));
273 items.push_back (MenuElem (_("Hide All"), sigc::mem_fun (*this, &EditorRoutes::hide_all_routes)));
274 items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
275 items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
276 items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus)));
277 items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
278 items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
282 EditorRoutes::show_menu ()
288 _menu->popup (1, gtk_get_current_event_time());
292 EditorRoutes::redisplay ()
294 if (_no_redisplay || !_session) {
298 TreeModel::Children rows = _model->children();
299 TreeModel::Children::iterator i;
303 for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
304 TimeAxisView *tv = (*i)[_columns.tv];
305 boost::shared_ptr<Route> route = (*i)[_columns.route];
308 // just a "title" row
312 if (!_redisplay_does_not_reset_order_keys) {
313 /* this reorder is caused by user action, so reassign sort order keys
316 route->set_order_key (N_ ("editor"), n);
319 bool visible = (*i)[_columns.visible];
321 /* show or hide the TimeAxisView */
323 tv->set_marked_for_display (true);
324 position += tv->show_at (position, n, &_editor->edit_controls_vbox);
325 tv->clip_to_viewport ();
327 tv->set_marked_for_display (false);
334 /* whenever we go idle, update the track view list to reflect the new order.
335 we can't do this here, because we could mess up something that is traversing
336 the track order and has caused a redisplay of the list.
338 Glib::signal_idle().connect (sigc::mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
340 _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
341 _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
343 if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
345 We're increasing the size of the canvas while the bottom is visible.
346 We scroll down to keep in step with the controls layout.
348 _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
351 if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
352 _session->sync_order_keys (N_ ("editor"));
357 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
359 if (!_session || _session->deletion_in_progress()) {
363 /* this could require an order reset & sync */
364 _session->set_remote_control_ids();
365 _ignore_reorder = true;
367 _ignore_reorder = false;
371 EditorRoutes::visible_changed (Glib::ustring const & path)
373 if (_session && _session->deletion_in_progress()) {
379 if ((iter = _model->get_iter (path))) {
380 TimeAxisView* tv = (*iter)[_columns.tv];
382 bool visible = (*iter)[_columns.visible];
383 (*iter)[_columns.visible] = !visible;
387 _redisplay_does_not_reset_order_keys = true;
388 _session->set_remote_control_ids();
390 _redisplay_does_not_reset_order_keys = false;
394 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
398 _redisplay_does_not_sync_order_keys = true;
399 suspend_redisplay ();
401 for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
403 row = *(_model->append ());
405 row[_columns.text] = (*x)->route()->name();
406 row[_columns.visible] = (*x)->marked_for_display();
407 row[_columns.tv] = *x;
408 row[_columns.route] = (*x)->route ();
409 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
410 row[_columns.mute_state] = (*x)->route()->muted();
411 row[_columns.solo_state] = (*x)->route()->soloed();
412 row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated();
413 row[_columns.name_editable] = true;
415 _ignore_reorder = true;
417 /* added a new fresh one at the end */
418 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
419 (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
422 _ignore_reorder = false;
424 boost::weak_ptr<Route> wr ((*x)->route());
426 (*x)->route()->gui_changed.connect (*this, ui_bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
427 (*x)->route()->NameChanged.connect (*this, boost::bind (&EditorRoutes::route_name_changed, this, wr), gui_context());
429 if ((*x)->is_track()) {
430 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
431 t->diskstream()->RecordEnableChanged.connect (*this, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
434 (*x)->route()->mute_changed.connect (*this, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
435 (*x)->route()->solo_changed.connect (*this, boost::bind (&EditorRoutes::update_solo_display, this), gui_context());
436 (*x)->route()->solo_isolated_changed.connect (*this, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
439 update_rec_display ();
440 update_mute_display ();
441 update_solo_display ();
442 update_solo_isolate_display ();
444 _redisplay_does_not_sync_order_keys = false;
448 EditorRoutes::handle_gui_changes (string const & what, void*)
450 ENSURE_GUI_THREAD (*this, &EditorRoutes::handle_gui_changes, what, src)
452 if (what == "track_height") {
453 /* Optional :make tracks change height while it happens, instead
456 //update_canvas_now ();
460 if (what == "visible_tracks") {
466 EditorRoutes::route_removed (TimeAxisView *tv)
468 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
470 TreeModel::Children rows = _model->children();
471 TreeModel::Children::iterator ri;
473 /* the core model has changed, there is no need to sync
477 _redisplay_does_not_sync_order_keys = true;
479 for (ri = rows.begin(); ri != rows.end(); ++ri) {
480 if ((*ri)[_columns.tv] == tv) {
486 _redisplay_does_not_sync_order_keys = false;
490 EditorRoutes::route_name_changed (boost::weak_ptr<Route> r)
492 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
494 boost::shared_ptr<Route> route = r.lock ();
499 TreeModel::Children rows = _model->children();
500 TreeModel::Children::iterator i;
502 for (i = rows.begin(); i != rows.end(); ++i) {
503 boost::shared_ptr<Route> t = (*i)[_columns.route];
505 (*i)[_columns.text] = route->name();
512 EditorRoutes::update_visibility ()
514 TreeModel::Children rows = _model->children();
515 TreeModel::Children::iterator i;
517 suspend_redisplay ();
519 for (i = rows.begin(); i != rows.end(); ++i) {
520 TimeAxisView *tv = (*i)[_columns.tv];
521 (*i)[_columns.visible] = tv->marked_for_display ();
522 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
529 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
531 TreeModel::Children rows = _model->children();
532 TreeModel::Children::iterator i;
534 for (i = rows.begin(); i != rows.end(); ++i) {
535 if ((*i)[_columns.tv] == &tv) {
536 (*i)[_columns.visible] = false;
543 EditorRoutes::show_track_in_display (TimeAxisView& tv)
545 TreeModel::Children rows = _model->children();
546 TreeModel::Children::iterator i;
548 for (i = rows.begin(); i != rows.end(); ++i) {
549 if ((*i)[_columns.tv] == &tv) {
550 (*i)[_columns.visible] = true;
557 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
562 /** If src != "editor", take editor order keys from each route and use them to rearrange the
563 * route list so that the visual arrangement of routes matches the order keys from the routes.
566 EditorRoutes::sync_order_keys (string const & src)
568 vector<int> neworder;
569 TreeModel::Children rows = _model->children();
570 TreeModel::Children::iterator ri;
572 if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
576 for (ri = rows.begin(); ri != rows.end(); ++ri) {
577 neworder.push_back (0);
580 bool changed = false;
583 for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
584 boost::shared_ptr<Route> route = (*ri)[_columns.route];
587 int new_key = route->order_key (N_ ("editor"));
589 neworder[new_key] = old_key;
591 if (new_key != old_key) {
597 _redisplay_does_not_reset_order_keys = true;
598 _model->reorder (neworder);
599 _redisplay_does_not_reset_order_keys = false;
605 EditorRoutes::hide_all_tracks (bool /*with_select*/)
607 TreeModel::Children rows = _model->children();
608 TreeModel::Children::iterator i;
610 suspend_redisplay ();
612 for (i = rows.begin(); i != rows.end(); ++i) {
614 TreeModel::Row row = (*i);
615 TimeAxisView *tv = row[_columns.tv];
621 row[_columns.visible] = false;
626 /* XXX this seems like a hack and half, but its not clear where to put this
630 //reset_scrolling_region ();
634 EditorRoutes::set_all_tracks_visibility (bool yn)
636 TreeModel::Children rows = _model->children();
637 TreeModel::Children::iterator i;
639 suspend_redisplay ();
641 for (i = rows.begin(); i != rows.end(); ++i) {
643 TreeModel::Row row = (*i);
644 TimeAxisView* tv = row[_columns.tv];
650 (*i)[_columns.visible] = yn;
657 EditorRoutes::set_all_audio_visibility (int tracks, bool yn)
659 TreeModel::Children rows = _model->children();
660 TreeModel::Children::iterator i;
662 suspend_redisplay ();
664 for (i = rows.begin(); i != rows.end(); ++i) {
665 TreeModel::Row row = (*i);
666 TimeAxisView* tv = row[_columns.tv];
667 AudioTimeAxisView* atv;
673 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
676 (*i)[_columns.visible] = yn;
680 if (atv->is_audio_track()) {
681 (*i)[_columns.visible] = yn;
686 if (!atv->is_audio_track()) {
687 (*i)[_columns.visible] = yn;
698 EditorRoutes::hide_all_routes ()
700 set_all_tracks_visibility (false);
704 EditorRoutes::show_all_routes ()
706 set_all_tracks_visibility (true);
710 EditorRoutes::show_all_audiobus ()
712 set_all_audio_visibility (2, true);
715 EditorRoutes::hide_all_audiobus ()
717 set_all_audio_visibility (2, false);
721 EditorRoutes::show_all_audiotracks()
723 set_all_audio_visibility (1, true);
726 EditorRoutes::hide_all_audiotracks ()
728 set_all_audio_visibility (1, false);
732 EditorRoutes::button_press (GdkEventButton* ev)
734 if (Keyboard::is_context_menu_event (ev)) {
739 //Scroll editor canvas to selected track
740 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
742 TreeModel::Path path;
747 _display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y);
749 // Get the model row.
750 Gtk::TreeModel::Row row = *_model->get_iter (path);
752 TimeAxisView *tv = row[_columns.tv];
754 int y_pos = tv->y_position();
756 //Clamp the y pos so that we do not extend beyond the canvas full height.
757 if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){
758 y_pos = _editor->full_canvas_height - _editor->_canvas_height;
761 //Only scroll to if the track is visible
763 _editor->reset_y_origin (y_pos);
771 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
776 struct EditorOrderRouteSorter {
777 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
778 /* use of ">" forces the correct sort order */
779 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
784 EditorRoutes::initial_display ()
786 suspend_redisplay ();
794 boost::shared_ptr<RouteList> routes = _session->get_routes();
795 RouteList r (*routes);
796 EditorOrderRouteSorter sorter;
799 _editor->handle_new_route (r);
801 /* don't show master bus in a new session */
803 if (ARDOUR_UI::instance()->session_is_new ()) {
805 TreeModel::Children rows = _model->children();
806 TreeModel::Children::iterator i;
808 _no_redisplay = true;
810 for (i = rows.begin(); i != rows.end(); ++i) {
812 TimeAxisView *tv = (*i)[_columns.tv];
813 RouteTimeAxisView *rtv;
815 if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
816 if (rtv->route()->is_master()) {
817 _display.get_selection()->unselect (i);
822 _no_redisplay = false;
830 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
832 _redisplay_does_not_sync_order_keys = true;
833 _session->set_remote_control_ids();
835 _redisplay_does_not_sync_order_keys = false;
839 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
841 const SelectionData& data,
842 guint info, guint time)
844 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
845 _display.on_drag_data_received (context, x, y, data, info, time);
849 context->drag_finish (true, false, time);
853 EditorRoutes::move_selected_tracks (bool up)
855 if (_editor->selection->tracks.empty()) {
859 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
860 std::list<ViewRoute> view_routes;
861 std::vector<int> neworder;
862 TreeModel::Children rows = _model->children();
863 TreeModel::Children::iterator ri;
865 for (ri = rows.begin(); ri != rows.end(); ++ri) {
866 TimeAxisView* tv = (*ri)[_columns.tv];
867 boost::shared_ptr<Route> route = (*ri)[_columns.route];
869 view_routes.push_back (ViewRoute (tv, route));
872 list<ViewRoute>::iterator trailing;
873 list<ViewRoute>::iterator leading;
877 trailing = view_routes.begin();
878 leading = view_routes.begin();
882 while (leading != view_routes.end()) {
883 if (_editor->selection->selected (leading->first)) {
884 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
885 leading = view_routes.erase (leading);
894 /* if we could use reverse_iterator in list::insert, this code
895 would be a beautiful reflection of the code above. but we can't
896 and so it looks like a bit of a mess.
899 trailing = view_routes.end();
900 leading = view_routes.end();
902 --leading; if (leading == view_routes.begin()) { return; }
908 if (_editor->selection->selected (leading->first)) {
909 list<ViewRoute>::iterator tmp;
911 /* need to insert *after* trailing, not *before* it,
912 which is what insert (iter, val) normally does.
918 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
920 /* can't use iter = cont.erase (iter); form here, because
921 we need iter to move backwards.
929 if (leading == view_routes.begin()) {
930 /* the one we've just inserted somewhere else
931 was the first in the list. erase this copy,
932 and then break, because we're done.
937 view_routes.erase (leading);
946 if (leading == view_routes.begin()) {
955 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
956 neworder.push_back (leading->second->order_key (N_ ("editor")));
959 _model->reorder (neworder);
961 _session->sync_order_keys (N_ ("editor"));
965 EditorRoutes::update_rec_display ()
967 TreeModel::Children rows = _model->children();
968 TreeModel::Children::iterator i;
970 for (i = rows.begin(); i != rows.end(); ++i) {
971 boost::shared_ptr<Route> route = (*i)[_columns.route];
973 if (boost::dynamic_pointer_cast<Track>(route)) {
974 (*i)[_columns.rec_enabled] = route->record_enabled ();
975 (*i)[_columns.name_editable] = !route->record_enabled ();
981 EditorRoutes::update_mute_display ()
983 TreeModel::Children rows = _model->children();
984 TreeModel::Children::iterator i;
986 for (i = rows.begin(); i != rows.end(); ++i) {
987 boost::shared_ptr<Route> route = (*i)[_columns.route];
988 (*i)[_columns.mute_state] = RouteUI::mute_visual_state (_session, route) > 0 ? 1 : 0;
993 EditorRoutes::update_solo_display ()
995 TreeModel::Children rows = _model->children();
996 TreeModel::Children::iterator i;
998 for (i = rows.begin(); i != rows.end(); ++i) {
999 boost::shared_ptr<Route> route = (*i)[_columns.route];
1000 (*i)[_columns.solo_state] = RouteUI::solo_visual_state (route) > 0 ? 1 : 0;
1005 EditorRoutes::update_solo_isolate_display ()
1007 TreeModel::Children rows = _model->children();
1008 TreeModel::Children::iterator i;
1010 for (i = rows.begin(); i != rows.end(); ++i) {
1011 boost::shared_ptr<Route> route = (*i)[_columns.route];
1012 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_visual_state (route) > 0 ? 1 : 0;
1017 EditorRoutes::views () const
1019 list<TimeAxisView*> v;
1020 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1021 v.push_back ((*i)[_columns.tv]);
1028 EditorRoutes::clear ()
1030 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1032 _display.set_model (_model);
1036 EditorRoutes::name_edit (Glib::ustring const & path, Glib::ustring const & new_text)
1038 TreeIter iter = _model->get_iter (path);
1043 boost::shared_ptr<Route> route = (*iter)[_columns.route];
1045 if (route && route->name() != new_text) {
1046 route->set_name (new_text);
1051 EditorRoutes::solo_changed_so_update_mute ()
1053 ENSURE_GUI_THREAD (*this, &EditorRoutes::solo_changed_so_update_mute)
1054 update_mute_display ();
1058 EditorRoutes::show_tracks_with_regions_at_playhead ()
1060 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1062 set<TimeAxisView*> show;
1063 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1064 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1070 suspend_redisplay ();
1072 TreeModel::Children rows = _model->children ();
1073 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1074 TimeAxisView* tv = (*i)[_columns.tv];
1075 (*i)[_columns.visible] = (show.find (tv) != show.end());
1078 resume_redisplay ();