2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "pbd/stacktrace.h"
25 #include "ardour/session.h"
26 #include "ardour/diskstream.h"
27 #include "ardour/playlist.h"
28 #include "ardour/route_group.h"
29 #include "ardour/profile.h"
33 #include "audio_time_axis.h"
34 #include "audio_region_view.h"
35 #include "audio_streamview.h"
36 #include "automation_line.h"
37 #include "control_point.h"
38 #include "editor_regions.h"
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);
174 /** Select clicked_routeview, unless there are no currently selected
175 * tracks, in which case nothing will happen unless `force' is true.
178 Editor::set_selected_track_as_side_effect (bool force)
180 if (!clicked_routeview) {
184 if (!selection->tracks.empty()) {
185 if (!selection->selected (clicked_routeview)) {
186 selection->add (clicked_routeview);
190 selection->set (clicked_routeview);
195 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
198 case Selection::Toggle:
199 if (selection->selected (&view)) {
201 selection->remove (&view);
204 selection->add (&view);
209 if (!selection->selected (&view)) {
210 selection->add (&view);
215 selection->set (&view);
218 case Selection::Extend:
219 extend_selection_to_track (view);
225 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
227 if (!clicked_routeview) {
235 set_selected_track (*clicked_routeview, op, no_remove);
239 Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
241 if (!clicked_control_point) {
245 /* select this point and any others that it represents */
250 x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
251 x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
252 y1 = clicked_control_point->get_x() - 10;
253 y2 = clicked_control_point->get_y() + 10;
255 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
259 Editor::get_onscreen_tracks (TrackViewList& tvl)
261 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
262 if ((*i)->y_position() < _canvas_height) {
268 /** Call a slot for a given `basis' track and also for any track that is in the same
269 * active route group with a particular set of properties.
271 * @param sl Slot to call.
272 * @param basis Basis track.
273 * @param prop Properties that active edit groups must share to be included in the map.
277 Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, RouteGroup::Property prop) const
279 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
280 if (route_basis == 0) {
284 set<RouteTimeAxisView*> tracks;
285 tracks.insert (route_basis);
287 RouteGroup* group = route_basis->route()->route_group();
288 if (group && group->active_property (prop)) {
290 /* the basis is a member of an active route group, with the appropriate
291 properties; find other members */
293 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
294 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
295 if (v && v->route()->route_group() == group) {
302 uint32_t const sz = tracks.size ();
303 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
309 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
311 boost::shared_ptr<Playlist> pl;
312 vector<boost::shared_ptr<Region> > results;
314 boost::shared_ptr<Diskstream> ds;
316 if ((ds = tv.get_diskstream()) == 0) {
321 if (&tv == &basis->get_time_axis_view()) {
322 /* looking in same track as the original */
326 if ((pl = ds->playlist()) != 0) {
327 pl->get_equivalent_regions (basis->region(), results);
330 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
331 if ((marv = tv.view()->find_view (*ir)) != 0) {
332 all_equivs->push_back (marv);
338 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, RouteGroup::Property prop) const
340 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview(), prop);
342 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
344 equivalent_regions.push_back (basis);
348 Editor::get_equivalent_regions (RegionSelection & basis, RouteGroup::Property prop) const
350 RegionSelection equivalent;
352 for (RegionSelection::const_iterator i = basis.begin(); i != basis.end(); ++i) {
354 vector<RegionView*> eq;
357 sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
358 &(*i)->get_trackview(), prop
361 for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {
373 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
375 int region_count = 0;
377 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
379 RouteTimeAxisView* tatv;
381 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
383 boost::shared_ptr<Playlist> pl;
384 vector<boost::shared_ptr<Region> > results;
386 boost::shared_ptr<Diskstream> ds;
388 if ((ds = tatv->get_diskstream()) == 0) {
393 if ((pl = (ds->playlist())) != 0) {
394 pl->get_region_list_equivalent_regions (region, results);
397 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
398 if ((marv = tatv->view()->find_view (*ir)) != 0) {
411 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
413 vector<RegionView*> all_equivalent_regions;
416 if (!clicked_regionview || !clicked_routeview) {
421 button_release_can_deselect = false;
424 if (op == Selection::Toggle || op == Selection::Set) {
428 case Selection::Toggle:
430 if (selection->selected (clicked_regionview)) {
433 /* whatever was clicked was selected already; do nothing here but allow
434 the button release to deselect it
437 button_release_can_deselect = true;
441 if (button_release_can_deselect) {
443 /* just remove this one region, but only on a permitted button release */
445 selection->remove (clicked_regionview);
448 /* no more deselect action on button release till a new press
449 finds an already selected object.
452 button_release_can_deselect = false;
460 if (selection->selected (clicked_routeview)) {
461 get_equivalent_regions (clicked_regionview, all_equivalent_regions, RouteGroup::Select);
463 all_equivalent_regions.push_back (clicked_regionview);
466 /* add all the equivalent regions, but only on button press */
468 if (!all_equivalent_regions.empty()) {
472 selection->add (all_equivalent_regions);
478 if (!selection->selected (clicked_regionview)) {
479 get_equivalent_regions (clicked_regionview, all_equivalent_regions, RouteGroup::Select);
480 selection->set (all_equivalent_regions);
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;
588 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
589 RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
591 relevant_tracks.insert (r);
595 set<RouteTimeAxisView*> already_in_selection;
597 if (relevant_tracks.empty()) {
599 /* no tracks selected .. thus .. if the
600 regionview we're in isn't selected
601 (i.e. we're about to extend to it), then
602 find all tracks between the this one and
606 if (!selection->selected (entered_regionview)) {
608 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
612 /* add this track to the ones we will search */
614 relevant_tracks.insert (rtv);
616 /* find the track closest to this one that
617 already a selected region.
620 RouteTimeAxisView* closest = 0;
621 int distance = INT_MAX;
622 int key = rtv->route()->order_key ("editor");
624 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
626 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
628 if (artv && artv != rtv) {
630 pair<set<RouteTimeAxisView*>::iterator,bool> result;
632 result = already_in_selection.insert (artv);
635 /* newly added to already_in_selection */
637 int d = artv->route()->order_key ("editor");
641 if (abs (d) < distance) {
651 /* now add all tracks between that one and this one */
653 int okey = closest->route()->order_key ("editor");
659 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
660 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
661 if (artv && artv != rtv) {
663 int k = artv->route()->order_key ("editor");
665 if (k >= okey && k <= key) {
667 /* in range but don't add it if
668 it already has tracks selected.
669 this avoids odd selection
670 behaviour that feels wrong.
673 if (find (already_in_selection.begin(),
674 already_in_selection.end(),
675 artv) == already_in_selection.end()) {
677 relevant_tracks.insert (artv);
687 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
688 one that was clicked.
691 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
692 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
695 /* 4. convert to a vector of regions */
697 vector<RegionView*> regions;
699 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
702 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
703 regions.push_back (arv);
707 if (!regions.empty()) {
708 selection->add (regions);
719 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
721 vector<RegionView*> all_equivalent_regions;
723 get_regions_corresponding_to (region, all_equivalent_regions);
725 if (all_equivalent_regions.empty()) {
729 begin_reversible_command (_("set selected regions"));
732 case Selection::Toggle:
733 /* XXX this is not correct */
734 selection->toggle (all_equivalent_regions);
737 selection->set (all_equivalent_regions);
739 case Selection::Extend:
740 selection->add (all_equivalent_regions);
743 selection->add (all_equivalent_regions);
747 commit_reversible_command () ;
751 Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* sv, boost::weak_ptr<Region> weak_r)
754 boost::shared_ptr<Region> r (weak_r.lock());
760 if ((rv = sv->find_view (r)) == 0) {
764 /* don't reset the selection if its something other than
765 a single other region.
768 if (selection->regions.size() > 1) {
772 begin_reversible_command (_("set selected regions"));
776 commit_reversible_command () ;
782 Editor::track_selection_changed ()
784 switch (selection->tracks.size()){
788 set_selected_mixer_strip (*(selection->tracks.front()));
792 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
793 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
794 (*i)->set_selected (true);
796 (*i)->set_selected (false);
800 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
804 Editor::time_selection_changed ()
806 if (Profile->get_sae()) {
810 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
811 (*i)->hide_selection ();
814 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
815 (*i)->show_selection (selection->time);
818 if (selection->time.empty()) {
819 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
821 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
826 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
828 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
829 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
831 string accel_path = (*x)->get_accel_path ();
834 /* if there is an accelerator, it should always be sensitive
835 to allow for keyboard ops on entered regions.
838 bool known = ActionManager::lookup_entry (accel_path, key);
840 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
841 (*x)->set_sensitive (true);
843 (*x)->set_sensitive (have_selected_regions);
850 Editor::region_selection_changed ()
852 _regions->block_change_connection (true);
853 editor_regions_selection_changed_connection.block(true);
855 _regions->unselect_all ();
857 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
859 (*i)->set_selected_regionviews (selection->regions);
860 _regions->set_selected (selection->regions);
864 sensitize_the_right_region_actions (!selection->regions.empty());
866 _regions->block_change_connection (false);
867 editor_regions_selection_changed_connection.block(false);
871 Editor::point_selection_changed ()
873 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
874 (*i)->set_selected_points (selection->points);
879 Editor::select_all_in_track (Selection::Operation op)
881 list<Selectable *> touched;
883 if (!clicked_routeview) {
887 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
890 case Selection::Toggle:
891 selection->add (touched);
894 selection->set (touched);
896 case Selection::Extend:
897 /* meaningless, because we're selecting everything */
900 selection->add (touched);
906 Editor::select_all (Selection::Operation op)
908 list<Selectable *> touched;
910 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
911 if ((*iter)->hidden()) {
914 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
916 begin_reversible_command (_("select all"));
919 selection->add (touched);
921 case Selection::Toggle:
922 selection->add (touched);
925 selection->set (touched);
927 case Selection::Extend:
928 /* meaningless, because we're selecting everything */
931 commit_reversible_command ();
934 Editor::invert_selection_in_track ()
936 list<Selectable *> touched;
938 if (!clicked_routeview) {
942 clicked_routeview->get_inverted_selectables (*selection, touched);
943 selection->set (touched);
947 Editor::invert_selection ()
949 list<Selectable *> touched;
951 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
952 if ((*iter)->hidden()) {
955 (*iter)->get_inverted_selectables (*selection, touched);
958 selection->set (touched);
962 Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
964 list<Selectable*> touched;
965 list<Selectable*>::size_type n = 0;
966 TrackViewList touched_tracks;
968 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
969 if ((*iter)->hidden()) {
975 (*iter)->get_selectables (start, end, top, bot, touched);
977 if (n != touched.size()) {
978 touched_tracks.push_back (*iter);
982 if (touched.empty()) {
986 if (!touched_tracks.empty()) {
990 selection->add (touched_tracks);
992 case Selection::Toggle:
993 selection->toggle (touched_tracks);
996 selection->set (touched_tracks);
998 case Selection::Extend:
999 /* not defined yet */
1004 begin_reversible_command (_("select all within"));
1006 case Selection::Add:
1007 selection->add (touched);
1009 case Selection::Toggle:
1010 selection->toggle (touched);
1012 case Selection::Set:
1013 selection->set (touched);
1015 case Selection::Extend:
1016 /* not defined yet */
1020 commit_reversible_command ();
1022 return !touched.empty();
1026 Editor::set_selection_from_region ()
1028 if (selection->regions.empty()) {
1032 selection->set (selection->regions.start(), selection->regions.end_frame());
1033 if (!Profile->get_sae()) {
1034 set_mouse_mode (Editing::MouseRange, false);
1039 Editor::set_selection_from_punch()
1043 if ((location = _session->locations()->auto_punch_location()) == 0) {
1047 set_selection_from_range (*location);
1051 Editor::set_selection_from_loop()
1055 if ((location = _session->locations()->auto_loop_location()) == 0) {
1058 set_selection_from_range (*location);
1062 Editor::set_selection_from_range (Location& loc)
1064 begin_reversible_command (_("set selection from range"));
1065 selection->set (loc.start(), loc.end());
1066 commit_reversible_command ();
1068 if (!Profile->get_sae()) {
1069 set_mouse_mode (Editing::MouseRange, false);
1074 Editor::select_all_selectables_using_time_selection ()
1076 list<Selectable *> touched;
1078 if (selection->time.empty()) {
1082 nframes64_t start = selection->time[clicked_selection].start;
1083 nframes64_t end = selection->time[clicked_selection].end;
1085 if (end - start < 1) {
1091 if (selection->tracks.empty()) {
1094 ts = &selection->tracks;
1097 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1098 if ((*iter)->hidden()) {
1101 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1104 begin_reversible_command (_("select all from range"));
1105 selection->set (touched);
1106 commit_reversible_command ();
1111 Editor::select_all_selectables_using_punch()
1113 Location* location = _session->locations()->auto_punch_location();
1114 list<Selectable *> touched;
1116 if (location == 0 || (location->end() - location->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 (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1135 begin_reversible_command (_("select all from punch"));
1136 selection->set (touched);
1137 commit_reversible_command ();
1142 Editor::select_all_selectables_using_loop()
1144 Location* location = _session->locations()->auto_loop_location();
1145 list<Selectable *> touched;
1147 if (location == 0 || (location->end() - location->start() <= 1)) {
1154 if (selection->tracks.empty()) {
1157 ts = &selection->tracks;
1160 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1161 if ((*iter)->hidden()) {
1164 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1166 begin_reversible_command (_("select all from loop"));
1167 selection->set (touched);
1168 commit_reversible_command ();
1173 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1177 list<Selectable *> touched;
1180 begin_reversible_command (_("select all after cursor"));
1181 start = cursor->current_frame ;
1182 end = _session->current_end_frame();
1184 if (cursor->current_frame > 0) {
1185 begin_reversible_command (_("select all before cursor"));
1187 end = cursor->current_frame - 1;
1196 if (selection->tracks.empty()) {
1199 ts = &selection->tracks;
1202 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1203 if ((*iter)->hidden()) {
1206 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1208 selection->set (touched);
1209 commit_reversible_command ();
1213 Editor::select_all_selectables_using_edit (bool after)
1217 list<Selectable *> touched;
1220 begin_reversible_command (_("select all after edit"));
1221 start = get_preferred_edit_position();
1222 end = _session->current_end_frame();
1224 if ((end = get_preferred_edit_position()) > 1) {
1225 begin_reversible_command (_("select all before edit"));
1236 if (selection->tracks.empty()) {
1239 ts = &selection->tracks;
1242 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1243 if ((*iter)->hidden()) {
1246 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1248 selection->set (touched);
1249 commit_reversible_command ();
1253 Editor::select_all_selectables_between (bool /*within*/)
1257 list<Selectable *> touched;
1259 if (!get_edit_op_range (start, end)) {
1265 if (selection->tracks.empty()) {
1268 ts = &selection->tracks;
1271 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1272 if ((*iter)->hidden()) {
1275 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1278 selection->set (touched);
1282 Editor::select_range_between ()
1287 if (!get_edit_op_range (start, end)) {
1291 set_mouse_mode (MouseRange);
1292 selection->set (start, end);
1296 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1301 /* in range mode, use any existing selection */
1303 if (mouse_mode == MouseRange && !selection->time.empty()) {
1304 /* we know that these are ordered */
1305 start = selection->time.start();
1306 end = selection->time.end_frame();
1310 if (!mouse_frame (m, ignored)) {
1311 /* mouse is not in a canvas, try playhead+selected marker.
1312 this is probably most true when using menus.
1315 if (selection->markers.empty()) {
1319 start = selection->markers.front()->position();
1320 end = _session->audible_frame();
1324 switch (_edit_point) {
1325 case EditAtPlayhead:
1326 if (selection->markers.empty()) {
1327 /* use mouse + playhead */
1329 end = _session->audible_frame();
1331 /* use playhead + selected marker */
1332 start = _session->audible_frame();
1333 end = selection->markers.front()->position();
1338 /* use mouse + selected marker */
1339 if (selection->markers.empty()) {
1341 end = _session->audible_frame();
1343 start = selection->markers.front()->position();
1348 case EditAtSelectedMarker:
1349 /* use mouse + selected marker */
1350 if (selection->markers.empty()) {
1352 MessageDialog win (_("No edit range defined"),
1357 win.set_secondary_text (
1358 _("the edit point is Selected Marker\nbut there is no selected marker."));
1361 win.set_default_response (RESPONSE_CLOSE);
1362 win.set_position (Gtk::WIN_POS_MOUSE);
1367 return false; // NO RANGE
1369 start = selection->markers.front()->position();
1383 /* turn range into one delimited by start...end,
1393 Editor::deselect_all ()
1395 selection->clear ();
1399 Editor::select_range_around_region (RegionView* rv)
1401 selection->set (&rv->get_time_axis_view());
1403 selection->time.clear ();
1404 boost::shared_ptr<Region> r = rv->region ();
1405 selection->set (r->position(), r->position() + r->length());