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();
414 _ignore_reorder = true;
416 /* added a new fresh one at the end */
417 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
418 (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
421 _ignore_reorder = false;
423 boost::weak_ptr<Route> wr ((*x)->route());
425 (*x)->route()->gui_changed.connect (*this, ui_bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
426 (*x)->route()->NameChanged.connect (*this, boost::bind (&EditorRoutes::route_name_changed, this, wr), gui_context());
428 if ((*x)->is_track()) {
429 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
430 t->diskstream()->RecordEnableChanged.connect (*this, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
433 (*x)->route()->mute_changed.connect (*this, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
434 (*x)->route()->solo_changed.connect (*this, boost::bind (&EditorRoutes::update_solo_display, this), gui_context());
435 (*x)->route()->solo_isolated_changed.connect (*this, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
438 update_rec_display ();
439 update_mute_display ();
440 update_solo_display ();
441 update_solo_isolate_display ();
443 _redisplay_does_not_sync_order_keys = false;
447 EditorRoutes::handle_gui_changes (string const & what, void*)
449 ENSURE_GUI_THREAD (*this, &EditorRoutes::handle_gui_changes, what, src)
451 if (what == "track_height") {
452 /* Optional :make tracks change height while it happens, instead
455 //update_canvas_now ();
459 if (what == "visible_tracks") {
465 EditorRoutes::route_removed (TimeAxisView *tv)
467 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
469 TreeModel::Children rows = _model->children();
470 TreeModel::Children::iterator ri;
472 /* the core model has changed, there is no need to sync
476 _redisplay_does_not_sync_order_keys = true;
478 for (ri = rows.begin(); ri != rows.end(); ++ri) {
479 if ((*ri)[_columns.tv] == tv) {
485 _redisplay_does_not_sync_order_keys = false;
489 EditorRoutes::route_name_changed (boost::weak_ptr<Route> r)
491 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
493 boost::shared_ptr<Route> route = r.lock ();
498 TreeModel::Children rows = _model->children();
499 TreeModel::Children::iterator i;
501 for (i = rows.begin(); i != rows.end(); ++i) {
502 boost::shared_ptr<Route> t = (*i)[_columns.route];
504 (*i)[_columns.text] = route->name();
511 EditorRoutes::update_visibility ()
513 TreeModel::Children rows = _model->children();
514 TreeModel::Children::iterator i;
516 suspend_redisplay ();
518 for (i = rows.begin(); i != rows.end(); ++i) {
519 TimeAxisView *tv = (*i)[_columns.tv];
520 (*i)[_columns.visible] = tv->marked_for_display ();
521 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
528 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
530 TreeModel::Children rows = _model->children();
531 TreeModel::Children::iterator i;
533 for (i = rows.begin(); i != rows.end(); ++i) {
534 if ((*i)[_columns.tv] == &tv) {
535 (*i)[_columns.visible] = false;
542 EditorRoutes::show_track_in_display (TimeAxisView& tv)
544 TreeModel::Children rows = _model->children();
545 TreeModel::Children::iterator i;
547 for (i = rows.begin(); i != rows.end(); ++i) {
548 if ((*i)[_columns.tv] == &tv) {
549 (*i)[_columns.visible] = true;
556 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
561 /** If src != "editor", take editor order keys from each route and use them to rearrange the
562 * route list so that the visual arrangement of routes matches the order keys from the routes.
565 EditorRoutes::sync_order_keys (string const & src)
567 vector<int> neworder;
568 TreeModel::Children rows = _model->children();
569 TreeModel::Children::iterator ri;
571 if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
575 for (ri = rows.begin(); ri != rows.end(); ++ri) {
576 neworder.push_back (0);
579 bool changed = false;
582 for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
583 boost::shared_ptr<Route> route = (*ri)[_columns.route];
586 int new_key = route->order_key (N_ ("editor"));
588 neworder[new_key] = old_key;
590 if (new_key != old_key) {
596 _redisplay_does_not_reset_order_keys = true;
597 _model->reorder (neworder);
598 _redisplay_does_not_reset_order_keys = false;
604 EditorRoutes::hide_all_tracks (bool /*with_select*/)
606 TreeModel::Children rows = _model->children();
607 TreeModel::Children::iterator i;
609 suspend_redisplay ();
611 for (i = rows.begin(); i != rows.end(); ++i) {
613 TreeModel::Row row = (*i);
614 TimeAxisView *tv = row[_columns.tv];
620 row[_columns.visible] = false;
625 /* XXX this seems like a hack and half, but its not clear where to put this
629 //reset_scrolling_region ();
633 EditorRoutes::set_all_tracks_visibility (bool yn)
635 TreeModel::Children rows = _model->children();
636 TreeModel::Children::iterator i;
638 suspend_redisplay ();
640 for (i = rows.begin(); i != rows.end(); ++i) {
642 TreeModel::Row row = (*i);
643 TimeAxisView* tv = row[_columns.tv];
649 (*i)[_columns.visible] = yn;
656 EditorRoutes::set_all_audio_visibility (int tracks, bool yn)
658 TreeModel::Children rows = _model->children();
659 TreeModel::Children::iterator i;
661 suspend_redisplay ();
663 for (i = rows.begin(); i != rows.end(); ++i) {
664 TreeModel::Row row = (*i);
665 TimeAxisView* tv = row[_columns.tv];
666 AudioTimeAxisView* atv;
672 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
675 (*i)[_columns.visible] = yn;
679 if (atv->is_audio_track()) {
680 (*i)[_columns.visible] = yn;
685 if (!atv->is_audio_track()) {
686 (*i)[_columns.visible] = yn;
697 EditorRoutes::hide_all_routes ()
699 set_all_tracks_visibility (false);
703 EditorRoutes::show_all_routes ()
705 set_all_tracks_visibility (true);
709 EditorRoutes::show_all_audiobus ()
711 set_all_audio_visibility (2, true);
714 EditorRoutes::hide_all_audiobus ()
716 set_all_audio_visibility (2, false);
720 EditorRoutes::show_all_audiotracks()
722 set_all_audio_visibility (1, true);
725 EditorRoutes::hide_all_audiotracks ()
727 set_all_audio_visibility (1, false);
731 EditorRoutes::button_press (GdkEventButton* ev)
733 if (Keyboard::is_context_menu_event (ev)) {
738 //Scroll editor canvas to selected track
739 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
741 TreeModel::Path path;
746 _display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y);
748 // Get the model row.
749 Gtk::TreeModel::Row row = *_model->get_iter (path);
751 TimeAxisView *tv = row[_columns.tv];
753 int y_pos = tv->y_position();
755 //Clamp the y pos so that we do not extend beyond the canvas full height.
756 if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){
757 y_pos = _editor->full_canvas_height - _editor->_canvas_height;
760 //Only scroll to if the track is visible
762 _editor->reset_y_origin (y_pos);
770 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
775 struct EditorOrderRouteSorter {
776 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
777 /* use of ">" forces the correct sort order */
778 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
783 EditorRoutes::initial_display ()
785 suspend_redisplay ();
793 boost::shared_ptr<RouteList> routes = _session->get_routes();
794 RouteList r (*routes);
795 EditorOrderRouteSorter sorter;
798 _editor->handle_new_route (r);
800 /* don't show master bus in a new session */
802 if (ARDOUR_UI::instance()->session_is_new ()) {
804 TreeModel::Children rows = _model->children();
805 TreeModel::Children::iterator i;
807 _no_redisplay = true;
809 for (i = rows.begin(); i != rows.end(); ++i) {
811 TimeAxisView *tv = (*i)[_columns.tv];
812 RouteTimeAxisView *rtv;
814 if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
815 if (rtv->route()->is_master()) {
816 _display.get_selection()->unselect (i);
821 _no_redisplay = false;
829 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
831 _redisplay_does_not_sync_order_keys = true;
832 _session->set_remote_control_ids();
834 _redisplay_does_not_sync_order_keys = false;
838 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
840 const SelectionData& data,
841 guint info, guint time)
843 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
844 _display.on_drag_data_received (context, x, y, data, info, time);
848 context->drag_finish (true, false, time);
852 EditorRoutes::move_selected_tracks (bool up)
854 if (_editor->selection->tracks.empty()) {
858 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
859 std::list<ViewRoute> view_routes;
860 std::vector<int> neworder;
861 TreeModel::Children rows = _model->children();
862 TreeModel::Children::iterator ri;
864 for (ri = rows.begin(); ri != rows.end(); ++ri) {
865 TimeAxisView* tv = (*ri)[_columns.tv];
866 boost::shared_ptr<Route> route = (*ri)[_columns.route];
868 view_routes.push_back (ViewRoute (tv, route));
871 list<ViewRoute>::iterator trailing;
872 list<ViewRoute>::iterator leading;
876 trailing = view_routes.begin();
877 leading = view_routes.begin();
881 while (leading != view_routes.end()) {
882 if (_editor->selection->selected (leading->first)) {
883 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
884 leading = view_routes.erase (leading);
893 /* if we could use reverse_iterator in list::insert, this code
894 would be a beautiful reflection of the code above. but we can't
895 and so it looks like a bit of a mess.
898 trailing = view_routes.end();
899 leading = view_routes.end();
901 --leading; if (leading == view_routes.begin()) { return; }
907 if (_editor->selection->selected (leading->first)) {
908 list<ViewRoute>::iterator tmp;
910 /* need to insert *after* trailing, not *before* it,
911 which is what insert (iter, val) normally does.
917 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
919 /* can't use iter = cont.erase (iter); form here, because
920 we need iter to move backwards.
928 if (leading == view_routes.begin()) {
929 /* the one we've just inserted somewhere else
930 was the first in the list. erase this copy,
931 and then break, because we're done.
936 view_routes.erase (leading);
945 if (leading == view_routes.begin()) {
954 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
955 neworder.push_back (leading->second->order_key (N_ ("editor")));
958 _model->reorder (neworder);
960 _session->sync_order_keys (N_ ("editor"));
964 EditorRoutes::update_rec_display ()
966 TreeModel::Children rows = _model->children();
967 TreeModel::Children::iterator i;
969 for (i = rows.begin(); i != rows.end(); ++i) {
970 boost::shared_ptr<Route> route = (*i)[_columns.route];
972 if (boost::dynamic_pointer_cast<Track>(route)) {
973 (*i)[_columns.rec_enabled] = route->record_enabled ();
974 (*i)[_columns.name_editable] = !route->record_enabled ();
980 EditorRoutes::update_mute_display ()
982 TreeModel::Children rows = _model->children();
983 TreeModel::Children::iterator i;
985 for (i = rows.begin(); i != rows.end(); ++i) {
986 boost::shared_ptr<Route> route = (*i)[_columns.route];
987 (*i)[_columns.mute_state] = RouteUI::mute_visual_state (_session, route) > 0 ? 1 : 0;
992 EditorRoutes::update_solo_display ()
994 TreeModel::Children rows = _model->children();
995 TreeModel::Children::iterator i;
997 for (i = rows.begin(); i != rows.end(); ++i) {
998 boost::shared_ptr<Route> route = (*i)[_columns.route];
999 (*i)[_columns.solo_state] = RouteUI::solo_visual_state (route) > 0 ? 1 : 0;
1004 EditorRoutes::update_solo_isolate_display ()
1006 TreeModel::Children rows = _model->children();
1007 TreeModel::Children::iterator i;
1009 for (i = rows.begin(); i != rows.end(); ++i) {
1010 boost::shared_ptr<Route> route = (*i)[_columns.route];
1011 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_visual_state (route) > 0 ? 1 : 0;
1016 EditorRoutes::views () const
1018 list<TimeAxisView*> v;
1019 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1020 v.push_back ((*i)[_columns.tv]);
1027 EditorRoutes::clear ()
1029 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1031 _display.set_model (_model);
1035 EditorRoutes::name_edit (Glib::ustring const & path, Glib::ustring const & new_text)
1037 TreeIter iter = _model->get_iter (path);
1042 boost::shared_ptr<Route> route = (*iter)[_columns.route];
1044 if (route && route->name() != new_text) {
1045 route->set_name (new_text);
1050 EditorRoutes::solo_changed_so_update_mute ()
1052 ENSURE_GUI_THREAD (*this, &EditorRoutes::solo_changed_so_update_mute)
1053 update_mute_display ();
1057 EditorRoutes::show_tracks_with_regions_at_playhead ()
1059 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1061 set<TimeAxisView*> show;
1062 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1063 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1069 suspend_redisplay ();
1071 TreeModel::Children rows = _model->children ();
1072 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1073 TimeAxisView* tv = (*i)[_columns.tv];
1074 (*i)[_columns.visible] = (show.find (tv) != show.end());
1077 resume_redisplay ();