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_relevant_tracks (set<RouteTimeAxisView*>& relevant_tracks)
257 /* step one: get all selected tracks and all tracks in the relevant edit groups */
259 for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
261 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*ti);
267 RouteGroup* group = rtv->route()->edit_group();
269 if (group && group->is_active()) {
271 /* active group for this track, loop over all tracks and get every member of the group */
273 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
275 RouteTimeAxisView* trtv;
277 if ((trtv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
279 if (trtv->route()->edit_group() == group) {
280 relevant_tracks.insert (trtv);
285 relevant_tracks.insert (rtv);
291 * Call a slot for a given `basis' track and also for any track that is in the same
293 * @param sl Slot to call.
294 * @param basis Basis track.
298 Editor::mapover_tracks (slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis) const
300 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
301 if (route_basis == 0) {
305 /* work out the tracks that we will call the slot for; use
306 a set here as it will disallow possible duplicates of the
308 set<RouteTimeAxisView*> tracks;
310 /* always call for the basis */
311 tracks.insert (route_basis);
313 RouteGroup* group = route_basis->route()->edit_group();
314 if (group && group->is_active()) {
316 /* the basis is a member of an active edit group; find other members */
317 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
318 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
319 if (v && v->route()->edit_group() == group) {
326 uint32_t const sz = tracks.size ();
327 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
333 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t ignored, RegionView* basis, vector<RegionView*>* all_equivs) const
335 boost::shared_ptr<Playlist> pl;
336 vector<boost::shared_ptr<Region> > results;
338 boost::shared_ptr<Diskstream> ds;
340 if ((ds = tv.get_diskstream()) == 0) {
345 if (&tv == &basis->get_time_axis_view()) {
346 /* looking in same track as the original */
350 if ((pl = ds->playlist()) != 0) {
351 pl->get_equivalent_regions (basis->region(), results);
354 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
355 if ((marv = tv.view()->find_view (*ir)) != 0) {
356 all_equivs->push_back (marv);
362 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions) const
364 mapover_tracks (bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview());
366 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
368 equivalent_regions.push_back (basis);
372 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
374 int region_count = 0;
376 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
378 RouteTimeAxisView* tatv;
380 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
382 boost::shared_ptr<Playlist> pl;
383 vector<boost::shared_ptr<Region> > results;
385 boost::shared_ptr<Diskstream> ds;
387 if ((ds = tatv->get_diskstream()) == 0) {
392 if ((pl = (ds->playlist())) != 0) {
393 pl->get_region_list_equivalent_regions (region, results);
396 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
397 if ((marv = tatv->view()->find_view (*ir)) != 0) {
410 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
412 vector<RegionView*> all_equivalent_regions;
415 if (!clicked_regionview || !clicked_routeview) {
420 button_release_can_deselect = false;
423 if (op == Selection::Toggle || op == Selection::Set) {
427 case Selection::Toggle:
429 if (selection->selected (clicked_regionview)) {
432 /* whatever was clicked was selected already; do nothing here but allow
433 the button release to deselect it
436 button_release_can_deselect = true;
440 if (button_release_can_deselect) {
442 /* just remove this one region, but only on a permitted button release */
444 selection->remove (clicked_regionview);
447 /* no more deselect action on button release till a new press
448 finds an already selected object.
451 button_release_can_deselect = false;
459 if (selection->selected (clicked_routeview)) {
460 get_equivalent_regions (clicked_regionview, all_equivalent_regions);
462 all_equivalent_regions.push_back (clicked_regionview);
465 /* add all the equivalent regions, but only on button press */
469 if (!all_equivalent_regions.empty()) {
473 selection->add (all_equivalent_regions);
479 if (!selection->selected (clicked_regionview)) {
480 selection->set (clicked_regionview);
483 /* no commit necessary: clicked on an already selected region */
493 } else if (op == Selection::Extend) {
495 list<Selectable*> results;
496 nframes64_t last_frame;
497 nframes64_t first_frame;
498 bool same_track = false;
500 /* 1. find the last selected regionview in the track that was clicked in */
503 first_frame = max_frames;
505 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
506 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
508 if ((*x)->region()->last_frame() > last_frame) {
509 last_frame = (*x)->region()->last_frame();
512 if ((*x)->region()->first_frame() < first_frame) {
513 first_frame = (*x)->region()->first_frame();
522 /* 2. figure out the boundaries for our search for new objects */
524 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
526 if (last_frame < clicked_regionview->region()->first_frame()) {
527 first_frame = last_frame;
528 last_frame = clicked_regionview->region()->last_frame();
530 last_frame = first_frame;
531 first_frame = clicked_regionview->region()->first_frame();
535 case OverlapExternal:
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 OverlapInternal:
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();
557 /* nothing to do except add clicked region to selection, since it
558 overlaps with the existing selection in this track.
565 /* click in a track that has no regions selected, so extend vertically
566 to pick out all regions that are defined by the existing selection
571 first_frame = entered_regionview->region()->position();
572 last_frame = entered_regionview->region()->last_frame();
574 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
575 if ((*i)->region()->position() < first_frame) {
576 first_frame = (*i)->region()->position();
578 if ((*i)->region()->last_frame() + 1 > last_frame) {
579 last_frame = (*i)->region()->last_frame();
584 /* 2. find all the tracks we should select in */
586 set<RouteTimeAxisView*> relevant_tracks;
587 set<RouteTimeAxisView*> already_in_selection;
589 get_relevant_tracks (relevant_tracks);
591 if (relevant_tracks.empty()) {
593 /* no relevant tracks -> no tracks selected .. thus .. if
594 the regionview we're in isn't selected (i.e. we're
595 about to extend to it), then find all tracks between
596 the this one and any selected ones.
599 if (!selection->selected (entered_regionview)) {
601 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
605 /* add this track to the ones we will search */
607 relevant_tracks.insert (rtv);
609 /* find the track closest to this one that
610 already a selected region.
613 RouteTimeAxisView* closest = 0;
614 int distance = INT_MAX;
615 int key = rtv->route()->order_key ("editor");
617 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
619 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
621 if (artv && artv != rtv) {
623 pair<set<RouteTimeAxisView*>::iterator,bool> result;
625 result = already_in_selection.insert (artv);
628 /* newly added to already_in_selection */
631 int d = artv->route()->order_key ("editor");
635 if (abs (d) < distance) {
645 /* now add all tracks between that one and this one */
647 int okey = closest->route()->order_key ("editor");
653 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
654 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
655 if (artv && artv != rtv) {
657 int k = artv->route()->order_key ("editor");
659 if (k >= okey && k <= key) {
661 /* in range but don't add it if
662 it already has tracks selected.
663 this avoids odd selection
664 behaviour that feels wrong.
667 if (find (already_in_selection.begin(),
668 already_in_selection.end(),
669 artv) == already_in_selection.end()) {
671 relevant_tracks.insert (artv);
681 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
682 one that was clicked.
685 get_relevant_tracks (relevant_tracks);
687 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
688 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
691 /* 4. convert to a vector of regions */
693 vector<RegionView*> regions;
695 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
698 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
699 regions.push_back (arv);
703 if (!regions.empty()) {
704 selection->add (regions);
715 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
717 vector<RegionView*> all_equivalent_regions;
719 get_regions_corresponding_to (region, all_equivalent_regions);
721 if (all_equivalent_regions.empty()) {
725 begin_reversible_command (_("set selected regions"));
728 case Selection::Toggle:
729 /* XXX this is not correct */
730 selection->toggle (all_equivalent_regions);
733 selection->set (all_equivalent_regions);
735 case Selection::Extend:
736 selection->add (all_equivalent_regions);
739 selection->add (all_equivalent_regions);
743 commit_reversible_command () ;
747 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
750 boost::shared_ptr<Region> r (weak_r.lock());
756 if ((rv = sv->find_view (r)) == 0) {
760 /* don't reset the selection if its something other than
761 a single other region.
764 if (selection->regions.size() > 1) {
768 begin_reversible_command (_("set selected regions"));
772 commit_reversible_command () ;
778 Editor::track_selection_changed ()
780 switch (selection->tracks.size()){
784 set_selected_mixer_strip (*(selection->tracks.front()));
788 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
789 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
790 (*i)->set_selected (true);
792 (*i)->set_selected (false);
796 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
800 Editor::time_selection_changed ()
802 if (Profile->get_sae()) {
806 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
807 (*i)->hide_selection ();
810 if (selection->tracks.empty()) {
811 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
812 (*i)->show_selection (selection->time);
815 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
816 (*i)->show_selection (selection->time);
820 if (selection->time.empty()) {
821 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
823 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
829 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
831 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
832 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
834 string accel_path = (*x)->get_accel_path ();
837 /* if there is an accelerator, it should always be sensitive
838 to allow for keyboard ops on entered regions.
841 bool known = ActionManager::lookup_entry (accel_path, key);
843 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
844 (*x)->set_sensitive (true);
846 (*x)->set_sensitive (have_selected_regions);
853 Editor::region_selection_changed ()
855 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
856 (*i)->set_selected_regionviews (selection->regions);
859 sensitize_the_right_region_actions (!selection->regions.empty());
861 zoomed_to_region = false;
865 Editor::point_selection_changed ()
867 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
868 (*i)->set_selected_points (selection->points);
873 Editor::select_all_in_track (Selection::Operation op)
875 list<Selectable *> touched;
877 if (!clicked_routeview) {
881 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
884 case Selection::Toggle:
885 selection->add (touched);
888 selection->set (touched);
890 case Selection::Extend:
891 /* meaningless, because we're selecting everything */
894 selection->add (touched);
900 Editor::select_all (Selection::Operation op)
902 list<Selectable *> touched;
904 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
905 if ((*iter)->hidden()) {
908 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
910 begin_reversible_command (_("select all"));
913 selection->add (touched);
915 case Selection::Toggle:
916 selection->add (touched);
919 selection->set (touched);
921 case Selection::Extend:
922 /* meaningless, because we're selecting everything */
925 commit_reversible_command ();
928 Editor::invert_selection_in_track ()
930 list<Selectable *> touched;
932 if (!clicked_routeview) {
936 clicked_routeview->get_inverted_selectables (*selection, touched);
937 selection->set (touched);
941 Editor::invert_selection ()
943 list<Selectable *> touched;
945 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
946 if ((*iter)->hidden()) {
949 (*iter)->get_inverted_selectables (*selection, touched);
952 selection->set (touched);
956 Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
958 list<Selectable*> touched;
959 list<Selectable*>::size_type n = 0;
960 TrackViewList touched_tracks;
962 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
963 if ((*iter)->hidden()) {
969 (*iter)->get_selectables (start, end, top, bot, touched);
971 if (n != touched.size()) {
972 touched_tracks.push_back (*iter);
976 if (touched.empty()) {
980 if (!touched_tracks.empty()) {
984 selection->add (touched_tracks);
986 case Selection::Toggle:
987 selection->toggle (touched_tracks);
990 selection->set (touched_tracks);
992 case Selection::Extend:
993 /* not defined yet */
998 begin_reversible_command (_("select all within"));
1000 case Selection::Add:
1001 selection->add (touched);
1003 case Selection::Toggle:
1004 selection->toggle (touched);
1006 case Selection::Set:
1007 selection->set (touched);
1009 case Selection::Extend:
1010 /* not defined yet */
1014 commit_reversible_command ();
1016 return !touched.empty();
1020 Editor::set_selection_from_region ()
1022 if (selection->regions.empty()) {
1026 selection->set (0, selection->regions.start(), selection->regions.end_frame());
1027 if (!Profile->get_sae()) {
1028 set_mouse_mode (Editing::MouseRange, false);
1033 Editor::set_selection_from_punch()
1037 if ((location = session->locations()->auto_punch_location()) == 0) {
1041 set_selection_from_range (*location);
1045 Editor::set_selection_from_loop()
1049 if ((location = session->locations()->auto_loop_location()) == 0) {
1052 set_selection_from_range (*location);
1056 Editor::set_selection_from_range (Location& loc)
1058 begin_reversible_command (_("set selection from range"));
1059 selection->set (0, loc.start(), loc.end());
1060 commit_reversible_command ();
1062 if (!Profile->get_sae()) {
1063 set_mouse_mode (Editing::MouseRange, false);
1068 Editor::select_all_selectables_using_time_selection ()
1070 list<Selectable *> touched;
1072 if (selection->time.empty()) {
1076 nframes64_t start = selection->time[clicked_selection].start;
1077 nframes64_t end = selection->time[clicked_selection].end;
1079 if (end - start < 1) {
1085 if (selection->tracks.empty()) {
1088 ts = &selection->tracks;
1091 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1092 if ((*iter)->hidden()) {
1095 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1098 begin_reversible_command (_("select all from range"));
1099 selection->set (touched);
1100 commit_reversible_command ();
1105 Editor::select_all_selectables_using_punch()
1107 Location* location = session->locations()->auto_punch_location();
1108 list<Selectable *> touched;
1110 if (location == 0 || (location->end() - location->start() <= 1)) {
1117 if (selection->tracks.empty()) {
1120 ts = &selection->tracks;
1123 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1124 if ((*iter)->hidden()) {
1127 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1129 begin_reversible_command (_("select all from punch"));
1130 selection->set (touched);
1131 commit_reversible_command ();
1136 Editor::select_all_selectables_using_loop()
1138 Location* location = session->locations()->auto_loop_location();
1139 list<Selectable *> touched;
1141 if (location == 0 || (location->end() - location->start() <= 1)) {
1148 if (selection->tracks.empty()) {
1151 ts = &selection->tracks;
1154 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1155 if ((*iter)->hidden()) {
1158 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1160 begin_reversible_command (_("select all from loop"));
1161 selection->set (touched);
1162 commit_reversible_command ();
1167 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1171 list<Selectable *> touched;
1174 begin_reversible_command (_("select all after cursor"));
1175 start = cursor->current_frame ;
1176 end = session->current_end_frame();
1178 if (cursor->current_frame > 0) {
1179 begin_reversible_command (_("select all before cursor"));
1181 end = cursor->current_frame - 1;
1190 if (selection->tracks.empty()) {
1193 ts = &selection->tracks;
1196 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1197 if ((*iter)->hidden()) {
1200 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1202 selection->set (touched);
1203 commit_reversible_command ();
1207 Editor::select_all_selectables_using_edit (bool after)
1211 list<Selectable *> touched;
1214 begin_reversible_command (_("select all after edit"));
1215 start = get_preferred_edit_position();
1216 end = session->current_end_frame();
1218 if ((end = get_preferred_edit_position()) > 1) {
1219 begin_reversible_command (_("select all before edit"));
1230 if (selection->tracks.empty()) {
1233 ts = &selection->tracks;
1236 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1237 if ((*iter)->hidden()) {
1240 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1242 selection->set (touched);
1243 commit_reversible_command ();
1247 Editor::select_all_selectables_between (bool within)
1251 list<Selectable *> touched;
1253 if (!get_edit_op_range (start, end)) {
1259 if (selection->tracks.empty()) {
1262 ts = &selection->tracks;
1265 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1266 if ((*iter)->hidden()) {
1269 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1272 selection->set (touched);
1276 Editor::select_range_between ()
1281 if (!get_edit_op_range (start, end)) {
1285 set_mouse_mode (MouseRange);
1286 selection->set ((TimeAxisView*) 0, start, end);
1290 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1295 /* in range mode, use any existing selection */
1297 if (mouse_mode == MouseRange && !selection->time.empty()) {
1298 /* we know that these are ordered */
1299 start = selection->time.start();
1300 end = selection->time.end_frame();
1304 if (!mouse_frame (m, ignored)) {
1305 /* mouse is not in a canvas, try playhead+selected marker.
1306 this is probably most true when using menus.
1309 if (selection->markers.empty()) {
1313 start = selection->markers.front()->position();
1314 end = session->audible_frame();
1318 switch (_edit_point) {
1319 case EditAtPlayhead:
1320 if (selection->markers.empty()) {
1321 /* use mouse + playhead */
1323 end = session->audible_frame();
1325 /* use playhead + selected marker */
1326 start = session->audible_frame();
1327 end = selection->markers.front()->position();
1332 /* use mouse + selected marker */
1333 if (selection->markers.empty()) {
1335 end = session->audible_frame();
1337 start = selection->markers.front()->position();
1342 case EditAtSelectedMarker:
1343 /* use mouse + selected marker */
1344 if (selection->markers.empty()) {
1346 MessageDialog win (_("No edit range defined"),
1351 win.set_secondary_text (
1352 _("the edit point is Selected Marker\nbut there is no selected marker."));
1355 win.set_default_response (RESPONSE_CLOSE);
1356 win.set_position (Gtk::WIN_POS_MOUSE);
1361 return false; // NO RANGE
1363 start = selection->markers.front()->position();
1377 /* turn range into one delimited by start...end,
1387 Editor::deselect_all ()
1389 selection->clear ();