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 region_list_change_connection.block(true);
856 editor_regions_selection_changed_connection.block(true);
858 region_list_display.get_selection()->unselect_all();
860 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
862 (*i)->set_selected_regionviews (selection->regions);
863 set_selected_in_region_list(selection->regions);
867 sensitize_the_right_region_actions (!selection->regions.empty());
869 zoomed_to_region = false;
871 region_list_change_connection.block(false);
872 editor_regions_selection_changed_connection.block(false);
876 Editor::point_selection_changed ()
878 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
879 (*i)->set_selected_points (selection->points);
884 Editor::select_all_in_track (Selection::Operation op)
886 list<Selectable *> touched;
888 if (!clicked_routeview) {
892 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
895 case Selection::Toggle:
896 selection->add (touched);
899 selection->set (touched);
901 case Selection::Extend:
902 /* meaningless, because we're selecting everything */
905 selection->add (touched);
911 Editor::select_all (Selection::Operation op)
913 list<Selectable *> touched;
915 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
916 if ((*iter)->hidden()) {
919 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
921 begin_reversible_command (_("select all"));
924 selection->add (touched);
926 case Selection::Toggle:
927 selection->add (touched);
930 selection->set (touched);
932 case Selection::Extend:
933 /* meaningless, because we're selecting everything */
936 commit_reversible_command ();
939 Editor::invert_selection_in_track ()
941 list<Selectable *> touched;
943 if (!clicked_routeview) {
947 clicked_routeview->get_inverted_selectables (*selection, touched);
948 selection->set (touched);
952 Editor::invert_selection ()
954 list<Selectable *> touched;
956 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
957 if ((*iter)->hidden()) {
960 (*iter)->get_inverted_selectables (*selection, touched);
963 selection->set (touched);
967 Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
969 list<Selectable*> touched;
970 list<Selectable*>::size_type n = 0;
971 TrackViewList touched_tracks;
973 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
974 if ((*iter)->hidden()) {
980 (*iter)->get_selectables (start, end, top, bot, touched);
982 if (n != touched.size()) {
983 touched_tracks.push_back (*iter);
987 if (touched.empty()) {
991 if (!touched_tracks.empty()) {
995 selection->add (touched_tracks);
997 case Selection::Toggle:
998 selection->toggle (touched_tracks);
1000 case Selection::Set:
1001 selection->set (touched_tracks);
1003 case Selection::Extend:
1004 /* not defined yet */
1009 begin_reversible_command (_("select all within"));
1011 case Selection::Add:
1012 selection->add (touched);
1014 case Selection::Toggle:
1015 selection->toggle (touched);
1017 case Selection::Set:
1018 selection->set (touched);
1020 case Selection::Extend:
1021 /* not defined yet */
1025 commit_reversible_command ();
1027 return !touched.empty();
1031 Editor::set_selection_from_region ()
1033 if (selection->regions.empty()) {
1037 selection->set (0, selection->regions.start(), selection->regions.end_frame());
1038 if (!Profile->get_sae()) {
1039 set_mouse_mode (Editing::MouseRange, false);
1044 Editor::set_selection_from_punch()
1048 if ((location = session->locations()->auto_punch_location()) == 0) {
1052 set_selection_from_range (*location);
1056 Editor::set_selection_from_loop()
1060 if ((location = session->locations()->auto_loop_location()) == 0) {
1063 set_selection_from_range (*location);
1067 Editor::set_selection_from_range (Location& loc)
1069 begin_reversible_command (_("set selection from range"));
1070 selection->set (0, loc.start(), loc.end());
1071 commit_reversible_command ();
1073 if (!Profile->get_sae()) {
1074 set_mouse_mode (Editing::MouseRange, false);
1079 Editor::select_all_selectables_using_time_selection ()
1081 list<Selectable *> touched;
1083 if (selection->time.empty()) {
1087 nframes64_t start = selection->time[clicked_selection].start;
1088 nframes64_t end = selection->time[clicked_selection].end;
1090 if (end - start < 1) {
1096 if (selection->tracks.empty()) {
1099 ts = &selection->tracks;
1102 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1103 if ((*iter)->hidden()) {
1106 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1109 begin_reversible_command (_("select all from range"));
1110 selection->set (touched);
1111 commit_reversible_command ();
1116 Editor::select_all_selectables_using_punch()
1118 Location* location = session->locations()->auto_punch_location();
1119 list<Selectable *> touched;
1121 if (location == 0 || (location->end() - location->start() <= 1)) {
1128 if (selection->tracks.empty()) {
1131 ts = &selection->tracks;
1134 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1135 if ((*iter)->hidden()) {
1138 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1140 begin_reversible_command (_("select all from punch"));
1141 selection->set (touched);
1142 commit_reversible_command ();
1147 Editor::select_all_selectables_using_loop()
1149 Location* location = session->locations()->auto_loop_location();
1150 list<Selectable *> touched;
1152 if (location == 0 || (location->end() - location->start() <= 1)) {
1159 if (selection->tracks.empty()) {
1162 ts = &selection->tracks;
1165 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1166 if ((*iter)->hidden()) {
1169 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1171 begin_reversible_command (_("select all from loop"));
1172 selection->set (touched);
1173 commit_reversible_command ();
1178 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1182 list<Selectable *> touched;
1185 begin_reversible_command (_("select all after cursor"));
1186 start = cursor->current_frame ;
1187 end = session->current_end_frame();
1189 if (cursor->current_frame > 0) {
1190 begin_reversible_command (_("select all before cursor"));
1192 end = cursor->current_frame - 1;
1201 if (selection->tracks.empty()) {
1204 ts = &selection->tracks;
1207 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1208 if ((*iter)->hidden()) {
1211 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1213 selection->set (touched);
1214 commit_reversible_command ();
1218 Editor::select_all_selectables_using_edit (bool after)
1222 list<Selectable *> touched;
1225 begin_reversible_command (_("select all after edit"));
1226 start = get_preferred_edit_position();
1227 end = session->current_end_frame();
1229 if ((end = get_preferred_edit_position()) > 1) {
1230 begin_reversible_command (_("select all before edit"));
1241 if (selection->tracks.empty()) {
1244 ts = &selection->tracks;
1247 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1248 if ((*iter)->hidden()) {
1251 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1253 selection->set (touched);
1254 commit_reversible_command ();
1258 Editor::select_all_selectables_between (bool within)
1262 list<Selectable *> touched;
1264 if (!get_edit_op_range (start, end)) {
1270 if (selection->tracks.empty()) {
1273 ts = &selection->tracks;
1276 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1277 if ((*iter)->hidden()) {
1280 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1283 selection->set (touched);
1287 Editor::select_range_between ()
1292 if (!get_edit_op_range (start, end)) {
1296 set_mouse_mode (MouseRange);
1297 selection->set ((TimeAxisView*) 0, start, end);
1301 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1306 /* in range mode, use any existing selection */
1308 if (mouse_mode == MouseRange && !selection->time.empty()) {
1309 /* we know that these are ordered */
1310 start = selection->time.start();
1311 end = selection->time.end_frame();
1315 if (!mouse_frame (m, ignored)) {
1316 /* mouse is not in a canvas, try playhead+selected marker.
1317 this is probably most true when using menus.
1320 if (selection->markers.empty()) {
1324 start = selection->markers.front()->position();
1325 end = session->audible_frame();
1329 switch (_edit_point) {
1330 case EditAtPlayhead:
1331 if (selection->markers.empty()) {
1332 /* use mouse + playhead */
1334 end = session->audible_frame();
1336 /* use playhead + selected marker */
1337 start = session->audible_frame();
1338 end = selection->markers.front()->position();
1343 /* use mouse + selected marker */
1344 if (selection->markers.empty()) {
1346 end = session->audible_frame();
1348 start = selection->markers.front()->position();
1353 case EditAtSelectedMarker:
1354 /* use mouse + selected marker */
1355 if (selection->markers.empty()) {
1357 MessageDialog win (_("No edit range defined"),
1362 win.set_secondary_text (
1363 _("the edit point is Selected Marker\nbut there is no selected marker."));
1366 win.set_default_response (RESPONSE_CLOSE);
1367 win.set_position (Gtk::WIN_POS_MOUSE);
1372 return false; // NO RANGE
1374 start = selection->markers.front()->position();
1388 /* turn range into one delimited by start...end,
1398 Editor::deselect_all ()
1400 selection->clear ();