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/diskstream.h"
26 #include "ardour/playlist.h"
27 #include "ardour/route_group.h"
28 #include "ardour/profile.h"
32 #include "audio_time_axis.h"
33 #include "audio_region_view.h"
34 #include "audio_streamview.h"
35 #include "automation_line.h"
36 #include "control_point.h"
37 #include "editor_regions.h"
43 using namespace ARDOUR;
47 using namespace Gtkmm2ext;
48 using namespace Editing;
50 struct TrackViewByPositionSorter
52 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
53 return a->y_position() < b->y_position();
58 Editor::extend_selection_to_track (TimeAxisView& view)
60 if (selection->selected (&view)) {
61 /* already selected, do nothing */
65 if (selection->tracks.empty()) {
67 if (!selection->selected (&view)) {
68 selection->set (&view);
75 /* something is already selected, so figure out which range of things to add */
77 TrackViewList to_be_added;
78 TrackViewList sorted = track_views;
79 TrackViewByPositionSorter cmp;
80 bool passed_clicked = false;
85 if (!selection->selected (&view)) {
86 to_be_added.push_back (&view);
89 /* figure out if we should go forward or backwards */
91 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
94 passed_clicked = true;
97 if (selection->selected (*i)) {
107 passed_clicked = false;
111 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
114 passed_clicked = true;
118 if (passed_clicked) {
119 if ((*i)->hidden()) {
122 if (selection->selected (*i)) {
124 } else if (!(*i)->hidden()) {
125 to_be_added.push_back (*i);
132 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
135 passed_clicked = true;
139 if (passed_clicked) {
141 if ((*r)->hidden()) {
145 if (selection->selected (*r)) {
147 } else if (!(*r)->hidden()) {
148 to_be_added.push_back (*r);
154 if (!to_be_added.empty()) {
155 selection->add (to_be_added);
163 Editor::select_all_tracks ()
165 TrackViewList visible_views;
166 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
167 if ((*i)->marked_for_display()) {
168 visible_views.push_back (*i);
171 selection->set (visible_views);
175 Editor::set_selected_track_as_side_effect (bool force)
177 if (!clicked_routeview) {
181 if (!selection->tracks.empty()) {
182 if (!selection->selected (clicked_routeview)) {
183 selection->add (clicked_routeview);
187 selection->set (clicked_routeview);
192 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
195 case Selection::Toggle:
196 if (selection->selected (&view)) {
198 selection->remove (&view);
201 selection->add (&view);
206 if (!selection->selected (&view)) {
207 selection->add (&view);
212 selection->set (&view);
215 case Selection::Extend:
216 extend_selection_to_track (view);
222 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
224 if (!clicked_routeview) {
232 set_selected_track (*clicked_routeview, op, no_remove);
236 Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
238 if (!clicked_control_point) {
242 /* select this point and any others that it represents */
247 x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
248 x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
249 y1 = clicked_control_point->get_x() - 10;
250 y2 = clicked_control_point->get_y() + 10;
252 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
256 Editor::get_onscreen_tracks (TrackViewList& tvl)
258 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
259 if ((*i)->y_position() < _canvas_height) {
265 /** Given a track, find any other tracks that are in the same active route group with a given property.
266 * @param basis Base track.
267 * @param equivs Filled with the base track and the found tracks.
268 * @param prop Property to look for in route groups.
272 Editor::get_equivalent_tracks (RouteTimeAxisView* basis, set<RouteTimeAxisView*> & equivs, RouteGroup::Property prop) const
274 equivs.insert (basis);
276 RouteGroup* group = basis->route()->route_group();
277 if (group && group->active_property (prop)) {
279 /* the basis is a member of an active route group, with the appropriate
280 properties; find other members */
282 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
283 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
284 if (v && v->route()->route_group() == group) {
291 /** Find tracks that are selected, and also those that are in the same `selection'-enabled route
292 * group as one that is selected.
293 * @param relevant_tracks set to add tracks to.
297 Editor::get_relevant_tracks (set<RouteTimeAxisView*>& relevant_tracks) const
299 for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
300 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*ti);
302 get_equivalent_tracks (rtv, relevant_tracks, RouteGroup::Select);
307 /** Call a slot for a given `basis' track and also for any track that is in the same
308 * active route group with a particular set of properties.
310 * @param sl Slot to call.
311 * @param basis Basis track.
312 * @param prop Properties that active edit groups must share to be included in the map.
316 Editor::mapover_tracks (slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, RouteGroup::Property prop) const
318 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
319 if (route_basis == 0) {
323 set<RouteTimeAxisView*> tracks;
324 get_equivalent_tracks (route_basis, tracks, prop);
327 uint32_t const sz = tracks.size ();
328 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
334 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
336 boost::shared_ptr<Playlist> pl;
337 vector<boost::shared_ptr<Region> > results;
339 boost::shared_ptr<Diskstream> ds;
341 if ((ds = tv.get_diskstream()) == 0) {
346 if (&tv == &basis->get_time_axis_view()) {
347 /* looking in same track as the original */
351 if ((pl = ds->playlist()) != 0) {
352 pl->get_equivalent_regions (basis->region(), results);
355 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
356 if ((marv = tv.view()->find_view (*ir)) != 0) {
357 all_equivs->push_back (marv);
363 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, RouteGroup::Property prop) const
365 mapover_tracks (bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview(), prop);
367 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
369 equivalent_regions.push_back (basis);
373 Editor::get_equivalent_regions (RegionSelection & basis, RouteGroup::Property prop) const
375 RegionSelection equivalent;
377 for (RegionSelection::const_iterator i = basis.begin(); i != basis.end(); ++i) {
379 vector<RegionView*> eq;
382 bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
383 &(*i)->get_trackview(), prop
386 for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {
398 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
400 int region_count = 0;
402 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
404 RouteTimeAxisView* tatv;
406 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
408 boost::shared_ptr<Playlist> pl;
409 vector<boost::shared_ptr<Region> > results;
411 boost::shared_ptr<Diskstream> ds;
413 if ((ds = tatv->get_diskstream()) == 0) {
418 if ((pl = (ds->playlist())) != 0) {
419 pl->get_region_list_equivalent_regions (region, results);
422 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
423 if ((marv = tatv->view()->find_view (*ir)) != 0) {
436 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
438 vector<RegionView*> all_equivalent_regions;
441 if (!clicked_regionview || !clicked_routeview) {
446 button_release_can_deselect = false;
449 if (op == Selection::Toggle || op == Selection::Set) {
453 case Selection::Toggle:
455 if (selection->selected (clicked_regionview)) {
458 /* whatever was clicked was selected already; do nothing here but allow
459 the button release to deselect it
462 button_release_can_deselect = true;
466 if (button_release_can_deselect) {
468 /* just remove this one region, but only on a permitted button release */
470 selection->remove (clicked_regionview);
473 /* no more deselect action on button release till a new press
474 finds an already selected object.
477 button_release_can_deselect = false;
485 if (selection->selected (clicked_routeview)) {
486 get_equivalent_regions (clicked_regionview, all_equivalent_regions, RouteGroup::Select);
488 all_equivalent_regions.push_back (clicked_regionview);
491 /* add all the equivalent regions, but only on button press */
495 if (!all_equivalent_regions.empty()) {
499 selection->add (all_equivalent_regions);
505 if (!selection->selected (clicked_regionview)) {
506 get_equivalent_regions (clicked_regionview, all_equivalent_regions, RouteGroup::Select);
507 selection->set (all_equivalent_regions);
510 /* no commit necessary: clicked on an already selected region */
520 } else if (op == Selection::Extend) {
522 list<Selectable*> results;
523 nframes64_t last_frame;
524 nframes64_t first_frame;
525 bool same_track = false;
527 /* 1. find the last selected regionview in the track that was clicked in */
530 first_frame = max_frames;
532 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
533 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
535 if ((*x)->region()->last_frame() > last_frame) {
536 last_frame = (*x)->region()->last_frame();
539 if ((*x)->region()->first_frame() < first_frame) {
540 first_frame = (*x)->region()->first_frame();
549 /* 2. figure out the boundaries for our search for new objects */
551 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
553 if (last_frame < clicked_regionview->region()->first_frame()) {
554 first_frame = last_frame;
555 last_frame = clicked_regionview->region()->last_frame();
557 last_frame = first_frame;
558 first_frame = clicked_regionview->region()->first_frame();
562 case OverlapExternal:
563 if (last_frame < clicked_regionview->region()->first_frame()) {
564 first_frame = last_frame;
565 last_frame = clicked_regionview->region()->last_frame();
567 last_frame = first_frame;
568 first_frame = clicked_regionview->region()->first_frame();
572 case OverlapInternal:
573 if (last_frame < clicked_regionview->region()->first_frame()) {
574 first_frame = last_frame;
575 last_frame = clicked_regionview->region()->last_frame();
577 last_frame = first_frame;
578 first_frame = clicked_regionview->region()->first_frame();
584 /* nothing to do except add clicked region to selection, since it
585 overlaps with the existing selection in this track.
592 /* click in a track that has no regions selected, so extend vertically
593 to pick out all regions that are defined by the existing selection
598 first_frame = entered_regionview->region()->position();
599 last_frame = entered_regionview->region()->last_frame();
601 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
602 if ((*i)->region()->position() < first_frame) {
603 first_frame = (*i)->region()->position();
605 if ((*i)->region()->last_frame() + 1 > last_frame) {
606 last_frame = (*i)->region()->last_frame();
611 /* 2. find all the tracks we should select in */
613 set<RouteTimeAxisView*> relevant_tracks;
614 set<RouteTimeAxisView*> already_in_selection;
616 get_relevant_tracks (relevant_tracks);
618 if (relevant_tracks.empty()) {
620 /* no relevant tracks -> no tracks selected .. thus .. if
621 the regionview we're in isn't selected (i.e. we're
622 about to extend to it), then find all tracks between
623 the this one and any selected ones.
626 if (!selection->selected (entered_regionview)) {
628 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
632 /* add this track to the ones we will search */
634 relevant_tracks.insert (rtv);
636 /* find the track closest to this one that
637 already a selected region.
640 RouteTimeAxisView* closest = 0;
641 int distance = INT_MAX;
642 int key = rtv->route()->order_key ("editor");
644 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
646 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
648 if (artv && artv != rtv) {
650 pair<set<RouteTimeAxisView*>::iterator,bool> result;
652 result = already_in_selection.insert (artv);
655 /* newly added to already_in_selection */
658 int d = artv->route()->order_key ("editor");
662 if (abs (d) < distance) {
672 /* now add all tracks between that one and this one */
674 int okey = closest->route()->order_key ("editor");
680 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
681 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
682 if (artv && artv != rtv) {
684 int k = artv->route()->order_key ("editor");
686 if (k >= okey && k <= key) {
688 /* in range but don't add it if
689 it already has tracks selected.
690 this avoids odd selection
691 behaviour that feels wrong.
694 if (find (already_in_selection.begin(),
695 already_in_selection.end(),
696 artv) == already_in_selection.end()) {
698 relevant_tracks.insert (artv);
708 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
709 one that was clicked.
712 get_relevant_tracks (relevant_tracks);
714 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
715 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
718 /* 4. convert to a vector of regions */
720 vector<RegionView*> regions;
722 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
725 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
726 regions.push_back (arv);
730 if (!regions.empty()) {
731 selection->add (regions);
742 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
744 vector<RegionView*> all_equivalent_regions;
746 get_regions_corresponding_to (region, all_equivalent_regions);
748 if (all_equivalent_regions.empty()) {
752 begin_reversible_command (_("set selected regions"));
755 case Selection::Toggle:
756 /* XXX this is not correct */
757 selection->toggle (all_equivalent_regions);
760 selection->set (all_equivalent_regions);
762 case Selection::Extend:
763 selection->add (all_equivalent_regions);
766 selection->add (all_equivalent_regions);
770 commit_reversible_command () ;
774 Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* sv, boost::weak_ptr<Region> weak_r)
777 boost::shared_ptr<Region> r (weak_r.lock());
783 if ((rv = sv->find_view (r)) == 0) {
787 /* don't reset the selection if its something other than
788 a single other region.
791 if (selection->regions.size() > 1) {
795 begin_reversible_command (_("set selected regions"));
799 commit_reversible_command () ;
805 Editor::track_selection_changed ()
807 switch (selection->tracks.size()){
811 set_selected_mixer_strip (*(selection->tracks.front()));
815 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
816 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
817 (*i)->set_selected (true);
819 (*i)->set_selected (false);
823 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
827 Editor::time_selection_changed ()
829 if (Profile->get_sae()) {
833 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
834 (*i)->hide_selection ();
837 if (selection->tracks.empty()) {
838 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
839 (*i)->show_selection (selection->time);
842 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
843 (*i)->show_selection (selection->time);
847 if (selection->time.empty()) {
848 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
850 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
856 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
858 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
859 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
861 string accel_path = (*x)->get_accel_path ();
864 /* if there is an accelerator, it should always be sensitive
865 to allow for keyboard ops on entered regions.
868 bool known = ActionManager::lookup_entry (accel_path, key);
870 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
871 (*x)->set_sensitive (true);
873 (*x)->set_sensitive (have_selected_regions);
880 Editor::region_selection_changed ()
882 _regions->block_change_connection (true);
883 editor_regions_selection_changed_connection.block(true);
885 _regions->unselect_all ();
887 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
889 (*i)->set_selected_regionviews (selection->regions);
890 _regions->set_selected (selection->regions);
894 sensitize_the_right_region_actions (!selection->regions.empty());
896 zoomed_to_region = false;
898 _regions->block_change_connection (false);
899 editor_regions_selection_changed_connection.block(false);
903 Editor::point_selection_changed ()
905 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
906 (*i)->set_selected_points (selection->points);
911 Editor::select_all_in_track (Selection::Operation op)
913 list<Selectable *> touched;
915 if (!clicked_routeview) {
919 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
922 case Selection::Toggle:
923 selection->add (touched);
926 selection->set (touched);
928 case Selection::Extend:
929 /* meaningless, because we're selecting everything */
932 selection->add (touched);
938 Editor::select_all (Selection::Operation op)
940 list<Selectable *> touched;
942 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
943 if ((*iter)->hidden()) {
946 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
948 begin_reversible_command (_("select all"));
951 selection->add (touched);
953 case Selection::Toggle:
954 selection->add (touched);
957 selection->set (touched);
959 case Selection::Extend:
960 /* meaningless, because we're selecting everything */
963 commit_reversible_command ();
966 Editor::invert_selection_in_track ()
968 list<Selectable *> touched;
970 if (!clicked_routeview) {
974 clicked_routeview->get_inverted_selectables (*selection, touched);
975 selection->set (touched);
979 Editor::invert_selection ()
981 list<Selectable *> touched;
983 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
984 if ((*iter)->hidden()) {
987 (*iter)->get_inverted_selectables (*selection, touched);
990 selection->set (touched);
994 Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
996 list<Selectable*> touched;
997 list<Selectable*>::size_type n = 0;
998 TrackViewList touched_tracks;
1000 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
1001 if ((*iter)->hidden()) {
1007 (*iter)->get_selectables (start, end, top, bot, touched);
1009 if (n != touched.size()) {
1010 touched_tracks.push_back (*iter);
1014 if (touched.empty()) {
1018 if (!touched_tracks.empty()) {
1021 case Selection::Add:
1022 selection->add (touched_tracks);
1024 case Selection::Toggle:
1025 selection->toggle (touched_tracks);
1027 case Selection::Set:
1028 selection->set (touched_tracks);
1030 case Selection::Extend:
1031 /* not defined yet */
1036 begin_reversible_command (_("select all within"));
1038 case Selection::Add:
1039 selection->add (touched);
1041 case Selection::Toggle:
1042 selection->toggle (touched);
1044 case Selection::Set:
1045 selection->set (touched);
1047 case Selection::Extend:
1048 /* not defined yet */
1052 commit_reversible_command ();
1054 return !touched.empty();
1058 Editor::set_selection_from_region ()
1060 if (selection->regions.empty()) {
1064 selection->set (0, selection->regions.start(), selection->regions.end_frame());
1065 if (!Profile->get_sae()) {
1066 set_mouse_mode (Editing::MouseRange, false);
1071 Editor::set_selection_from_punch()
1075 if ((location = session->locations()->auto_punch_location()) == 0) {
1079 set_selection_from_range (*location);
1083 Editor::set_selection_from_loop()
1087 if ((location = session->locations()->auto_loop_location()) == 0) {
1090 set_selection_from_range (*location);
1094 Editor::set_selection_from_range (Location& loc)
1096 begin_reversible_command (_("set selection from range"));
1097 selection->set (0, loc.start(), loc.end());
1098 commit_reversible_command ();
1100 if (!Profile->get_sae()) {
1101 set_mouse_mode (Editing::MouseRange, false);
1106 Editor::select_all_selectables_using_time_selection ()
1108 list<Selectable *> touched;
1110 if (selection->time.empty()) {
1114 nframes64_t start = selection->time[clicked_selection].start;
1115 nframes64_t end = selection->time[clicked_selection].end;
1117 if (end - start < 1) {
1123 if (selection->tracks.empty()) {
1126 ts = &selection->tracks;
1129 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1130 if ((*iter)->hidden()) {
1133 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1136 begin_reversible_command (_("select all from range"));
1137 selection->set (touched);
1138 commit_reversible_command ();
1143 Editor::select_all_selectables_using_punch()
1145 Location* location = session->locations()->auto_punch_location();
1146 list<Selectable *> touched;
1148 if (location == 0 || (location->end() - location->start() <= 1)) {
1155 if (selection->tracks.empty()) {
1158 ts = &selection->tracks;
1161 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1162 if ((*iter)->hidden()) {
1165 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1167 begin_reversible_command (_("select all from punch"));
1168 selection->set (touched);
1169 commit_reversible_command ();
1174 Editor::select_all_selectables_using_loop()
1176 Location* location = session->locations()->auto_loop_location();
1177 list<Selectable *> touched;
1179 if (location == 0 || (location->end() - location->start() <= 1)) {
1186 if (selection->tracks.empty()) {
1189 ts = &selection->tracks;
1192 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1193 if ((*iter)->hidden()) {
1196 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1198 begin_reversible_command (_("select all from loop"));
1199 selection->set (touched);
1200 commit_reversible_command ();
1205 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1209 list<Selectable *> touched;
1212 begin_reversible_command (_("select all after cursor"));
1213 start = cursor->current_frame ;
1214 end = session->current_end_frame();
1216 if (cursor->current_frame > 0) {
1217 begin_reversible_command (_("select all before cursor"));
1219 end = cursor->current_frame - 1;
1228 if (selection->tracks.empty()) {
1231 ts = &selection->tracks;
1234 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1235 if ((*iter)->hidden()) {
1238 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1240 selection->set (touched);
1241 commit_reversible_command ();
1245 Editor::select_all_selectables_using_edit (bool after)
1249 list<Selectable *> touched;
1252 begin_reversible_command (_("select all after edit"));
1253 start = get_preferred_edit_position();
1254 end = session->current_end_frame();
1256 if ((end = get_preferred_edit_position()) > 1) {
1257 begin_reversible_command (_("select all before edit"));
1268 if (selection->tracks.empty()) {
1271 ts = &selection->tracks;
1274 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1275 if ((*iter)->hidden()) {
1278 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1280 selection->set (touched);
1281 commit_reversible_command ();
1285 Editor::select_all_selectables_between (bool /*within*/)
1289 list<Selectable *> touched;
1291 if (!get_edit_op_range (start, end)) {
1297 if (selection->tracks.empty()) {
1300 ts = &selection->tracks;
1303 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1304 if ((*iter)->hidden()) {
1307 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1310 selection->set (touched);
1314 Editor::select_range_between ()
1319 if (!get_edit_op_range (start, end)) {
1323 set_mouse_mode (MouseRange);
1324 selection->set ((TimeAxisView*) 0, start, end);
1328 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1333 /* in range mode, use any existing selection */
1335 if (mouse_mode == MouseRange && !selection->time.empty()) {
1336 /* we know that these are ordered */
1337 start = selection->time.start();
1338 end = selection->time.end_frame();
1342 if (!mouse_frame (m, ignored)) {
1343 /* mouse is not in a canvas, try playhead+selected marker.
1344 this is probably most true when using menus.
1347 if (selection->markers.empty()) {
1351 start = selection->markers.front()->position();
1352 end = session->audible_frame();
1356 switch (_edit_point) {
1357 case EditAtPlayhead:
1358 if (selection->markers.empty()) {
1359 /* use mouse + playhead */
1361 end = session->audible_frame();
1363 /* use playhead + selected marker */
1364 start = session->audible_frame();
1365 end = selection->markers.front()->position();
1370 /* use mouse + selected marker */
1371 if (selection->markers.empty()) {
1373 end = session->audible_frame();
1375 start = selection->markers.front()->position();
1380 case EditAtSelectedMarker:
1381 /* use mouse + selected marker */
1382 if (selection->markers.empty()) {
1384 MessageDialog win (_("No edit range defined"),
1389 win.set_secondary_text (
1390 _("the edit point is Selected Marker\nbut there is no selected marker."));
1393 win.set_default_response (RESPONSE_CLOSE);
1394 win.set_position (Gtk::WIN_POS_MOUSE);
1399 return false; // NO RANGE
1401 start = selection->markers.front()->position();
1415 /* turn range into one delimited by start...end,
1425 Editor::deselect_all ()
1427 selection->clear ();