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"
42 using namespace ARDOUR;
46 using namespace Gtkmm2ext;
47 using namespace Editing;
49 struct TrackViewByPositionSorter
51 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
52 return a->y_position() < b->y_position();
57 Editor::extend_selection_to_track (TimeAxisView& view)
59 if (selection->selected (&view)) {
60 /* already selected, do nothing */
64 if (selection->tracks.empty()) {
66 if (!selection->selected (&view)) {
67 selection->set (&view);
74 /* something is already selected, so figure out which range of things to add */
76 TrackViewList to_be_added;
77 TrackViewList sorted = track_views;
78 TrackViewByPositionSorter cmp;
79 bool passed_clicked = false;
84 if (!selection->selected (&view)) {
85 to_be_added.push_back (&view);
88 /* figure out if we should go forward or backwards */
90 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
93 passed_clicked = true;
96 if (selection->selected (*i)) {
106 passed_clicked = false;
110 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
113 passed_clicked = true;
117 if (passed_clicked) {
118 if ((*i)->hidden()) {
121 if (selection->selected (*i)) {
123 } else if (!(*i)->hidden()) {
124 to_be_added.push_back (*i);
131 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
134 passed_clicked = true;
138 if (passed_clicked) {
140 if ((*r)->hidden()) {
144 if (selection->selected (*r)) {
146 } else if (!(*r)->hidden()) {
147 to_be_added.push_back (*r);
153 if (!to_be_added.empty()) {
154 selection->add (to_be_added);
162 Editor::select_all_tracks ()
164 TrackViewList visible_views;
165 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
166 if ((*i)->marked_for_display()) {
167 visible_views.push_back (*i);
170 selection->set (visible_views);
174 Editor::set_selected_track_as_side_effect (bool force)
176 if (!clicked_routeview) {
180 if (!selection->tracks.empty()) {
181 if (!selection->selected (clicked_routeview)) {
182 selection->add (clicked_routeview);
186 selection->set (clicked_routeview);
191 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
194 case Selection::Toggle:
195 if (selection->selected (&view)) {
197 selection->remove (&view);
200 selection->add (&view);
205 if (!selection->selected (&view)) {
206 selection->add (&view);
211 selection->set (&view);
214 case Selection::Extend:
215 extend_selection_to_track (view);
221 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
223 if (!clicked_routeview) {
231 set_selected_track (*clicked_routeview, op, no_remove);
235 Editor::set_selected_control_point_from_click (Selection::Operation op, bool no_remove)
237 if (!clicked_control_point) {
241 /* select this point and any others that it represents */
246 x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
247 x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
248 y1 = clicked_control_point->get_x() - 10;
249 y2 = clicked_control_point->get_y() + 10;
251 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
255 Editor::get_onscreen_tracks (TrackViewList& tvl)
257 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
258 if ((*i)->y_position() < _canvas_height) {
265 Editor::get_relevant_tracks (set<RouteTimeAxisView*>& relevant_tracks)
267 /* step one: get all selected tracks and all tracks in the relevant edit groups */
269 for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
271 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*ti);
277 RouteGroup* group = rtv->route()->edit_group();
279 if (group && group->is_active()) {
281 /* active group for this track, loop over all tracks and get every member of the group */
283 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
285 RouteTimeAxisView* trtv;
287 if ((trtv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
289 if (trtv->route()->edit_group() == group) {
290 relevant_tracks.insert (trtv);
295 relevant_tracks.insert (rtv);
301 * Call a slot for a given `basis' track and also for any track that is in the same
303 * @param sl Slot to call.
304 * @param basis Basis track.
308 Editor::mapover_tracks (slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis) const
310 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
311 if (route_basis == 0) {
315 /* work out the tracks that we will call the slot for; use
316 a set here as it will disallow possible duplicates of the
318 set<RouteTimeAxisView*> tracks;
320 /* always call for the basis */
321 tracks.insert (route_basis);
323 RouteGroup* group = route_basis->route()->edit_group();
324 if (group && group->is_active()) {
326 /* the basis is a member of an active edit group; find other members */
327 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
328 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
329 if (v && v->route()->edit_group() == group) {
336 uint32_t const sz = tracks.size ();
337 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
343 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t ignored, RegionView* basis, vector<RegionView*>* all_equivs) const
345 boost::shared_ptr<Playlist> pl;
346 vector<boost::shared_ptr<Region> > results;
348 boost::shared_ptr<Diskstream> ds;
350 if ((ds = tv.get_diskstream()) == 0) {
355 if (&tv == &basis->get_time_axis_view()) {
356 /* looking in same track as the original */
360 if ((pl = ds->playlist()) != 0) {
361 pl->get_equivalent_regions (basis->region(), results);
364 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
365 if ((marv = tv.view()->find_view (*ir)) != 0) {
366 all_equivs->push_back (marv);
372 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions) const
374 mapover_tracks (bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview());
376 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
378 equivalent_regions.push_back (basis);
382 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
384 int region_count = 0;
386 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
388 RouteTimeAxisView* tatv;
390 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
392 boost::shared_ptr<Playlist> pl;
393 vector<boost::shared_ptr<Region> > results;
395 boost::shared_ptr<Diskstream> ds;
397 if ((ds = tatv->get_diskstream()) == 0) {
402 if ((pl = (ds->playlist())) != 0) {
403 pl->get_region_list_equivalent_regions (region, results);
406 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
407 if ((marv = tatv->view()->find_view (*ir)) != 0) {
420 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
422 vector<RegionView*> all_equivalent_regions;
425 if (!clicked_regionview || !clicked_routeview) {
430 button_release_can_deselect = false;
433 if (op == Selection::Toggle || op == Selection::Set) {
437 case Selection::Toggle:
439 if (selection->selected (clicked_regionview)) {
442 /* whatever was clicked was selected already; do nothing here but allow
443 the button release to deselect it
446 button_release_can_deselect = true;
450 if (button_release_can_deselect) {
452 /* just remove this one region, but only on a permitted button release */
454 selection->remove (clicked_regionview);
457 /* no more deselect action on button release till a new press
458 finds an already selected object.
461 button_release_can_deselect = false;
469 if (selection->selected (clicked_routeview)) {
470 get_equivalent_regions (clicked_regionview, all_equivalent_regions);
472 all_equivalent_regions.push_back (clicked_regionview);
475 /* add all the equivalent regions, but only on button press */
479 if (!all_equivalent_regions.empty()) {
483 selection->add (all_equivalent_regions);
489 if (!selection->selected (clicked_regionview)) {
490 selection->set (clicked_regionview);
493 /* no commit necessary: clicked on an already selected region */
503 } else if (op == Selection::Extend) {
505 list<Selectable*> results;
506 nframes64_t last_frame;
507 nframes64_t first_frame;
508 bool same_track = false;
510 /* 1. find the last selected regionview in the track that was clicked in */
513 first_frame = max_frames;
515 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
516 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
518 if ((*x)->region()->last_frame() > last_frame) {
519 last_frame = (*x)->region()->last_frame();
522 if ((*x)->region()->first_frame() < first_frame) {
523 first_frame = (*x)->region()->first_frame();
532 /* 2. figure out the boundaries for our search for new objects */
534 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
536 if (last_frame < clicked_regionview->region()->first_frame()) {
537 first_frame = last_frame;
538 last_frame = clicked_regionview->region()->last_frame();
540 last_frame = first_frame;
541 first_frame = clicked_regionview->region()->first_frame();
545 case OverlapExternal:
546 if (last_frame < clicked_regionview->region()->first_frame()) {
547 first_frame = last_frame;
548 last_frame = clicked_regionview->region()->last_frame();
550 last_frame = first_frame;
551 first_frame = clicked_regionview->region()->first_frame();
555 case OverlapInternal:
556 if (last_frame < clicked_regionview->region()->first_frame()) {
557 first_frame = last_frame;
558 last_frame = clicked_regionview->region()->last_frame();
560 last_frame = first_frame;
561 first_frame = clicked_regionview->region()->first_frame();
567 /* nothing to do except add clicked region to selection, since it
568 overlaps with the existing selection in this track.
575 /* click in a track that has no regions selected, so extend vertically
576 to pick out all regions that are defined by the existing selection
581 first_frame = entered_regionview->region()->position();
582 last_frame = entered_regionview->region()->last_frame();
584 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
585 if ((*i)->region()->position() < first_frame) {
586 first_frame = (*i)->region()->position();
588 if ((*i)->region()->last_frame() + 1 > last_frame) {
589 last_frame = (*i)->region()->last_frame();
594 /* 2. find all the tracks we should select in */
596 set<RouteTimeAxisView*> relevant_tracks;
597 set<RouteTimeAxisView*> already_in_selection;
599 get_relevant_tracks (relevant_tracks);
601 if (relevant_tracks.empty()) {
603 /* no relevant tracks -> no tracks selected .. thus .. if
604 the regionview we're in isn't selected (i.e. we're
605 about to extend to it), then find all tracks between
606 the this one and any selected ones.
609 if (!selection->selected (entered_regionview)) {
611 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
615 /* add this track to the ones we will search */
617 relevant_tracks.insert (rtv);
619 /* find the track closest to this one that
620 already a selected region.
623 RouteTimeAxisView* closest = 0;
624 int distance = INT_MAX;
625 int key = rtv->route()->order_key ("editor");
627 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
629 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
631 if (artv && artv != rtv) {
633 pair<set<RouteTimeAxisView*>::iterator,bool> result;
635 result = already_in_selection.insert (artv);
638 /* newly added to already_in_selection */
641 int d = artv->route()->order_key ("editor");
645 if (abs (d) < distance) {
655 /* now add all tracks between that one and this one */
657 int okey = closest->route()->order_key ("editor");
663 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
664 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
665 if (artv && artv != rtv) {
667 int k = artv->route()->order_key ("editor");
669 if (k >= okey && k <= key) {
671 /* in range but don't add it if
672 it already has tracks selected.
673 this avoids odd selection
674 behaviour that feels wrong.
677 if (find (already_in_selection.begin(),
678 already_in_selection.end(),
679 artv) == already_in_selection.end()) {
681 relevant_tracks.insert (artv);
691 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
692 one that was clicked.
695 get_relevant_tracks (relevant_tracks);
697 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
698 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
701 /* 4. convert to a vector of regions */
703 vector<RegionView*> regions;
705 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
708 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
709 regions.push_back (arv);
713 if (!regions.empty()) {
714 selection->add (regions);
725 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
727 vector<RegionView*> all_equivalent_regions;
729 get_regions_corresponding_to (region, all_equivalent_regions);
731 if (all_equivalent_regions.empty()) {
735 begin_reversible_command (_("set selected regions"));
738 case Selection::Toggle:
739 /* XXX this is not correct */
740 selection->toggle (all_equivalent_regions);
743 selection->set (all_equivalent_regions);
745 case Selection::Extend:
746 selection->add (all_equivalent_regions);
749 selection->add (all_equivalent_regions);
753 commit_reversible_command () ;
757 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
760 boost::shared_ptr<Region> r (weak_r.lock());
766 if ((rv = sv->find_view (r)) == 0) {
770 /* don't reset the selection if its something other than
771 a single other region.
774 if (selection->regions.size() > 1) {
778 begin_reversible_command (_("set selected regions"));
782 commit_reversible_command () ;
788 Editor::track_selection_changed ()
790 switch (selection->tracks.size()){
794 set_selected_mixer_strip (*(selection->tracks.front()));
798 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
799 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
800 (*i)->set_selected (true);
802 (*i)->set_selected (false);
806 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
810 Editor::time_selection_changed ()
812 if (Profile->get_sae()) {
816 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
817 (*i)->hide_selection ();
820 if (selection->tracks.empty()) {
821 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
822 (*i)->show_selection (selection->time);
825 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
826 (*i)->show_selection (selection->time);
830 if (selection->time.empty()) {
831 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
833 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
839 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
841 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
842 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
844 string accel_path = (*x)->get_accel_path ();
847 /* if there is an accelerator, it should always be sensitive
848 to allow for keyboard ops on entered regions.
851 bool known = ActionManager::lookup_entry (accel_path, key);
853 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
854 (*x)->set_sensitive (true);
856 (*x)->set_sensitive (have_selected_regions);
863 Editor::region_selection_changed ()
865 region_list_change_connection.block(true);
866 editor_regions_selection_changed_connection.block(true);
868 region_list_display.get_selection()->unselect_all();
870 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
872 (*i)->set_selected_regionviews (selection->regions);
873 set_selected_in_region_list(selection->regions);
877 sensitize_the_right_region_actions (!selection->regions.empty());
879 zoomed_to_region = false;
881 region_list_change_connection.block(false);
882 editor_regions_selection_changed_connection.block(false);
886 Editor::point_selection_changed ()
888 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
889 (*i)->set_selected_points (selection->points);
894 Editor::select_all_in_track (Selection::Operation op)
896 list<Selectable *> touched;
898 if (!clicked_routeview) {
902 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
905 case Selection::Toggle:
906 selection->add (touched);
909 selection->set (touched);
911 case Selection::Extend:
912 /* meaningless, because we're selecting everything */
915 selection->add (touched);
921 Editor::select_all (Selection::Operation op)
923 list<Selectable *> touched;
925 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
926 if ((*iter)->hidden()) {
929 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
931 begin_reversible_command (_("select all"));
934 selection->add (touched);
936 case Selection::Toggle:
937 selection->add (touched);
940 selection->set (touched);
942 case Selection::Extend:
943 /* meaningless, because we're selecting everything */
946 commit_reversible_command ();
949 Editor::invert_selection_in_track ()
951 list<Selectable *> touched;
953 if (!clicked_routeview) {
957 clicked_routeview->get_inverted_selectables (*selection, touched);
958 selection->set (touched);
962 Editor::invert_selection ()
964 list<Selectable *> touched;
966 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
967 if ((*iter)->hidden()) {
970 (*iter)->get_inverted_selectables (*selection, touched);
973 selection->set (touched);
977 Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
979 list<Selectable*> touched;
980 list<Selectable*>::size_type n = 0;
981 TrackViewList touched_tracks;
983 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
984 if ((*iter)->hidden()) {
990 (*iter)->get_selectables (start, end, top, bot, touched);
992 if (n != touched.size()) {
993 touched_tracks.push_back (*iter);
997 if (touched.empty()) {
1001 if (!touched_tracks.empty()) {
1004 case Selection::Add:
1005 selection->add (touched_tracks);
1007 case Selection::Toggle:
1008 selection->toggle (touched_tracks);
1010 case Selection::Set:
1011 selection->set (touched_tracks);
1013 case Selection::Extend:
1014 /* not defined yet */
1019 begin_reversible_command (_("select all within"));
1021 case Selection::Add:
1022 selection->add (touched);
1024 case Selection::Toggle:
1025 selection->toggle (touched);
1027 case Selection::Set:
1028 selection->set (touched);
1030 case Selection::Extend:
1031 /* not defined yet */
1035 commit_reversible_command ();
1037 return !touched.empty();
1041 Editor::set_selection_from_region ()
1043 if (selection->regions.empty()) {
1047 selection->set (0, selection->regions.start(), selection->regions.end_frame());
1048 if (!Profile->get_sae()) {
1049 set_mouse_mode (Editing::MouseRange, false);
1054 Editor::set_selection_from_punch()
1058 if ((location = session->locations()->auto_punch_location()) == 0) {
1062 set_selection_from_range (*location);
1066 Editor::set_selection_from_loop()
1070 if ((location = session->locations()->auto_loop_location()) == 0) {
1073 set_selection_from_range (*location);
1077 Editor::set_selection_from_range (Location& loc)
1079 begin_reversible_command (_("set selection from range"));
1080 selection->set (0, loc.start(), loc.end());
1081 commit_reversible_command ();
1083 if (!Profile->get_sae()) {
1084 set_mouse_mode (Editing::MouseRange, false);
1089 Editor::select_all_selectables_using_time_selection ()
1091 list<Selectable *> touched;
1093 if (selection->time.empty()) {
1097 nframes64_t start = selection->time[clicked_selection].start;
1098 nframes64_t end = selection->time[clicked_selection].end;
1100 if (end - start < 1) {
1106 if (selection->tracks.empty()) {
1109 ts = &selection->tracks;
1112 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1113 if ((*iter)->hidden()) {
1116 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1119 begin_reversible_command (_("select all from range"));
1120 selection->set (touched);
1121 commit_reversible_command ();
1126 Editor::select_all_selectables_using_punch()
1128 Location* location = session->locations()->auto_punch_location();
1129 list<Selectable *> touched;
1131 if (location == 0 || (location->end() - location->start() <= 1)) {
1138 if (selection->tracks.empty()) {
1141 ts = &selection->tracks;
1144 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1145 if ((*iter)->hidden()) {
1148 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1150 begin_reversible_command (_("select all from punch"));
1151 selection->set (touched);
1152 commit_reversible_command ();
1157 Editor::select_all_selectables_using_loop()
1159 Location* location = session->locations()->auto_loop_location();
1160 list<Selectable *> touched;
1162 if (location == 0 || (location->end() - location->start() <= 1)) {
1169 if (selection->tracks.empty()) {
1172 ts = &selection->tracks;
1175 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1176 if ((*iter)->hidden()) {
1179 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1181 begin_reversible_command (_("select all from loop"));
1182 selection->set (touched);
1183 commit_reversible_command ();
1188 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1192 list<Selectable *> touched;
1195 begin_reversible_command (_("select all after cursor"));
1196 start = cursor->current_frame ;
1197 end = session->current_end_frame();
1199 if (cursor->current_frame > 0) {
1200 begin_reversible_command (_("select all before cursor"));
1202 end = cursor->current_frame - 1;
1211 if (selection->tracks.empty()) {
1214 ts = &selection->tracks;
1217 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1218 if ((*iter)->hidden()) {
1221 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1223 selection->set (touched);
1224 commit_reversible_command ();
1228 Editor::select_all_selectables_using_edit (bool after)
1232 list<Selectable *> touched;
1235 begin_reversible_command (_("select all after edit"));
1236 start = get_preferred_edit_position();
1237 end = session->current_end_frame();
1239 if ((end = get_preferred_edit_position()) > 1) {
1240 begin_reversible_command (_("select all before edit"));
1251 if (selection->tracks.empty()) {
1254 ts = &selection->tracks;
1257 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1258 if ((*iter)->hidden()) {
1261 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1263 selection->set (touched);
1264 commit_reversible_command ();
1268 Editor::select_all_selectables_between (bool within)
1272 list<Selectable *> touched;
1274 if (!get_edit_op_range (start, end)) {
1280 if (selection->tracks.empty()) {
1283 ts = &selection->tracks;
1286 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1287 if ((*iter)->hidden()) {
1290 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1293 selection->set (touched);
1297 Editor::select_range_between ()
1302 if (!get_edit_op_range (start, end)) {
1306 set_mouse_mode (MouseRange);
1307 selection->set ((TimeAxisView*) 0, start, end);
1311 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1316 /* in range mode, use any existing selection */
1318 if (mouse_mode == MouseRange && !selection->time.empty()) {
1319 /* we know that these are ordered */
1320 start = selection->time.start();
1321 end = selection->time.end_frame();
1325 if (!mouse_frame (m, ignored)) {
1326 /* mouse is not in a canvas, try playhead+selected marker.
1327 this is probably most true when using menus.
1330 if (selection->markers.empty()) {
1334 start = selection->markers.front()->position();
1335 end = session->audible_frame();
1339 switch (_edit_point) {
1340 case EditAtPlayhead:
1341 if (selection->markers.empty()) {
1342 /* use mouse + playhead */
1344 end = session->audible_frame();
1346 /* use playhead + selected marker */
1347 start = session->audible_frame();
1348 end = selection->markers.front()->position();
1353 /* use mouse + selected marker */
1354 if (selection->markers.empty()) {
1356 end = session->audible_frame();
1358 start = selection->markers.front()->position();
1363 case EditAtSelectedMarker:
1364 /* use mouse + selected marker */
1365 if (selection->markers.empty()) {
1367 MessageDialog win (_("No edit range defined"),
1372 win.set_secondary_text (
1373 _("the edit point is Selected Marker\nbut there is no selected marker."));
1376 win.set_default_response (RESPONSE_CLOSE);
1377 win.set_position (Gtk::WIN_POS_MOUSE);
1382 return false; // NO RANGE
1384 start = selection->markers.front()->position();
1398 /* turn range into one delimited by start...end,
1408 Editor::deselect_all ()
1410 selection->clear ();