2 Copyright (C) 2000-2006 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.
23 #include "pbd/stacktrace.h"
25 #include "ardour/session.h"
26 #include "ardour/diskstream.h"
27 #include "ardour/playlist.h"
28 #include "ardour/route_group.h"
29 #include "ardour/profile.h"
33 #include "audio_time_axis.h"
34 #include "audio_region_view.h"
35 #include "audio_streamview.h"
36 #include "automation_line.h"
37 #include "control_point.h"
38 #include "editor_regions.h"
44 using namespace ARDOUR;
48 using namespace Gtkmm2ext;
49 using namespace Editing;
51 struct TrackViewByPositionSorter
53 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
54 return a->y_position() < b->y_position();
59 Editor::extend_selection_to_track (TimeAxisView& view)
61 if (selection->selected (&view)) {
62 /* already selected, do nothing */
66 if (selection->tracks.empty()) {
68 if (!selection->selected (&view)) {
69 selection->set (&view);
76 /* something is already selected, so figure out which range of things to add */
78 TrackViewList to_be_added;
79 TrackViewList sorted = track_views;
80 TrackViewByPositionSorter cmp;
81 bool passed_clicked = false;
86 if (!selection->selected (&view)) {
87 to_be_added.push_back (&view);
90 /* figure out if we should go forward or backwards */
92 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
95 passed_clicked = true;
98 if (selection->selected (*i)) {
108 passed_clicked = false;
112 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
115 passed_clicked = true;
119 if (passed_clicked) {
120 if ((*i)->hidden()) {
123 if (selection->selected (*i)) {
125 } else if (!(*i)->hidden()) {
126 to_be_added.push_back (*i);
133 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
136 passed_clicked = true;
140 if (passed_clicked) {
142 if ((*r)->hidden()) {
146 if (selection->selected (*r)) {
148 } else if (!(*r)->hidden()) {
149 to_be_added.push_back (*r);
155 if (!to_be_added.empty()) {
156 selection->add (to_be_added);
164 Editor::select_all_tracks ()
166 TrackViewList visible_views;
167 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
168 if ((*i)->marked_for_display()) {
169 visible_views.push_back (*i);
172 selection->set (visible_views);
176 Editor::set_selected_track_as_side_effect (bool force)
178 if (!clicked_routeview) {
182 if (!selection->tracks.empty()) {
183 if (!selection->selected (clicked_routeview)) {
184 selection->add (clicked_routeview);
188 selection->set (clicked_routeview);
193 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
196 case Selection::Toggle:
197 if (selection->selected (&view)) {
199 selection->remove (&view);
202 selection->add (&view);
207 if (!selection->selected (&view)) {
208 selection->add (&view);
213 selection->set (&view);
216 case Selection::Extend:
217 extend_selection_to_track (view);
223 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
225 if (!clicked_routeview) {
233 set_selected_track (*clicked_routeview, op, no_remove);
237 Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
239 if (!clicked_control_point) {
243 /* select this point and any others that it represents */
248 x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
249 x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
250 y1 = clicked_control_point->get_x() - 10;
251 y2 = clicked_control_point->get_y() + 10;
253 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
257 Editor::get_onscreen_tracks (TrackViewList& tvl)
259 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
260 if ((*i)->y_position() < _canvas_height) {
266 /** Given a track, find any other tracks that are in the same active route group with a given property.
267 * @param basis Base track.
268 * @param equivs Filled with the base track and the found tracks.
269 * @param prop Property to look for in route groups.
273 Editor::get_equivalent_tracks (RouteTimeAxisView* basis, set<RouteTimeAxisView*> & equivs, RouteGroup::Property prop) const
275 equivs.insert (basis);
277 RouteGroup* group = basis->route()->route_group();
278 if (group && group->active_property (prop)) {
280 /* the basis is a member of an active route group, with the appropriate
281 properties; find other members */
283 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
284 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
285 if (v && v->route()->route_group() == group) {
292 /** Find tracks that are selected, and also those that are in the same `selection'-enabled route
293 * group as one that is selected.
294 * @param relevant_tracks set to add tracks to.
298 Editor::get_relevant_tracks (set<RouteTimeAxisView*>& relevant_tracks) const
300 for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
301 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*ti);
303 get_equivalent_tracks (rtv, relevant_tracks, RouteGroup::Select);
308 /** Call a slot for a given `basis' track and also for any track that is in the same
309 * active route group with a particular set of properties.
311 * @param sl Slot to call.
312 * @param basis Basis track.
313 * @param prop Properties that active edit groups must share to be included in the map.
317 Editor::mapover_tracks (slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, RouteGroup::Property prop) const
319 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
320 if (route_basis == 0) {
324 set<RouteTimeAxisView*> tracks;
325 get_equivalent_tracks (route_basis, tracks, prop);
328 uint32_t const sz = tracks.size ();
329 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
335 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
337 boost::shared_ptr<Playlist> pl;
338 vector<boost::shared_ptr<Region> > results;
340 boost::shared_ptr<Diskstream> ds;
342 if ((ds = tv.get_diskstream()) == 0) {
347 if (&tv == &basis->get_time_axis_view()) {
348 /* looking in same track as the original */
352 if ((pl = ds->playlist()) != 0) {
353 pl->get_equivalent_regions (basis->region(), results);
356 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
357 if ((marv = tv.view()->find_view (*ir)) != 0) {
358 all_equivs->push_back (marv);
364 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, RouteGroup::Property prop) const
366 mapover_tracks (bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview(), prop);
368 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
370 equivalent_regions.push_back (basis);
374 Editor::get_equivalent_regions (RegionSelection & basis, RouteGroup::Property prop) const
376 RegionSelection equivalent;
378 for (RegionSelection::const_iterator i = basis.begin(); i != basis.end(); ++i) {
380 vector<RegionView*> eq;
383 bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
384 &(*i)->get_trackview(), prop
387 for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {
399 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
401 int region_count = 0;
403 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
405 RouteTimeAxisView* tatv;
407 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
409 boost::shared_ptr<Playlist> pl;
410 vector<boost::shared_ptr<Region> > results;
412 boost::shared_ptr<Diskstream> ds;
414 if ((ds = tatv->get_diskstream()) == 0) {
419 if ((pl = (ds->playlist())) != 0) {
420 pl->get_region_list_equivalent_regions (region, results);
423 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
424 if ((marv = tatv->view()->find_view (*ir)) != 0) {
437 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
439 vector<RegionView*> all_equivalent_regions;
442 if (!clicked_regionview || !clicked_routeview) {
447 button_release_can_deselect = false;
450 if (op == Selection::Toggle || op == Selection::Set) {
454 case Selection::Toggle:
456 if (selection->selected (clicked_regionview)) {
459 /* whatever was clicked was selected already; do nothing here but allow
460 the button release to deselect it
463 button_release_can_deselect = true;
467 if (button_release_can_deselect) {
469 /* just remove this one region, but only on a permitted button release */
471 selection->remove (clicked_regionview);
474 /* no more deselect action on button release till a new press
475 finds an already selected object.
478 button_release_can_deselect = false;
486 if (selection->selected (clicked_routeview)) {
487 get_equivalent_regions (clicked_regionview, all_equivalent_regions, RouteGroup::Select);
489 all_equivalent_regions.push_back (clicked_regionview);
492 /* add all the equivalent regions, but only on button press */
496 if (!all_equivalent_regions.empty()) {
500 selection->add (all_equivalent_regions);
506 if (!selection->selected (clicked_regionview)) {
507 get_equivalent_regions (clicked_regionview, all_equivalent_regions, RouteGroup::Select);
508 selection->set (all_equivalent_regions);
511 /* no commit necessary: clicked on an already selected region */
521 } else if (op == Selection::Extend) {
523 list<Selectable*> results;
524 nframes64_t last_frame;
525 nframes64_t first_frame;
526 bool same_track = false;
528 /* 1. find the last selected regionview in the track that was clicked in */
531 first_frame = max_frames;
533 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
534 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
536 if ((*x)->region()->last_frame() > last_frame) {
537 last_frame = (*x)->region()->last_frame();
540 if ((*x)->region()->first_frame() < first_frame) {
541 first_frame = (*x)->region()->first_frame();
550 /* 2. figure out the boundaries for our search for new objects */
552 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
554 if (last_frame < clicked_regionview->region()->first_frame()) {
555 first_frame = last_frame;
556 last_frame = clicked_regionview->region()->last_frame();
558 last_frame = first_frame;
559 first_frame = clicked_regionview->region()->first_frame();
563 case OverlapExternal:
564 if (last_frame < clicked_regionview->region()->first_frame()) {
565 first_frame = last_frame;
566 last_frame = clicked_regionview->region()->last_frame();
568 last_frame = first_frame;
569 first_frame = clicked_regionview->region()->first_frame();
573 case OverlapInternal:
574 if (last_frame < clicked_regionview->region()->first_frame()) {
575 first_frame = last_frame;
576 last_frame = clicked_regionview->region()->last_frame();
578 last_frame = first_frame;
579 first_frame = clicked_regionview->region()->first_frame();
585 /* nothing to do except add clicked region to selection, since it
586 overlaps with the existing selection in this track.
593 /* click in a track that has no regions selected, so extend vertically
594 to pick out all regions that are defined by the existing selection
599 first_frame = entered_regionview->region()->position();
600 last_frame = entered_regionview->region()->last_frame();
602 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
603 if ((*i)->region()->position() < first_frame) {
604 first_frame = (*i)->region()->position();
606 if ((*i)->region()->last_frame() + 1 > last_frame) {
607 last_frame = (*i)->region()->last_frame();
612 /* 2. find all the tracks we should select in */
614 set<RouteTimeAxisView*> relevant_tracks;
615 set<RouteTimeAxisView*> already_in_selection;
617 get_relevant_tracks (relevant_tracks);
619 if (relevant_tracks.empty()) {
621 /* no relevant tracks -> no tracks selected .. thus .. if
622 the regionview we're in isn't selected (i.e. we're
623 about to extend to it), then find all tracks between
624 the this one and any selected ones.
627 if (!selection->selected (entered_regionview)) {
629 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
633 /* add this track to the ones we will search */
635 relevant_tracks.insert (rtv);
637 /* find the track closest to this one that
638 already a selected region.
641 RouteTimeAxisView* closest = 0;
642 int distance = INT_MAX;
643 int key = rtv->route()->order_key ("editor");
645 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
647 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
649 if (artv && artv != rtv) {
651 pair<set<RouteTimeAxisView*>::iterator,bool> result;
653 result = already_in_selection.insert (artv);
656 /* newly added to already_in_selection */
659 int d = artv->route()->order_key ("editor");
663 if (abs (d) < distance) {
673 /* now add all tracks between that one and this one */
675 int okey = closest->route()->order_key ("editor");
681 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
682 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
683 if (artv && artv != rtv) {
685 int k = artv->route()->order_key ("editor");
687 if (k >= okey && k <= key) {
689 /* in range but don't add it if
690 it already has tracks selected.
691 this avoids odd selection
692 behaviour that feels wrong.
695 if (find (already_in_selection.begin(),
696 already_in_selection.end(),
697 artv) == already_in_selection.end()) {
699 relevant_tracks.insert (artv);
709 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
710 one that was clicked.
713 get_relevant_tracks (relevant_tracks);
715 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
716 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
719 /* 4. convert to a vector of regions */
721 vector<RegionView*> regions;
723 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
726 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
727 regions.push_back (arv);
731 if (!regions.empty()) {
732 selection->add (regions);
743 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
745 vector<RegionView*> all_equivalent_regions;
747 get_regions_corresponding_to (region, all_equivalent_regions);
749 if (all_equivalent_regions.empty()) {
753 begin_reversible_command (_("set selected regions"));
756 case Selection::Toggle:
757 /* XXX this is not correct */
758 selection->toggle (all_equivalent_regions);
761 selection->set (all_equivalent_regions);
763 case Selection::Extend:
764 selection->add (all_equivalent_regions);
767 selection->add (all_equivalent_regions);
771 commit_reversible_command () ;
775 Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* sv, boost::weak_ptr<Region> weak_r)
778 boost::shared_ptr<Region> r (weak_r.lock());
784 if ((rv = sv->find_view (r)) == 0) {
788 /* don't reset the selection if its something other than
789 a single other region.
792 if (selection->regions.size() > 1) {
796 begin_reversible_command (_("set selected regions"));
800 commit_reversible_command () ;
806 Editor::track_selection_changed ()
808 switch (selection->tracks.size()){
812 set_selected_mixer_strip (*(selection->tracks.front()));
816 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
817 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
818 (*i)->set_selected (true);
820 (*i)->set_selected (false);
824 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
828 Editor::time_selection_changed ()
830 if (Profile->get_sae()) {
834 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
835 (*i)->hide_selection ();
838 if (selection->tracks.empty()) {
839 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
840 (*i)->show_selection (selection->time);
843 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
844 (*i)->show_selection (selection->time);
848 if (selection->time.empty()) {
849 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
851 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
857 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
859 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
860 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
862 string accel_path = (*x)->get_accel_path ();
865 /* if there is an accelerator, it should always be sensitive
866 to allow for keyboard ops on entered regions.
869 bool known = ActionManager::lookup_entry (accel_path, key);
871 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
872 (*x)->set_sensitive (true);
874 (*x)->set_sensitive (have_selected_regions);
881 Editor::region_selection_changed ()
883 _regions->block_change_connection (true);
884 editor_regions_selection_changed_connection.block(true);
886 _regions->unselect_all ();
888 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
890 (*i)->set_selected_regionviews (selection->regions);
891 _regions->set_selected (selection->regions);
895 sensitize_the_right_region_actions (!selection->regions.empty());
897 _regions->block_change_connection (false);
898 editor_regions_selection_changed_connection.block(false);
902 Editor::point_selection_changed ()
904 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
905 (*i)->set_selected_points (selection->points);
910 Editor::select_all_in_track (Selection::Operation op)
912 list<Selectable *> touched;
914 if (!clicked_routeview) {
918 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
921 case Selection::Toggle:
922 selection->add (touched);
925 selection->set (touched);
927 case Selection::Extend:
928 /* meaningless, because we're selecting everything */
931 selection->add (touched);
937 Editor::select_all (Selection::Operation op)
939 list<Selectable *> touched;
941 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
942 if ((*iter)->hidden()) {
945 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
947 begin_reversible_command (_("select all"));
950 selection->add (touched);
952 case Selection::Toggle:
953 selection->add (touched);
956 selection->set (touched);
958 case Selection::Extend:
959 /* meaningless, because we're selecting everything */
962 commit_reversible_command ();
965 Editor::invert_selection_in_track ()
967 list<Selectable *> touched;
969 if (!clicked_routeview) {
973 clicked_routeview->get_inverted_selectables (*selection, touched);
974 selection->set (touched);
978 Editor::invert_selection ()
980 list<Selectable *> touched;
982 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
983 if ((*iter)->hidden()) {
986 (*iter)->get_inverted_selectables (*selection, touched);
989 selection->set (touched);
993 Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
995 list<Selectable*> touched;
996 list<Selectable*>::size_type n = 0;
997 TrackViewList touched_tracks;
999 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
1000 if ((*iter)->hidden()) {
1006 (*iter)->get_selectables (start, end, top, bot, touched);
1008 if (n != touched.size()) {
1009 touched_tracks.push_back (*iter);
1013 if (touched.empty()) {
1017 if (!touched_tracks.empty()) {
1020 case Selection::Add:
1021 selection->add (touched_tracks);
1023 case Selection::Toggle:
1024 selection->toggle (touched_tracks);
1026 case Selection::Set:
1027 selection->set (touched_tracks);
1029 case Selection::Extend:
1030 /* not defined yet */
1035 begin_reversible_command (_("select all within"));
1037 case Selection::Add:
1038 selection->add (touched);
1040 case Selection::Toggle:
1041 selection->toggle (touched);
1043 case Selection::Set:
1044 selection->set (touched);
1046 case Selection::Extend:
1047 /* not defined yet */
1051 commit_reversible_command ();
1053 return !touched.empty();
1057 Editor::set_selection_from_region ()
1059 if (selection->regions.empty()) {
1063 selection->set (0, selection->regions.start(), selection->regions.end_frame());
1064 if (!Profile->get_sae()) {
1065 set_mouse_mode (Editing::MouseRange, false);
1070 Editor::set_selection_from_punch()
1074 if ((location = session->locations()->auto_punch_location()) == 0) {
1078 set_selection_from_range (*location);
1082 Editor::set_selection_from_loop()
1086 if ((location = session->locations()->auto_loop_location()) == 0) {
1089 set_selection_from_range (*location);
1093 Editor::set_selection_from_range (Location& loc)
1095 begin_reversible_command (_("set selection from range"));
1096 selection->set (0, loc.start(), loc.end());
1097 commit_reversible_command ();
1099 if (!Profile->get_sae()) {
1100 set_mouse_mode (Editing::MouseRange, false);
1105 Editor::select_all_selectables_using_time_selection ()
1107 list<Selectable *> touched;
1109 if (selection->time.empty()) {
1113 nframes64_t start = selection->time[clicked_selection].start;
1114 nframes64_t end = selection->time[clicked_selection].end;
1116 if (end - start < 1) {
1122 if (selection->tracks.empty()) {
1125 ts = &selection->tracks;
1128 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1129 if ((*iter)->hidden()) {
1132 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1135 begin_reversible_command (_("select all from range"));
1136 selection->set (touched);
1137 commit_reversible_command ();
1142 Editor::select_all_selectables_using_punch()
1144 Location* location = session->locations()->auto_punch_location();
1145 list<Selectable *> touched;
1147 if (location == 0 || (location->end() - location->start() <= 1)) {
1154 if (selection->tracks.empty()) {
1157 ts = &selection->tracks;
1160 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1161 if ((*iter)->hidden()) {
1164 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1166 begin_reversible_command (_("select all from punch"));
1167 selection->set (touched);
1168 commit_reversible_command ();
1173 Editor::select_all_selectables_using_loop()
1175 Location* location = session->locations()->auto_loop_location();
1176 list<Selectable *> touched;
1178 if (location == 0 || (location->end() - location->start() <= 1)) {
1185 if (selection->tracks.empty()) {
1188 ts = &selection->tracks;
1191 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1192 if ((*iter)->hidden()) {
1195 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1197 begin_reversible_command (_("select all from loop"));
1198 selection->set (touched);
1199 commit_reversible_command ();
1204 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1208 list<Selectable *> touched;
1211 begin_reversible_command (_("select all after cursor"));
1212 start = cursor->current_frame ;
1213 end = session->current_end_frame();
1215 if (cursor->current_frame > 0) {
1216 begin_reversible_command (_("select all before cursor"));
1218 end = cursor->current_frame - 1;
1227 if (selection->tracks.empty()) {
1230 ts = &selection->tracks;
1233 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1234 if ((*iter)->hidden()) {
1237 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1239 selection->set (touched);
1240 commit_reversible_command ();
1244 Editor::select_all_selectables_using_edit (bool after)
1248 list<Selectable *> touched;
1251 begin_reversible_command (_("select all after edit"));
1252 start = get_preferred_edit_position();
1253 end = session->current_end_frame();
1255 if ((end = get_preferred_edit_position()) > 1) {
1256 begin_reversible_command (_("select all before edit"));
1267 if (selection->tracks.empty()) {
1270 ts = &selection->tracks;
1273 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1274 if ((*iter)->hidden()) {
1277 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1279 selection->set (touched);
1280 commit_reversible_command ();
1284 Editor::select_all_selectables_between (bool /*within*/)
1288 list<Selectable *> touched;
1290 if (!get_edit_op_range (start, end)) {
1296 if (selection->tracks.empty()) {
1299 ts = &selection->tracks;
1302 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1303 if ((*iter)->hidden()) {
1306 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1309 selection->set (touched);
1313 Editor::select_range_between ()
1318 if (!get_edit_op_range (start, end)) {
1322 set_mouse_mode (MouseRange);
1323 selection->set ((TimeAxisView*) 0, start, end);
1327 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1332 /* in range mode, use any existing selection */
1334 if (mouse_mode == MouseRange && !selection->time.empty()) {
1335 /* we know that these are ordered */
1336 start = selection->time.start();
1337 end = selection->time.end_frame();
1341 if (!mouse_frame (m, ignored)) {
1342 /* mouse is not in a canvas, try playhead+selected marker.
1343 this is probably most true when using menus.
1346 if (selection->markers.empty()) {
1350 start = selection->markers.front()->position();
1351 end = session->audible_frame();
1355 switch (_edit_point) {
1356 case EditAtPlayhead:
1357 if (selection->markers.empty()) {
1358 /* use mouse + playhead */
1360 end = session->audible_frame();
1362 /* use playhead + selected marker */
1363 start = session->audible_frame();
1364 end = selection->markers.front()->position();
1369 /* use mouse + selected marker */
1370 if (selection->markers.empty()) {
1372 end = session->audible_frame();
1374 start = selection->markers.front()->position();
1379 case EditAtSelectedMarker:
1380 /* use mouse + selected marker */
1381 if (selection->markers.empty()) {
1383 MessageDialog win (_("No edit range defined"),
1388 win.set_secondary_text (
1389 _("the edit point is Selected Marker\nbut there is no selected marker."));
1392 win.set_default_response (RESPONSE_CLOSE);
1393 win.set_position (Gtk::WIN_POS_MOUSE);
1398 return false; // NO RANGE
1400 start = selection->markers.front()->position();
1414 /* turn range into one delimited by start...end,
1424 Editor::deselect_all ()
1426 selection->clear ();